mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Triaged two more silently-excluded test files back into CI. - nostr-boost-actions: STALE SPEC. Test required buildRepostEvent to throw /missing-event-relay/ with no relay hint, but a relay hint is a NIP-18 SHOULD (not MUST) — the builder degrades to a two-element `e` tag so a user can always repost. Replaced with an exact assertion of the valid output (kind 16 + e/p/k). - admin-list-store: STALE HARNESS (no production change, no assertion weakened). Community curator lists are fetched via the batched SubscriptionManager (cold-start relay-storm fix) the harness never mocked; the mock "hex" curator values started with "npub" so parseCommunityBlacklistReferences decoded them twice; and createListEvent omitted the `d` tag selectNewestEventsForReferences matches on. Fixed all three to be faithful to production. Removed both from the QUARANTINE map; TEST_INTEGRITY.md + TODO updated. Co-Authored-By: Claude Opus 4.8 <[email protected]>
420 lines
13 KiB
JavaScript
420 lines
13 KiB
JavaScript
import "./test-helpers/setup-localstorage.mjs";
|
|
import assert from "node:assert/strict";
|
|
|
|
const { buildRepostEvent } = await import("../js/nostrEventSchemas.js");
|
|
const {
|
|
repostEvent,
|
|
mirrorVideoEvent,
|
|
} = await import("../js/nostr/publishHelpers.js");
|
|
|
|
const resolveActiveSignerStub = () => ({
|
|
signEvent: async (event) => ({
|
|
...event,
|
|
id: `${event.kind}-${event.created_at}`,
|
|
sig: "active-signature",
|
|
}),
|
|
});
|
|
|
|
const shouldRequestExtensionPermissionsStub = () => false;
|
|
|
|
const signEventWithPrivateKeyStub = (event) => ({
|
|
...event,
|
|
id: `${event.kind}-${event.created_at}-session`,
|
|
sig: "session-signature",
|
|
});
|
|
|
|
const inferMimeTypeStub = (url = "") => {
|
|
if (typeof url !== "string") {
|
|
return "";
|
|
}
|
|
if (url.toLowerCase().endsWith(".mp4")) {
|
|
return "video/mp4";
|
|
}
|
|
if (url.toLowerCase().endsWith(".webm")) {
|
|
return "video/webm";
|
|
}
|
|
return "";
|
|
};
|
|
|
|
const eventToAddressPointerStub = () => "";
|
|
|
|
function createPublishClient({ actorPubkey = "", sessionPubkey = "", failPublish = false } = {}) {
|
|
const publishCalls = [];
|
|
const pool = {
|
|
publish(urls, event) {
|
|
publishCalls.push({ urls, event });
|
|
return {
|
|
on(eventName, handler) {
|
|
if (!failPublish && eventName === "ok") {
|
|
handler();
|
|
}
|
|
if (failPublish && eventName === "failed") {
|
|
handler(new Error("publish failed"));
|
|
}
|
|
return true;
|
|
},
|
|
};
|
|
},
|
|
};
|
|
|
|
const client = {
|
|
pubkey: actorPubkey,
|
|
relays: ["wss://relay.example"],
|
|
writeRelays: ["wss://relay.example"],
|
|
allEvents: new Map(),
|
|
rawEvents: new Map(),
|
|
pool,
|
|
ensurePool: async () => pool,
|
|
ensureSessionActor: async () => sessionPubkey,
|
|
ensureExtensionPermissions: async () => ({ ok: true }),
|
|
fetchRawEventById: async (id, { relays: requestedRelays } = {}) => {
|
|
void requestedRelays;
|
|
return client.rawEvents.get(id) || null;
|
|
},
|
|
countEventsAcrossRelays: async () => ({ total: 0, perRelay: [] }),
|
|
};
|
|
|
|
if (sessionPubkey) {
|
|
client.sessionActor = { pubkey: sessionPubkey, privateKey: "session-private-key" };
|
|
}
|
|
|
|
return { client, publishCalls };
|
|
}
|
|
|
|
(function testBuildRepostEventIncludesPointerTags() {
|
|
const createdAt = 1_700_000_000;
|
|
const event = buildRepostEvent({
|
|
pubkey: "actorpubkey",
|
|
created_at: createdAt,
|
|
eventId: "event123",
|
|
eventRelay: "wss://origin",
|
|
publishRelay: "wss://relay.example",
|
|
address: "30078:deadbeef:identifier",
|
|
addressRelay: "wss://address",
|
|
authorPubkey: "deadbeef",
|
|
targetKind: 1,
|
|
});
|
|
|
|
assert.equal(event.kind, 6);
|
|
assert.equal(event.pubkey, "actorpubkey");
|
|
assert.equal(event.created_at, createdAt);
|
|
|
|
assert.deepEqual(event.tags[0], ["e", "event123", "wss://origin"]);
|
|
assert.deepEqual(event.tags[1], ["a", "30078:deadbeef:identifier", "wss://address"]);
|
|
assert.deepEqual(event.tags[2], ["p", "deadbeef"]);
|
|
})();
|
|
|
|
(function testBuildRepostEventOmitsRelayHintWhenAbsent() {
|
|
const createdAt = 1_700_000_001;
|
|
|
|
// Spec correction (SCN-repost-optional-relay): a relay hint on the `e` tag is a
|
|
// NIP-18 SHOULD, not a MUST. With no relay available the builder must still emit
|
|
// a VALID repost — a two-element `e` tag (no relay) — rather than throwing, so a
|
|
// user can always repost even without a known relay hint.
|
|
const event = buildRepostEvent({
|
|
pubkey: "actorpubkey",
|
|
created_at: createdAt,
|
|
eventId: "event456",
|
|
authorPubkey: "cafebabe",
|
|
targetKind: 30078,
|
|
});
|
|
|
|
// Non-kind-1 (addressable) target → generic repost kind 16 with a `k` tag.
|
|
assert.equal(event.kind, 16);
|
|
assert.equal(event.pubkey, "actorpubkey");
|
|
assert.equal(event.created_at, createdAt);
|
|
assert.deepEqual(
|
|
event.tags.find((tag) => tag[0] === "e"),
|
|
["e", "event456"],
|
|
"e tag omits the relay hint when none is provided (no throw)",
|
|
);
|
|
assert.deepEqual(
|
|
event.tags.find((tag) => tag[0] === "p"),
|
|
["p", "cafebabe"],
|
|
);
|
|
assert.deepEqual(
|
|
event.tags.find((tag) => tag[0] === "k"),
|
|
["k", "30078"],
|
|
"generic repost records the target kind",
|
|
);
|
|
})();
|
|
|
|
await (async function testRepostEventUsesSessionActorAndDerivesAddress() {
|
|
const eventId = "test-event";
|
|
const authorPubkey = "f".repeat(64);
|
|
const sessionPubkey = "a".repeat(64);
|
|
const { client } = createPublishClient({ sessionPubkey });
|
|
|
|
client.rawEvents.set(eventId, {
|
|
id: eventId,
|
|
pubkey: authorPubkey,
|
|
relays: ["wss://relay.example"],
|
|
});
|
|
client.allEvents.set(eventId, {
|
|
id: eventId,
|
|
pubkey: authorPubkey,
|
|
videoRootId: "root-id",
|
|
title: "Video",
|
|
url: "https://cdn.example/video.mp4",
|
|
});
|
|
|
|
const result = await repostEvent({
|
|
client,
|
|
eventId,
|
|
options: {
|
|
pointer: ["e", eventId],
|
|
authorPubkey,
|
|
},
|
|
resolveActiveSigner: () => null,
|
|
shouldRequestExtensionPermissions: shouldRequestExtensionPermissionsStub,
|
|
signEventWithPrivateKey: signEventWithPrivateKeyStub,
|
|
eventToAddressPointer: eventToAddressPointerStub,
|
|
});
|
|
|
|
assert.equal(result.ok, true);
|
|
assert.equal(result.sessionActor, true);
|
|
assert.equal(result.signerPubkey, sessionPubkey);
|
|
assert.equal(result.event?.kind, 16);
|
|
const tags = result.event?.tags || [];
|
|
assert.ok(Array.isArray(tags), "Repost event should include tags");
|
|
assert.deepEqual(tags[0], ["e", eventId, "wss://relay.example"]);
|
|
assert.equal(
|
|
tags.some((tag) => Array.isArray(tag) && tag[0] === "a" && tag[1].startsWith("30078:")),
|
|
true,
|
|
"Repost event should include an address pointer",
|
|
);
|
|
assert.equal(
|
|
tags.some((tag) => Array.isArray(tag) && tag[0] === "p" && tag[1] === authorPubkey),
|
|
true,
|
|
"Repost event should include a p tag",
|
|
);
|
|
})();
|
|
|
|
await (async function testRepostEventHandlesPublishFailure() {
|
|
const eventId = "repost-fail";
|
|
const authorPubkey = "d".repeat(64);
|
|
const sessionPubkey = "b".repeat(64);
|
|
const { client } = createPublishClient({ sessionPubkey, failPublish: true });
|
|
|
|
client.allEvents.set(eventId, {
|
|
id: eventId,
|
|
pubkey: authorPubkey,
|
|
videoRootId: "root-id",
|
|
title: "Video",
|
|
});
|
|
|
|
const result = await repostEvent({
|
|
client,
|
|
eventId,
|
|
options: {
|
|
pointer: ["e", eventId, "wss://origin"],
|
|
authorPubkey,
|
|
},
|
|
resolveActiveSigner: resolveActiveSignerStub,
|
|
shouldRequestExtensionPermissions: shouldRequestExtensionPermissionsStub,
|
|
signEventWithPrivateKey: signEventWithPrivateKeyStub,
|
|
eventToAddressPointer: eventToAddressPointerStub,
|
|
});
|
|
|
|
assert.equal(result.ok, false);
|
|
assert.equal(result.error, "publish-rejected");
|
|
assert.ok(result.details instanceof Error);
|
|
})();
|
|
|
|
await (async function testRepostEventFailsWhenRelayMissing() {
|
|
const eventId = "repost-no-relay";
|
|
const authorPubkey = "c".repeat(64);
|
|
const sessionPubkey = "e".repeat(64);
|
|
const { client } = createPublishClient({ sessionPubkey });
|
|
|
|
client.fetchRawEventById = async () => null;
|
|
|
|
const result = await repostEvent({
|
|
client,
|
|
eventId,
|
|
options: {
|
|
pointer: ["e", eventId],
|
|
authorPubkey,
|
|
},
|
|
resolveActiveSigner: resolveActiveSignerStub,
|
|
shouldRequestExtensionPermissions: shouldRequestExtensionPermissionsStub,
|
|
signEventWithPrivateKey: signEventWithPrivateKeyStub,
|
|
eventToAddressPointer: eventToAddressPointerStub,
|
|
});
|
|
|
|
assert.equal(result.ok, false);
|
|
assert.equal(result.error, "missing-event-relay");
|
|
assert.ok(Array.isArray(result.details?.relays));
|
|
})();
|
|
|
|
await (async function testRepostEventSerializesKindOneTargetsWhenSourceAvailable() {
|
|
const eventId = "repost-kind1-content";
|
|
const authorPubkey = "d".repeat(64);
|
|
const sessionPubkey = "f".repeat(64);
|
|
const { client } = createPublishClient({ sessionPubkey });
|
|
|
|
const rawEvent = {
|
|
id: eventId,
|
|
pubkey: authorPubkey,
|
|
created_at: 1_700_000_100,
|
|
kind: 1,
|
|
tags: [],
|
|
content: "hello from kind1",
|
|
};
|
|
|
|
client.rawEvents.set(eventId, rawEvent);
|
|
|
|
const result = await repostEvent({
|
|
client,
|
|
eventId,
|
|
options: {
|
|
pointer: ["e", eventId, "wss://origin"],
|
|
authorPubkey,
|
|
},
|
|
resolveActiveSigner: resolveActiveSignerStub,
|
|
shouldRequestExtensionPermissions: shouldRequestExtensionPermissionsStub,
|
|
signEventWithPrivateKey: signEventWithPrivateKeyStub,
|
|
eventToAddressPointer: eventToAddressPointerStub,
|
|
});
|
|
|
|
assert.equal(result.ok, true);
|
|
const expectedContent = JSON.stringify(rawEvent);
|
|
assert.equal(result.event?.kind, 6);
|
|
assert.equal(result.event?.content, expectedContent);
|
|
assert.equal(result.source?.serialized, expectedContent);
|
|
assert.equal(result.source?.raw, rawEvent);
|
|
})();
|
|
|
|
await (async function testRepostEventSerializesGenericTargetsWhenSourceAvailable() {
|
|
const eventId = "repost-kind30078-content";
|
|
const authorPubkey = "e".repeat(64);
|
|
const sessionPubkey = "g".repeat(64);
|
|
const { client } = createPublishClient({ sessionPubkey });
|
|
|
|
const identifier = "video-identifier";
|
|
const rawEvent = {
|
|
id: eventId,
|
|
pubkey: authorPubkey,
|
|
created_at: 1_700_000_200,
|
|
kind: 30078,
|
|
tags: [["d", identifier]],
|
|
content: JSON.stringify({ version: 3, title: "Demo" }),
|
|
};
|
|
|
|
client.rawEvents.set(eventId, rawEvent);
|
|
|
|
const address = `30078:${authorPubkey}:${identifier}`;
|
|
|
|
const result = await repostEvent({
|
|
client,
|
|
eventId,
|
|
options: {
|
|
pointer: ["e", eventId, "wss://origin"],
|
|
authorPubkey,
|
|
address,
|
|
addressRelay: "wss://origin",
|
|
},
|
|
resolveActiveSigner: resolveActiveSignerStub,
|
|
shouldRequestExtensionPermissions: shouldRequestExtensionPermissionsStub,
|
|
signEventWithPrivateKey: signEventWithPrivateKeyStub,
|
|
eventToAddressPointer: eventToAddressPointerStub,
|
|
});
|
|
|
|
assert.equal(result.ok, true);
|
|
const expectedContent = JSON.stringify(rawEvent);
|
|
assert.equal(result.event?.kind, 16);
|
|
assert.equal(result.event?.content, expectedContent);
|
|
assert.equal(result.source?.serialized, expectedContent);
|
|
assert.equal(result.source?.raw, rawEvent);
|
|
|
|
const kTag = result.event?.tags?.find(
|
|
(tag) => Array.isArray(tag) && tag[0] === "k",
|
|
);
|
|
assert.deepEqual(kTag, ["k", String(rawEvent.kind)]);
|
|
})();
|
|
|
|
await (async function testMirrorEventIncludesHostedMetadata() {
|
|
const eventId = "mirror-event";
|
|
const actorPubkey = "1".repeat(64);
|
|
const { client } = createPublishClient({ actorPubkey });
|
|
|
|
const result = await mirrorVideoEvent({
|
|
client,
|
|
eventId,
|
|
options: {
|
|
url: "https://videos.example/video.mp4",
|
|
magnet: "magnet:?xt=urn:btih:abc",
|
|
thumbnail: "https://videos.example/thumb.jpg",
|
|
description: "Sample clip",
|
|
title: "Sample",
|
|
},
|
|
resolveActiveSigner: resolveActiveSignerStub,
|
|
shouldRequestExtensionPermissions: shouldRequestExtensionPermissionsStub,
|
|
signEventWithPrivateKey: signEventWithPrivateKeyStub,
|
|
inferMimeTypeFromUrl: inferMimeTypeStub,
|
|
});
|
|
|
|
assert.equal(result.ok, true);
|
|
const tags = result.event?.tags;
|
|
assert.ok(Array.isArray(tags));
|
|
const tagValues = Object.fromEntries(tags.map((tag) => [tag[0], tag.slice(1)]));
|
|
assert.equal(tagValues.url[0], "https://videos.example/video.mp4");
|
|
assert.equal(tagValues.m[0], "video/mp4");
|
|
assert.equal(tagValues.thumb[0], "https://videos.example/thumb.jpg");
|
|
assert.equal(tagValues.alt[0], "Sample clip");
|
|
assert.equal(tagValues.magnet[0], "magnet:?xt=urn:btih:abc");
|
|
})();
|
|
|
|
await (async function testMirrorSkipsMagnetWhenPrivate() {
|
|
const eventId = "private-mirror";
|
|
const actorPubkey = "2".repeat(64);
|
|
const { client } = createPublishClient({ actorPubkey });
|
|
|
|
const result = await mirrorVideoEvent({
|
|
client,
|
|
eventId,
|
|
options: {
|
|
url: "https://videos.example/private.mp4",
|
|
magnet: "magnet:?xt=urn:btih:hidden",
|
|
isPrivate: true,
|
|
},
|
|
resolveActiveSigner: resolveActiveSignerStub,
|
|
shouldRequestExtensionPermissions: shouldRequestExtensionPermissionsStub,
|
|
signEventWithPrivateKey: signEventWithPrivateKeyStub,
|
|
inferMimeTypeFromUrl: inferMimeTypeStub,
|
|
});
|
|
|
|
assert.equal(result.ok, true);
|
|
const tags = result.event?.tags || [];
|
|
assert.equal(
|
|
tags.some((tag) => Array.isArray(tag) && tag[0] === "magnet"),
|
|
false,
|
|
"Private mirrors must omit the magnet tag",
|
|
);
|
|
})();
|
|
|
|
await (async function testMirrorEventPublishFailureIsSurfaced() {
|
|
const eventId = "mirror-fail";
|
|
const actorPubkey = "3".repeat(64);
|
|
const { client } = createPublishClient({ actorPubkey, failPublish: true });
|
|
|
|
const result = await mirrorVideoEvent({
|
|
client,
|
|
eventId,
|
|
options: {
|
|
url: "https://videos.example/video.mp4",
|
|
title: "Failure",
|
|
},
|
|
resolveActiveSigner: resolveActiveSignerStub,
|
|
shouldRequestExtensionPermissions: shouldRequestExtensionPermissionsStub,
|
|
signEventWithPrivateKey: signEventWithPrivateKeyStub,
|
|
inferMimeTypeFromUrl: inferMimeTypeStub,
|
|
});
|
|
|
|
assert.equal(result.ok, false);
|
|
assert.equal(result.error, "publish-rejected");
|
|
assert.ok(result.details instanceof Error);
|
|
})();
|
|
|
|
console.log("nostr boost action tests passed");
|