Files
bitvid/tests/watchHistory/watch-history-telemetry.test.mjs
T
google-labs-jules[bot]andPR0M3TH3AN 83499ae5c4 audit(tests): fix skipped auth tests and produce audit report
- Refactored `tests/auth-service.test.mjs` to use `node:test` API so it is detected by the runner.
- Removed console noise from `tests/watchHistory/watch-history-telemetry.test.mjs`.
- Generated daily audit report `test-audit-report-2026-02-12.md`.
- Updated test logs and tracking artifacts.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-12 14:36:45 +00:00

224 lines
5.9 KiB
JavaScript

import "../test-helpers/setup-localstorage.mjs";
import assert from "node:assert/strict";
import WatchHistoryTelemetry from "../../js/services/watchHistoryTelemetry.js";
const hexPubkey = "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789";
function createTelemetry({
serviceOverrides = {},
controllerOverrides = {},
options = {},
} = {}) {
const watchHistoryService = {
isEnabled: () => true,
getSettings: () => ({ metadata: { storeLocally: true } }),
setLocalMetadata: () => {},
removeLocalMetadata: () => {},
clearLocalMetadata: () => {},
publishView: async () => ({ ok: true }),
subscribe: () => () => {},
...serviceOverrides,
};
const watchHistoryController = {
handleWatchHistoryRemoval: async () => ({}),
flush: async () => {},
...controllerOverrides,
};
const telemetry = new WatchHistoryTelemetry({
watchHistoryService,
watchHistoryController,
nostrClient: options.nostrClient || { pubkey: hexPubkey },
log: options.log || (() => {}),
normalizeHexPubkey:
options.normalizeHexPubkey || ((value) => (typeof value === "string" ? value.toLowerCase() : null)),
getActiveUserPubkey: options.getActiveUserPubkey || (() => hexPubkey),
ingestLocalViewEvent: options.ingestLocalViewEvent || (() => {}),
viewThresholdSeconds: options.viewThresholdSeconds,
});
return { telemetry, watchHistoryService, watchHistoryController };
}
class FakeVideoElement {
constructor() {
this.listeners = new Map();
this.paused = true;
this.currentTime = 0;
}
addEventListener(eventName, handler) {
if (!this.listeners.has(eventName)) {
this.listeners.set(eventName, new Set());
}
this.listeners.get(eventName).add(handler);
}
removeEventListener(eventName, handler) {
const set = this.listeners.get(eventName);
if (!set) {
return;
}
set.delete(handler);
if (set.size === 0) {
this.listeners.delete(eventName);
}
}
emit(eventName) {
const set = this.listeners.get(eventName);
if (!set) {
return;
}
for (const handler of set) {
handler({ type: eventName });
}
}
}
async function flushAsyncOperations() {
await new Promise((resolve) => setTimeout(resolve, 0));
}
async function testMetadataPreferenceSync() {
const { telemetry } = createTelemetry();
const unsubscribe = await telemetry.initPreferenceSync();
assert.equal(unsubscribe, null, "initPreferenceSync should no-op");
assert.equal(telemetry.isMetadataPreferenceEnabled(), false);
}
async function testPreparePlaybackLoggingPublishesOnce() {
const ingestEvents = [];
const publishCalls = [];
const pointer = { type: "e", value: "event-id" };
const pointerKey = "event-id::relay";
const { telemetry } = createTelemetry({
serviceOverrides: {
publishView: async (ptr, _relay) => {
publishCalls.push({ ptr });
return {
ok: true,
event: { pubkey: hexPubkey },
};
},
},
options: {
ingestLocalViewEvent: (payload) => ingestEvents.push(payload),
},
});
const videoA = new FakeVideoElement();
videoA.paused = false;
videoA.currentTime = telemetry.viewThresholdSeconds;
telemetry.preparePlaybackLogging({
videoElement: videoA,
pointer,
pointerKey,
});
await flushAsyncOperations();
assert.equal(publishCalls.length, 1, "publishView should be called once");
assert.equal(ingestEvents.length, 1, "ingestLocalViewEvent should run once");
assert.deepEqual(publishCalls[0].ptr, pointer);
assert.deepEqual(ingestEvents[0].pointer, pointer);
const videoB = new FakeVideoElement();
videoB.paused = false;
videoB.currentTime = telemetry.viewThresholdSeconds;
telemetry.preparePlaybackLogging({
videoElement: videoB,
pointer,
pointerKey,
});
await flushAsyncOperations();
assert.equal(
publishCalls.length,
1,
"Repeated preparePlaybackLogging should reuse cooldown cache"
);
}
async function testPreparePlaybackLoggingIgnoresMetadata() {
const publishCalls = [];
const pointer = { type: "e", value: "event-id" };
const pointerKey = "event-id";
const { telemetry } = createTelemetry({
serviceOverrides: {
publishView: async (ptr, _relay) => {
publishCalls.push({ ptr });
return {
ok: true,
event: { pubkey: hexPubkey },
};
},
},
});
const videoElement = new FakeVideoElement();
videoElement.paused = false;
videoElement.currentTime = telemetry.viewThresholdSeconds;
const videoMetadata = {
id: "evt1",
title: "Example Video",
thumbnail: "https://example.com/thumb.jpg",
pubkey: hexPubkey,
rootCreatedAt: 1_700_000_000,
url: "https://example.com/video.mp4",
};
telemetry.preparePlaybackLogging({
videoElement,
pointer,
pointerKey,
video: videoMetadata,
});
await flushAsyncOperations();
assert.equal(publishCalls.length, 1, "publishView should be invoked once");
assert.equal(publishCalls[0].ptr, pointer);
assert.equal(publishCalls[0].metadata, undefined, "metadata should NOT be passed");
}
async function testCancelPlaybackLoggingFlushes() {
let flushArgs = null;
const video = new FakeVideoElement();
const { telemetry } = createTelemetry({
controllerOverrides: {
flush: async (reason, context) => {
flushArgs = { reason, context };
},
},
});
video.paused = true;
video.currentTime = 0;
telemetry.preparePlaybackLogging({
videoElement: video,
pointer: { type: "e", value: "event" },
pointerKey: "event",
});
telemetry.cancelPlaybackLogging({ reason: "unit", context: "test" });
await flushAsyncOperations();
assert.deepEqual(flushArgs, { reason: "unit", context: "test" });
}
await testMetadataPreferenceSync();
await testPreparePlaybackLoggingPublishesOnce();
await testPreparePlaybackLoggingIgnoresMetadata();
await testCancelPlaybackLoggingFlushes();