Files
bitvid/tests/e2e/profile-list-sync-diagnostics.spec.ts
T

186 lines
5.3 KiB
TypeScript

import { test, expect } from "./helpers/bitvidTestFixture";
import { finalizeEvent, getPublicKey } from "nostr-tools";
function makeHex(char: string) {
return char.repeat(64);
}
test.describe("Profile list sync diagnostics", () => {
test("captures console + page errors during login/profile sync baseline", async ({
page,
gotoApp,
loginAs,
testPubkey,
relayUrl,
setTestRelays,
startDiagnostics,
}) => {
const diagnostics = await startDiagnostics(page);
await gotoApp();
await loginAs(page);
await setTestRelays(page, [relayUrl]);
await page.waitForFunction(
() => Boolean((window as any).__bitvidTest__?.getAppState?.()?.isLoggedIn),
{ timeout: 15_000 },
);
const appState = await page.evaluate(() => {
return (window as any).__bitvidTest__.getAppState();
});
expect(appState.isLoggedIn).toBe(true);
const syncState = await page.evaluate(async (activePubkey) => {
const module = await import("/js/userBlocks.js");
const manager = module.userBlocks;
const statuses: any[] = [];
const unsubscribe = manager.on("status", (detail: any) => {
statuses.push(detail);
});
try {
await manager.loadBlocks(activePubkey, {
allowPermissionPrompt: false,
decryptTimeoutMs: 250,
});
} finally {
if (typeof unsubscribe === "function") unsubscribe();
}
return {
statuses,
blockedPubkeys: manager.getBlockedPubkeys(),
};
}, testPubkey);
const diagnosticsResult = await diagnostics.stop();
const appErrorLogs = diagnosticsResult.console.filter(
(entry) =>
entry.type === "error" ||
entry.text.includes("[UserBlockList]") ||
entry.text.includes("profile list") ||
entry.text.includes("blocked creators"),
);
expect(Array.isArray(syncState.statuses)).toBe(true);
expect(Array.isArray(syncState.blockedPubkeys)).toBe(true);
// Diagnostic output is intentionally logged for local triage.
console.log(
JSON.stringify(
{
phase: "baseline",
appState,
consoleCount: diagnosticsResult.console.length,
pageErrorCount: diagnosticsResult.pageErrors.length,
appErrorLogs,
syncEventsTail: diagnosticsResult.syncEvents.slice(-8),
statusTail: syncState.statuses.slice(-8),
blockedPubkeys: syncState.blockedPubkeys,
},
null,
2,
),
);
});
test("forced decrypt-timeout still ingests public mute tags", async ({
page,
gotoApp,
loginAs,
seedRawEvent,
testPubkey,
testPrivateKey,
relayUrl,
setTestRelays,
setDecryptBehavior,
startDiagnostics,
}) => {
const publicBlocked = makeHex("a");
const privateKeyBytes = Uint8Array.from(Buffer.from(testPrivateKey, "hex"));
const derivedPubkey = getPublicKey(privateKeyBytes);
const staleEvent = finalizeEvent(
{
kind: 10000,
created_at: Math.floor(Date.now() / 1000),
tags: [
["encrypted", "nip44"],
["p", publicBlocked],
],
content: "ciphertext-timeout",
},
privateKeyBytes,
);
await seedRawEvent(staleEvent);
const diagnostics = await startDiagnostics(page);
await gotoApp();
await loginAs(page);
await setTestRelays(page, [relayUrl]);
await page.waitForFunction(
() => Boolean((window as any).__bitvidTest__?.getAppState?.()?.isLoggedIn),
{ timeout: 15_000 },
);
let result: any = null;
try {
await setDecryptBehavior(page, "timeout");
result = await page.evaluate(
async ({ activePubkey, blockedPubkey }) => {
const blocksModule = await import("/js/userBlocks.js");
const manager = blocksModule.userBlocks;
const statuses: any[] = [];
const unsubscribe = manager.on("status", (detail: any) => {
statuses.push(detail);
});
try {
await manager.loadBlocks(activePubkey, {
allowPermissionPrompt: false,
decryptTimeoutMs: 80,
});
} finally {
if (typeof unsubscribe === "function") unsubscribe();
}
return {
statuses,
blockedPubkeys: manager.getBlockedPubkeys(),
containsPublicMute: manager.getBlockedPubkeys().includes(blockedPubkey),
};
},
{ activePubkey: testPubkey, blockedPubkey: publicBlocked },
);
expect(testPubkey).toBe(derivedPubkey);
expect(result.containsPublicMute).toBe(true);
expect(
result.statuses.some(
(entry: any) =>
entry?.status === "stale" && entry?.reason === "decrypt-timeout",
),
).toBe(true);
} finally {
await setDecryptBehavior(page, "passthrough");
}
const diagnosticsResult = await diagnostics.stop();
console.log(
JSON.stringify(
{
phase: "forced-timeout",
consoleCount: diagnosticsResult.console.length,
pageErrorCount: diagnosticsResult.pageErrors.length,
syncEventsTail: diagnosticsResult.syncEvents.slice(-10),
statusTail: result?.statuses?.slice?.(-10) || [],
blockedPubkeys: result?.blockedPubkeys || [],
},
null,
2,
),
);
});
});