mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-02 02:42:28 +00:00
86 lines
4.7 KiB
JavaScript
86 lines
4.7 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { tombstoneFixture, videoEvent, ids, author, filteredStorageKey } from './test-helpers/storage-tombstone-fixture.mjs';
|
|
|
|
const cachedVideo = (id, extra = {}) => ({ id, pubkey: author, videoRootId: id, created_at: 100, title: id, url: 'https://example.invalid/video.mp4', ...extra });
|
|
const assertSnapshot = (f, expected) => {
|
|
assert.deepEqual(ids([...f.service.getVideosMap().values()]), expected);
|
|
assert.deepEqual(ids(f.notifications.at(-1).videos), expected);
|
|
assert.deepEqual(ids(f.updates.at(-1).videos), expected);
|
|
assert.deepEqual(ids(f.persisted()), expected);
|
|
};
|
|
|
|
test('different-ID tombstone removes every obsolete cached version and preserves unrelated live content', async t => {
|
|
const f = tombstoneFixture(t); await f.load();
|
|
await f.ingest(videoEvent('first', 100));
|
|
await f.ingest(videoEvent('edit', 150), videoEvent('other', 100, { root: 'other', pubkey: 'b'.repeat(64) }));
|
|
await f.ingest(videoEvent('delete', 200, { deleted: true }));
|
|
assertSnapshot(f, ['other']);
|
|
assert.deepEqual(ids(f.updates.at(-1).deleted), ['delete']);
|
|
await f.ingest(videoEvent('late', 120));
|
|
assertSnapshot(f, ['other']);
|
|
});
|
|
|
|
test('deletion-only empty result persists and second consumer receives no optimistic resurrection', async t => {
|
|
const f = tombstoneFixture(t); await f.load(); await f.ingest(videoEvent('first', 100));
|
|
await f.ingest(videoEvent('delete', 200, { deleted: true }));
|
|
assertSnapshot(f, []);
|
|
const count = f.notifications.length;
|
|
await f.load();
|
|
assert.deepEqual(f.notifications.slice(count).map(entry => ids(entry.videos)), [[]]);
|
|
assert.deepEqual(f.persisted(), []);
|
|
});
|
|
|
|
for (const viewer of ['public', 'author']) {
|
|
test(`persistent deleted and invalid entries are rejected before ${viewer} access bypass`, async t => {
|
|
const f = tombstoneFixture(t, { persisted: [cachedVideo('deleted', { deleted: true }), cachedVideo('invalid', { invalid: true }), cachedVideo('live')] });
|
|
if (viewer === 'author') f.client.pubkey = author;
|
|
const initial = await f.load();
|
|
assert.deepEqual(ids(initial), ['live']);
|
|
assert.equal(f.notifications.some(entry => entry.videos.some(video => video.deleted || video.invalid)), false);
|
|
assert.deepEqual(ids([...f.service.getVideosMap().values()]), ['live']);
|
|
assert.deepEqual(ids(f.persisted()), ['live']);
|
|
});
|
|
}
|
|
|
|
test('all-ineligible persistent cache is cleared even when active snapshot is empty', async t => {
|
|
const f = tombstoneFixture(t, { persisted: [cachedVideo('deleted', { deleted: true }), cachedVideo('invalid', { invalid: true })] });
|
|
assert.deepEqual(await f.load(), []);
|
|
assert.deepEqual(f.persisted(), []);
|
|
assert.deepEqual(f.notifications.map(entry => ids(entry.videos)), [[]]);
|
|
});
|
|
|
|
test('stale nondeleted persistent copies honor known tombstone while strictly newer and unrelated entries survive', async t => {
|
|
const f = tombstoneFixture(t); await f.load();
|
|
await f.ingest(videoEvent('old', 100));
|
|
const stale = f.persisted()[0];
|
|
await f.ingest(videoEvent('delete', 200, { deleted: true }));
|
|
await f.ingest(videoEvent('newer', 300), videoEvent('other', 150, { root: 'other' }));
|
|
// A stale storage snapshot contains an independent, still-nondeleted copy.
|
|
localStorage.setItem(filteredStorageKey, JSON.stringify([stale, ...f.persisted()]));
|
|
const start = f.notifications.length;
|
|
await f.load();
|
|
assert.equal(f.notifications.slice(start).some(entry => entry.videos.some(video => video.id === 'old')), false);
|
|
assertSnapshot(f, ['newer', 'other']);
|
|
});
|
|
|
|
test('direct cache API never reintroduces deleted invalid or tombstone-covered copies', async t => {
|
|
const f = tombstoneFixture(t); await f.load(); await f.ingest(videoEvent('old', 100));
|
|
const stale = f.persisted()[0];
|
|
await f.ingest(videoEvent('delete', 200, { deleted: true }));
|
|
f.service.cacheVideos([stale, cachedVideo('deleted', { deleted: true }), cachedVideo('invalid', { invalid: true }), cachedVideo('live')]);
|
|
assert.deepEqual(ids([...f.service.getVideosMap().values()]), ['live']);
|
|
});
|
|
|
|
test('legacy tombstone cleanup retains other author with same d-tag and strictly newer content', async t => {
|
|
const f = tombstoneFixture(t); await f.load();
|
|
const legacy = { root: `LEGACY:${author}:same`, dTag: 'same' };
|
|
const other = { root: `LEGACY:${'b'.repeat(64)}:same`, dTag: 'same', pubkey: 'b'.repeat(64) };
|
|
await f.ingest(videoEvent('old', 100, legacy), videoEvent('other-author', 100, other));
|
|
await f.ingest(videoEvent('delete', 200, { ...legacy, deleted: true }));
|
|
assertSnapshot(f, ['other-author']);
|
|
await f.ingest(videoEvent('newer', 300, legacy));
|
|
await f.ingest(videoEvent('delete-replayed', 200, { ...legacy, deleted: true }));
|
|
assertSnapshot(f, ['newer', 'other-author']);
|
|
});
|