Files
bitvid/tests/dm-normalization.test.mjs
T
google-labs-jules[bot] 6e55c37d50 chore(ai): CI health fixes (flaky tests)
- Fix `tests/dm-normalization.test.mjs`: Replace fixed timeout with polling loop and add process exit hook to prevent hangs.
- Fix `tests/nostr/dm-direct-message-flow.test.mjs`: Replace fixed timeouts with polling loops and add process exit hook.
- Fix `detect_flakiness.mjs` path resolution.
2026-01-20 12:39:19 +00:00

133 lines
3.6 KiB
JavaScript

import assert from "node:assert/strict";
import { test, afterEach } from "node:test";
import { NostrService } from "../js/services/nostrService.js";
const { indexedDB, IDBKeyRange } = await import("fake-indexeddb");
if (!globalThis.indexedDB) {
globalThis.indexedDB = indexedDB;
globalThis.IDBKeyRange = IDBKeyRange;
}
async function deleteDatabase(name) {
await new Promise((resolve) => {
const request = indexedDB.deleteDatabase(name);
request.onsuccess = () => resolve();
request.onerror = () => resolve();
request.onblocked = () => resolve();
});
}
afterEach(async () => {
await deleteDatabase("bitvidDm");
await deleteDatabase("bitvidSettings");
});
test("direct message normalization hashes conversations consistently", async () => {
const service = new NostrService({ logger: () => {} });
const sender = "b".repeat(64);
const receiver = "a".repeat(64);
const incoming = {
ok: true,
direction: "incoming",
plaintext: "Hello there",
sender: { pubkey: sender },
recipients: [{ pubkey: receiver }],
event: {
id: "event-incoming",
created_at: 1_700_000_001,
kind: 4,
tags: [["p", receiver]],
pubkey: sender,
},
};
const outgoing = {
ok: true,
direction: "outgoing",
plaintext: "Hello there",
sender: { pubkey: sender },
recipients: [{ pubkey: receiver }],
event: {
id: "event-outgoing",
created_at: 1_700_000_002,
kind: 4,
tags: [["p", receiver]],
pubkey: sender,
},
};
const incomingRecord = await service.persistDirectMessageRecord(incoming, {
actorPubkey: receiver,
});
const outgoingRecord = await service.persistDirectMessageRecord(outgoing, {
actorPubkey: sender,
});
const expectedId = `dm:${[sender, receiver].sort().join(":")}`;
assert.equal(incomingRecord.conversation_id, expectedId);
assert.equal(outgoingRecord.conversation_id, expectedId);
});
test("direct message list dedupes entries by event id", async () => {
const service = new NostrService({ logger: () => {} });
const sender = "c".repeat(64);
const receiver = "d".repeat(64);
const baseMessage = {
ok: true,
direction: "incoming",
actorPubkey: receiver,
plaintext: "First payload",
sender: { pubkey: sender },
recipients: [{ pubkey: receiver }],
event: {
id: "event-dedupe",
created_at: 1_700_000_010,
kind: 4,
tags: [["p", receiver]],
pubkey: sender,
},
};
service.applyDirectMessage(baseMessage, { reason: "initial" });
service.applyDirectMessage(
{
...baseMessage,
plaintext: "Updated payload",
preview: "Updated payload",
},
{ reason: "duplicate" },
);
// Poll until the message update is reflected
const maxRetries = 20;
let messages = [];
for (let i = 0; i < maxRetries; i++) {
messages = service.getDirectMessages();
if (messages.length === 1 && messages[0].plaintext === "Updated payload") {
break;
}
await new Promise((resolve) => setTimeout(resolve, 50));
}
assert.equal(messages.length, 1);
assert.equal(messages[0].plaintext, "Updated payload");
// Ensure database connections are closed to prevent test hang
// This is a workaround for fake-indexeddb holding the process open
// or NostrService having lingering promises/listeners
if (service.dmNotificationManager && service.dmNotificationManager.conversationCache) {
service.dmNotificationManager.conversationCache.clear();
}
});
// Explicitly exit to avoid hanging processes due to unclosed handles (e.g. from fake-indexeddb or nostr-tools)
test.after(() => {
setTimeout(() => process.exit(0), 100);
});