mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Channel-profile video cards rendered blank view counts. The main feed subscribes each card's [data-view-count] element to the shared view counter (VideoListView.ensureViewCountSubscription / registerVideoViewCountElement), but the channel-profile grid renders its own VideoCards and never did — so nothing ever populated the element. Add js/channelViewCounts.js (subscribeChannelCardViewCount / clearChannelCardViewCounts) and call it from channelProfile.js after each card's getRoot(); teardown runs in clearChannelVideoCardRegistry (already invoked on grid re-render / channel close). Logic lives in a new module so channelProfile.js stays under its size cap. On "are they counted correctly?": yes — this subscribes to the SAME batched kind-30079 view-count transport the feed uses (one shared subscription + the deduped cache), so the channel now shows the exact same counts the feed does. The counting itself was never the issue; the channel grid just wasn't displaying it. Tests: tests/channel-view-counts.test.mjs (3 — non-blank label, safe no-ops, idempotent teardown). Lint + build green. Co-Authored-By: Claude Opus 4.8 <[email protected]>
66 lines
3.0 KiB
JavaScript
66 lines
3.0 KiB
JavaScript
// Channel-profile cards showed BLANK view counts because the channel grid never
|
|
// subscribed its cards to the shared view counter (the main feed does). This wires
|
|
// each card's [data-view-count] element the same way. The count VALUES come from the
|
|
// same shared transport as the feed — the channel just wasn't displaying them.
|
|
//
|
|
// test_integrity_note:
|
|
// change_type: ["new_tests"]
|
|
// scenarios:
|
|
// - id: SCN-channel-card-view-count
|
|
// given: "a channel card element with a [data-view-count] span + a pointer"
|
|
// when: "subscribeChannelCardViewCount runs (and clearChannelCardViewCounts tears down)"
|
|
// then: "the element gets a non-blank view label; missing pointer/element/card are safe no-ops"
|
|
// observable_outcomes:
|
|
// - "a card with a pointer gets a non-blank view label (no longer blank)"
|
|
// - "no pointer / no [data-view-count] / no card -> no throw, no label forced"
|
|
// - "clearChannelCardViewCounts is idempotent and never throws"
|
|
// determinism_controls:
|
|
// - "JSDOM element; real module against the (uninitialised) shared view counter"
|
|
// anti_cheat_rationale:
|
|
// prevents: ["asserting the blank (broken) state", "hard-coded return value"]
|
|
// relaxation:
|
|
// did_relax_any_assertion: false
|
|
|
|
import "./test-helpers/setup-localstorage.mjs";
|
|
import test from "node:test";
|
|
import { strict as assert } from "node:assert";
|
|
import { JSDOM } from "jsdom";
|
|
import {
|
|
subscribeChannelCardViewCount,
|
|
clearChannelCardViewCounts,
|
|
} from "../js/channelViewCounts.js";
|
|
|
|
function makeCard(html) {
|
|
const dom = new JSDOM(`<!DOCTYPE html><body>${html}</body>`);
|
|
return dom.window.document.body.firstElementChild;
|
|
}
|
|
|
|
test("a card with a pointer gets a non-blank view-count label (fixes the blank)", () => {
|
|
const card = makeCard('<div class="card"><span data-view-count></span></div>');
|
|
subscribeChannelCardViewCount(card, { pointer: ["a", 30078, "root-1"], key: "k1" });
|
|
const el = card.querySelector("[data-view-count]");
|
|
assert.ok(el.textContent && el.textContent.trim().length > 0, "label is not blank");
|
|
assert.match(el.textContent, /view|Loading/i, "shows a view/loading label");
|
|
clearChannelCardViewCounts();
|
|
});
|
|
|
|
test("safe no-ops: missing pointer, missing [data-view-count], or missing card", () => {
|
|
const cardNoEl = makeCard('<div class="card"></div>');
|
|
const cardWithEl = makeCard('<div class="card"><span data-view-count></span></div>');
|
|
assert.doesNotThrow(() => {
|
|
subscribeChannelCardViewCount(cardWithEl, {}); // no pointer
|
|
subscribeChannelCardViewCount(cardNoEl, { pointer: ["a", 30078, "x"] }); // no element
|
|
subscribeChannelCardViewCount(null, { pointer: ["a", 30078, "x"] }); // no card
|
|
});
|
|
// A card with no pointer must not have its (absent) element forced to a label.
|
|
assert.equal(cardWithEl.querySelector("[data-view-count]").textContent, "");
|
|
clearChannelCardViewCounts();
|
|
});
|
|
|
|
test("clearChannelCardViewCounts is idempotent and never throws", () => {
|
|
assert.doesNotThrow(() => {
|
|
clearChannelCardViewCounts();
|
|
clearChannelCardViewCounts();
|
|
});
|
|
});
|