mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 02:44:02 +00:00
397 lines
16 KiB
JavaScript
397 lines
16 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { readFile } from 'node:fs/promises';
|
|
|
|
import {
|
|
createBhoteKoshiEmbeddedMedia,
|
|
createTrimmedYouTubePlayback,
|
|
embeddedMediaFrameUrl,
|
|
publicEmbeddedMediaUrl,
|
|
resolveEmbeddedMediaSource,
|
|
} from './bhoteKoshiEmbeddedMedia.js';
|
|
|
|
test('Pinokio fallback never creates provider DOM or loads SDKs', async () => {
|
|
const unexpected = () => { throw new Error('Provider resource allocated in Pinokio'); };
|
|
const media = createBhoteKoshiEmbeddedMedia({
|
|
viewer: {},
|
|
documentRef: { createElement: unexpected },
|
|
globalRef: {
|
|
navigator: { userAgent: 'Mozilla/5.0 Chrome/140.0.0.0 Safari/537.36 Pinokio/8.0.40' },
|
|
setTimeout: unexpected,
|
|
requestAnimationFrame: unexpected,
|
|
},
|
|
facebookLoader: unexpected,
|
|
youtubeLoader: unexpected,
|
|
xLoader: unexpected,
|
|
});
|
|
for (const sourceUrl of [
|
|
'https://www.youtube.com/watch?v=abcdefghijk',
|
|
'https://www.facebook.com/watch/?v=123456789',
|
|
'https://x.com/example/status/123456789',
|
|
]) {
|
|
const options = { observation: { media: { sourceUrl } }, autoplay: true };
|
|
assert.equal(media.warm(options), false, 'no hidden preload');
|
|
assert.equal(media.show(options), false, 'retain the existing fallback card');
|
|
assert.equal(media.play(), false);
|
|
assert.equal(media.pause(), false);
|
|
media.hide();
|
|
}
|
|
media.destroy();
|
|
media.hide();
|
|
await Promise.resolve();
|
|
});
|
|
|
|
test('ordinary browsers retain real preloads on the same launcher URL', () => {
|
|
for (const userAgent of [
|
|
'Mozilla/5.0 Chrome/140.0.0.0 Safari/537.36',
|
|
'Mozilla/5.0 Version/18.0 Safari/605.1.15',
|
|
'Mozilla/5.0 Electron/38.0.0',
|
|
'',
|
|
]) {
|
|
const { media, root } = preloadFixture({ globalRef: {
|
|
navigator: { userAgent }, location: { href: 'http://127.0.0.1:42003/' },
|
|
} });
|
|
assert.equal(media.warm({ observation: { media: {
|
|
sourceUrl: 'https://www.youtube.com/watch?v=abcdefghijk',
|
|
} } }), true);
|
|
assert.equal(root.children.length, 1);
|
|
media.pause();
|
|
assert.equal(root.children.length, 0);
|
|
media.destroy();
|
|
}
|
|
});
|
|
|
|
function trimmedPlaybackFixture() {
|
|
let now = 0;
|
|
let nextId = 0;
|
|
const timers = new Map();
|
|
const globalRef = {
|
|
setTimeout(fn, delay) { const id = ++nextId; timers.set(id, { at: now + delay, fn }); return id; },
|
|
clearTimeout(id) { timers.delete(id); },
|
|
};
|
|
const advance = (ms) => {
|
|
const until = now + ms;
|
|
while (true) {
|
|
const entry = [...timers].filter(([, item]) => item.at <= until).sort((a, b) => a[1].at - b[1].at)[0];
|
|
if (!entry) break;
|
|
const [id, item] = entry; timers.delete(id); now = item.at; item.fn();
|
|
}
|
|
now = until;
|
|
};
|
|
let events;
|
|
const calls = [];
|
|
let time = 0;
|
|
let state = -1;
|
|
const player = {
|
|
mute: () => calls.push('mute'), playVideo: () => calls.push('play'),
|
|
pauseVideo: () => calls.push('pause'), destroy: () => calls.push('destroy'),
|
|
getCurrentTime: () => time,
|
|
getPlayerState: () => state,
|
|
};
|
|
const api = { Player: class { constructor(_iframe, options) { events = options.events; return player; } } };
|
|
const statuses = [];
|
|
const session = createTrimmedYouTubePlayback({ iframe: {}, endAtSec: 7, globalRef,
|
|
loadApi: () => api, onStatus: (phase) => statuses.push(phase) });
|
|
return { session, advance, calls, timers, statuses, player, get events() { return events; }, setTime(value) { time = value; }, setState(value) { state = value; } };
|
|
}
|
|
|
|
test('trimmed YouTube reconciles already-playing READY and missed PLAYING callbacks', async () => {
|
|
for (const alreadyPlaying of [true, false]) {
|
|
const f = trimmedPlaybackFixture();
|
|
await Promise.resolve(); await Promise.resolve();
|
|
if (alreadyPlaying) { f.setState(1); f.setTime(1); }
|
|
f.events.onReady({ target: f.player });
|
|
if (!alreadyPlaying) { f.setState(1); f.setTime(1); f.advance(100); }
|
|
f.setTime(6); f.advance(5000);
|
|
assert.deepEqual(f.session.getState(), { phase: 'playing', currentTime: 6 });
|
|
f.setTime(7); f.advance(100);
|
|
assert.deepEqual(f.session.getState(), { phase: 'completed', currentTime: 7 });
|
|
assert.deepEqual(f.statuses, ['completed']);
|
|
assert.equal(f.timers.size, 0);
|
|
f.session.destroy();
|
|
}
|
|
});
|
|
|
|
test('trimmed YouTube accepts ENDED before PLAYING and never replays a completed READY', async () => {
|
|
for (const endedCallback of [true, false]) {
|
|
const f = trimmedPlaybackFixture();
|
|
await Promise.resolve(); await Promise.resolve();
|
|
f.setState(0); f.setTime(7);
|
|
if (endedCallback) f.events.onStateChange({ data: 0, target: f.player });
|
|
f.events.onReady({ target: f.player });
|
|
assert.deepEqual(f.session.getState(), { phase: 'completed', currentTime: 7 });
|
|
assert.deepEqual(f.calls, ['pause']);
|
|
assert.deepEqual(f.statuses, ['completed']);
|
|
assert.equal(f.timers.size, 0);
|
|
f.session.destroy();
|
|
}
|
|
});
|
|
|
|
test('trimmed YouTube waits through delayed startup, stops at source 0:07, and releases its timers', async () => {
|
|
const f = trimmedPlaybackFixture();
|
|
await Promise.resolve(); await Promise.resolve();
|
|
f.advance(3000);
|
|
assert.equal(f.session.getState().phase, 'starting');
|
|
f.events.onReady({ target: f.player });
|
|
f.events.onStateChange({ data: 1 });
|
|
f.setTime(4); f.advance(4000);
|
|
assert.equal(f.session.getState().phase, 'playing', 'seven wall-clock seconds do not truncate a delayed clip');
|
|
f.setTime(7); f.advance(100);
|
|
assert.deepEqual(f.session.getState(), { phase: 'completed', currentTime: 7 });
|
|
assert.deepEqual(f.statuses, ['completed']);
|
|
assert.equal(f.timers.size, 0);
|
|
assert.equal(f.calls.at(-1), 'pause');
|
|
f.session.destroy();
|
|
});
|
|
|
|
test('trimmed YouTube bounds blocked, failed, stalled and never-started playback', async () => {
|
|
for (const outcome of ['blocked', 'unavailable', 'timeout', 'stalled']) {
|
|
const f = trimmedPlaybackFixture();
|
|
await Promise.resolve(); await Promise.resolve();
|
|
if (outcome === 'blocked') f.events.onAutoplayBlocked();
|
|
else if (outcome === 'unavailable') f.events.onError();
|
|
else if (outcome === 'stalled') { f.events.onStateChange({ data: 1 }); f.advance(12000); }
|
|
else f.advance(5000);
|
|
assert.equal(f.session.getState().phase, outcome === 'stalled' ? 'timeout' : outcome);
|
|
assert.equal(f.timers.size, 0);
|
|
const calls = [...f.calls];
|
|
f.events.onReady({ target: f.player });
|
|
f.events.onStateChange({ data: 1 });
|
|
assert.deepEqual(f.calls, calls, 'late provider callbacks cannot restart a terminal attempt');
|
|
f.session.destroy();
|
|
}
|
|
});
|
|
|
|
test('trimmed YouTube teardown revokes pending SDK and player callbacks', async () => {
|
|
const f = trimmedPlaybackFixture();
|
|
await Promise.resolve(); await Promise.resolve();
|
|
f.session.destroy();
|
|
f.events.onReady({ target: f.player });
|
|
f.events.onStateChange({ data: 1 });
|
|
f.events.onError(); f.advance(20000);
|
|
assert.deepEqual(f.calls, ['destroy']);
|
|
assert.deepEqual(f.statuses, []);
|
|
assert.equal(f.timers.size, 0);
|
|
let constructCount = 0;
|
|
let resolveApi;
|
|
const session = createTrimmedYouTubePlayback({ iframe: {}, endAtSec: 7,
|
|
loadApi: () => new Promise((resolve) => { resolveApi = resolve; }) });
|
|
await Promise.resolve();
|
|
session.destroy();
|
|
resolveApi({ Player: class { constructor() { constructCount++; } } });
|
|
await Promise.resolve(); await Promise.resolve();
|
|
assert.equal(constructCount, 0);
|
|
});
|
|
|
|
test('pausing YouTube removes its frame and rejects a late load from the stopped generation', () => {
|
|
const nodes = [];
|
|
class Element extends EventTarget {
|
|
constructor(tag) { super(); this.tag = tag; this.children = []; this.dataset = {}; this.classList = { add() {}, remove() {} }; nodes.push(this); }
|
|
setAttribute() {}
|
|
append(...children) { for (const child of children) { child.parent = this; this.children.push(child); } }
|
|
remove() { if (this.parent) this.parent.children = this.parent.children.filter((child) => child !== this); this.parent = null; }
|
|
}
|
|
const documentRef = {
|
|
body: new Element('body'),
|
|
createElement: (tag) => new Element(tag),
|
|
createElementNS: (_, tag) => new Element(tag),
|
|
};
|
|
const media = createBhoteKoshiEmbeddedMedia({ viewer: {}, documentRef, globalRef: {} });
|
|
const options = { observation: { title: 'Clip', media: { sourceUrl: 'https://youtu.be/DbqRexFxv3k' } }, anchor: {}, autoplay: true };
|
|
assert.equal(media.show(options), true);
|
|
const frame = nodes.find((node) => node.tag === 'iframe');
|
|
const card = nodes.find((node) => node.tag === 'section');
|
|
assert.ok(card.parent);
|
|
assert.equal(media.pause(), true);
|
|
assert.equal(card.parent, null);
|
|
frame.dispatchEvent(new Event('load'));
|
|
assert.equal(card.parent, null);
|
|
assert.equal(media.show(options), true, 'an explicit replay creates a fresh player');
|
|
media.destroy();
|
|
assert.equal(documentRef.body.children.length, 0);
|
|
});
|
|
|
|
test('resolves supported embedded callout providers from canonical public URLs', () => {
|
|
assert.deepEqual(
|
|
resolveEmbeddedMediaSource('https://www.youtube.com/watch?v=DbqRexFxv3k'),
|
|
{
|
|
provider: 'youtube',
|
|
id: 'DbqRexFxv3k',
|
|
url: 'https://www.youtube.com/watch?v=DbqRexFxv3k',
|
|
},
|
|
);
|
|
assert.equal(
|
|
resolveEmbeddedMediaSource('https://www.facebook.com/reel/1571491657757829').provider,
|
|
'facebook',
|
|
);
|
|
assert.deepEqual(
|
|
resolveEmbeddedMediaSource('https://x.com/Indowatchosint/status/2092640554568007958'),
|
|
{
|
|
provider: 'x',
|
|
id: '2092640554568007958',
|
|
url: 'https://x.com/Indowatchosint/status/2092640554568007958',
|
|
},
|
|
);
|
|
assert.equal(
|
|
resolveEmbeddedMediaSource('https://twitter.com/Indowatchosint/status/2092640554568007958').provider,
|
|
'x',
|
|
);
|
|
assert.equal(
|
|
resolveEmbeddedMediaSource('https://www.youtube.com/shorts/DbqRexFxv3k').id,
|
|
'DbqRexFxv3k',
|
|
);
|
|
});
|
|
|
|
test('rejects deceptive hosts, non-post X links, private targets, and iframe markup', () => {
|
|
for (const value of [
|
|
'https://x.com.evil.example/user/status/2092640554568007958',
|
|
'https://x.com/Indowatchosint',
|
|
'https://youtube.com.evil.example/watch?v=DbqRexFxv3k',
|
|
'http://www.youtube.com/watch?v=DbqRexFxv3k',
|
|
'https://localhost/video.mp4',
|
|
'<iframe src="https://x.com/user/status/2092640554568007958"></iframe>',
|
|
]) {
|
|
assert.equal(resolveEmbeddedMediaSource(value), null, value);
|
|
}
|
|
assert.equal(publicEmbeddedMediaUrl('https://user:[email protected]/name/status/123'), null);
|
|
});
|
|
|
|
test('builds privacy-aware provider frames and keeps X on its widget runtime', () => {
|
|
const youtube = resolveEmbeddedMediaSource('https://youtu.be/DbqRexFxv3k');
|
|
const youtubeFrame = new URL(embeddedMediaFrameUrl(youtube, { autoplay: true }));
|
|
assert.equal(youtubeFrame.hostname, 'www.youtube-nocookie.com');
|
|
assert.equal(youtubeFrame.pathname, '/embed/DbqRexFxv3k');
|
|
assert.equal(youtubeFrame.searchParams.get('autoplay'), '1');
|
|
assert.equal(youtubeFrame.searchParams.get('mute'), '1');
|
|
|
|
const timestampedFrame = new URL(embeddedMediaFrameUrl(youtube, {
|
|
autoplay: true,
|
|
startAtSec: 26,
|
|
}));
|
|
assert.equal(timestampedFrame.searchParams.get('start'), '26');
|
|
|
|
const facebook = resolveEmbeddedMediaSource('https://www.facebook.com/watch/?v=456');
|
|
const facebookFrame = new URL(embeddedMediaFrameUrl(facebook, { autoplay: false }));
|
|
assert.equal(facebookFrame.hostname, 'www.facebook.com');
|
|
assert.equal(facebookFrame.pathname, '/plugins/video.php');
|
|
assert.equal(facebookFrame.searchParams.get('href'), facebook.url);
|
|
assert.equal(facebookFrame.searchParams.get('autoplay'), 'false');
|
|
|
|
const x = resolveEmbeddedMediaSource('https://x.com/Indowatchosint/status/2092640554568007958');
|
|
assert.equal(embeddedMediaFrameUrl(x), null);
|
|
});
|
|
|
|
test('Mailung playback stops at source timestamp 0:07 without changing other clips', async () => {
|
|
const event = JSON.parse(await readFile(new URL('../../public/events/bhote-koshi-2026/event.json', import.meta.url), 'utf8'));
|
|
const bounded = event.evidenceSpine.filter(point => point.media?.embedEndAtSec != null);
|
|
assert.deepEqual(bounded.map(point => point.id), ['mailung-bazzar']);
|
|
const media = bounded[0].media;
|
|
assert.equal(media.embedEndAtSec, 7);
|
|
const source = resolveEmbeddedMediaSource(media.sourceUrl);
|
|
for (const autoplay of [false, true]) {
|
|
const url = new URL(embeddedMediaFrameUrl(source, {
|
|
autoplay, startAtSec: media.clipInSec, endAtSec: media.embedEndAtSec,
|
|
}));
|
|
assert.equal(url.searchParams.get('end'), '7');
|
|
}
|
|
for (const endAtSec of [undefined, null, NaN, Infinity, -1, 0, 3]) {
|
|
const url = new URL(embeddedMediaFrameUrl(source, {startAtSec: 3, endAtSec}));
|
|
assert.equal(url.searchParams.has('end'), false);
|
|
}
|
|
});
|
|
|
|
function preloadFixture(options = {}) {
|
|
class Element extends EventTarget {
|
|
constructor(tag) {
|
|
super(); this.tag = tag; this.children = []; this.dataset = {};
|
|
this.classList = { add() {}, remove() {}, contains() { return false; } };
|
|
}
|
|
setAttribute() {}
|
|
removeAttribute() {}
|
|
append(...children) {
|
|
for (const child of children) { child.remove(); child.parent = this; this.children.push(child); }
|
|
}
|
|
remove() {
|
|
if (this.parent) this.parent.children = this.parent.children.filter(child => child !== this);
|
|
this.parent = null;
|
|
}
|
|
}
|
|
const documentRef = {
|
|
body: new Element('body'),
|
|
createElement: tag => new Element(tag),
|
|
createElementNS: (_, tag) => new Element(tag),
|
|
};
|
|
const media = createBhoteKoshiEmbeddedMedia({ viewer: {}, documentRef, globalRef: {}, ...options });
|
|
return { media, root: documentRef.body.children[0] };
|
|
}
|
|
|
|
for (const operation of ['pause', 'hide', 'destroy']) {
|
|
test(`${operation} removes a hidden YouTube preload`, () => {
|
|
const { media, root } = preloadFixture();
|
|
media.warm({ sourceUrl: 'https://youtu.be/DbqRexFxv3k' });
|
|
assert.equal(root.children.length, 1);
|
|
media[operation]();
|
|
assert.equal(root.children.length, 0);
|
|
media.destroy();
|
|
});
|
|
}
|
|
|
|
test('camera updates retain a preload until the visible player loads', () => {
|
|
const { media, root } = preloadFixture();
|
|
const observation = { media: { sourceUrl: 'https://youtu.be/DbqRexFxv3k' } };
|
|
media.warm({ observation });
|
|
const frame = root.children[0];
|
|
media.hide({ preserveWarm: true });
|
|
media.warm({ observation });
|
|
assert.equal(root.children[0], frame);
|
|
assert.equal(media.show({ observation, anchor: {} }), true);
|
|
assert.equal(frame.parent, root, 'keep the preload while the visible player starts');
|
|
const card = root.children.find(node => node.tag === 'section');
|
|
const body = card.children.find(node => node.className === 'bhote-embedded-callout-body');
|
|
const player = body.children.find(node => node.className === 'bhote-embedded-callout-player');
|
|
player.children.find(node => node.tag === 'iframe').dispatchEvent(new Event('load'));
|
|
assert.equal(frame.parent, null, 'visible player readiness releases the preload');
|
|
media.destroy();
|
|
assert.equal(root.children.length, 0);
|
|
});
|
|
|
|
test('hiding revokes a pending Facebook SDK before it can mount or subscribe', async () => {
|
|
let resolveApi;
|
|
const calls = [];
|
|
const { media, root } = preloadFixture({
|
|
facebookLoader: () => new Promise(resolve => { resolveApi = resolve; }),
|
|
});
|
|
media.warm({ sourceUrl: 'https://www.facebook.com/reel/1571491657757829' });
|
|
assert.equal(root.children.length, 1);
|
|
media.hide();
|
|
assert.equal(root.children.length, 0);
|
|
resolveApi({ Event: { subscribe() { calls.push('subscribe'); } }, XFBML: { parse() { calls.push('parse'); } } });
|
|
await Promise.resolve(); await Promise.resolve();
|
|
assert.deepEqual(calls, []);
|
|
media.destroy();
|
|
});
|
|
|
|
test('pausing cancels a mounted Facebook preload and rejects its late ready callback', async () => {
|
|
let ready;
|
|
let unsubscribed = 0;
|
|
const timers = new Set();
|
|
const playerCalls = [];
|
|
const { media, root } = preloadFixture({
|
|
globalRef: { setTimeout(fn) { timers.add(fn); return fn; }, clearTimeout(fn) { timers.delete(fn); } },
|
|
facebookLoader: async () => ({
|
|
Event: { subscribe(_name, callback) { ready = callback; }, unsubscribe() { unsubscribed++; } },
|
|
XFBML: { parse() {} },
|
|
}),
|
|
});
|
|
media.warm({ sourceUrl: 'https://www.facebook.com/reel/1571491657757829' });
|
|
await Promise.resolve(); await Promise.resolve();
|
|
assert.equal(timers.size, 1);
|
|
media.pause();
|
|
assert.equal(root.children.length, 0);
|
|
assert.equal(timers.size, 0);
|
|
assert.equal(unsubscribed, 1);
|
|
ready({ type: 'video', instance: { play() { playerCalls.push('play'); }, pause() { playerCalls.push('pause'); } } });
|
|
assert.deepEqual(playerCalls, []);
|
|
media.destroy();
|
|
});
|