mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
loadUserVideos rendered only the live relay fetch, and the render REPLACES the grid container. So when a relay holding a creator's video transiently failed or EOSE'd late, that video disappeared from the wall even though it was already known in memory/cache — the "channel doesn't pull in all of a creator's videos" bug (#20, symptom 1). Union the live events with the already-known author events (mergeChannelVideoSources, live wins on id collision) before building the renderable list, so the rendered set is a superset and can't shrink on a transient relay gap. Existing dedupe-by-root + access/delete filtering still decide precedence downstream, so newer versions and deletions still win. Helper + tests live in channelProfileVideos.js (channelProfile.js is at its size cap); the call site stays net-zero. Streaming/first-relay-wins render is still the separate 17d UX follow-up. Regression: tests/channel-video-merge.test.mjs. Co-Authored-By: Claude Opus 4.8 <[email protected]>
53 lines
2.2 KiB
JavaScript
53 lines
2.2 KiB
JavaScript
// Regression (#20): the channel grid render replaces the container with the live
|
|
// fetch, so a transiently-failing relay produced a smaller set and previously-
|
|
// known videos vanished ("some of a creator's videos are missing"). The live
|
|
// fetch must be unioned with already-known events so the grid never shrinks.
|
|
|
|
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import { mergeChannelVideoSources } from "../js/channelProfileVideos.js";
|
|
|
|
const ev = (id, extra = {}) => ({ id, kind: 30078, ...extra });
|
|
|
|
test("union is a superset of both live and known events", () => {
|
|
const live = [ev("a"), ev("b")];
|
|
const known = [ev("b"), ev("c"), ev("d")];
|
|
|
|
const merged = mergeChannelVideoSources(live, known);
|
|
const ids = merged.map((e) => e.id).sort();
|
|
|
|
assert.deepEqual(ids, ["a", "b", "c", "d"], "all unique ids from both sources");
|
|
});
|
|
|
|
test("a known video missing from the live fetch still appears (the bug)", () => {
|
|
// The live fetch this load only returned one video; the other is known in
|
|
// memory (e.g. from a prior load / the main feed). It must not disappear.
|
|
const live = [ev("only-live")];
|
|
const known = [ev("only-live"), ev("dropped-by-slow-relay")];
|
|
|
|
const merged = mergeChannelVideoSources(live, known);
|
|
const ids = merged.map((e) => e.id).sort();
|
|
|
|
assert.deepEqual(ids, ["dropped-by-slow-relay", "only-live"]);
|
|
});
|
|
|
|
test("live wins on id collision (freshest copy)", () => {
|
|
const live = [ev("x", { created_at: 200, source: "live" })];
|
|
const known = [ev("x", { created_at: 100, source: "cache" })];
|
|
|
|
const merged = mergeChannelVideoSources(live, known);
|
|
assert.equal(merged.length, 1);
|
|
assert.equal(merged[0].source, "live", "live copy must win the dedupe");
|
|
});
|
|
|
|
test("preserves id-less entries and tolerates non-array / junk input", () => {
|
|
const live = [ev("a"), { kind: 30078 /* no id */ }, null, "junk"];
|
|
const merged = mergeChannelVideoSources(live, undefined);
|
|
const withId = merged.filter((e) => e && e.id === "a");
|
|
const withoutId = merged.filter((e) => e && typeof e === "object" && !e.id);
|
|
|
|
assert.equal(withId.length, 1);
|
|
assert.equal(withoutId.length, 1, "id-less event kept, not dropped");
|
|
assert.deepEqual(mergeChannelVideoSources(null, null), []);
|
|
});
|