UNPKG

@fedify/fedify

Version:

An ActivityPub server framework

190 lines (189 loc) • 6.96 kB
import "@js-temporal/polyfill"; import "urlpattern-polyfill"; globalThis.addEventListener = () => {}; import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs"; import { t as assertStrictEquals } from "../assert_strict_equals-Dmjbg-bA.mjs"; import { n as normalizeAttachmentArrays, r as normalizeOutgoingActivityJsonLd, t as isPreloadedContextAttachmentSafe } from "../outgoing-jsonld-CNmZLixq.mjs"; import { mockDocumentLoader, test } from "@fedify/fixture"; import { Create, Document, Note, PUBLIC_COLLECTION } from "@fedify/vocab"; //#region src/compat/outgoing-jsonld.test.ts test("normalizeAttachmentArrays() wraps scalar attachments", async () => { const object = (await normalizeAttachmentArrays({ "@context": "https://www.w3.org/ns/activitystreams", type: "Create", object: { type: "Note", attachment: { type: "Document", mediaType: "image/png", url: "https://example.com/image.png" } } })).object; assertEquals(object.attachment, [{ type: "Document", mediaType: "image/png", url: "https://example.com/image.png" }]); }); test("normalizeAttachmentArrays() skips canonicalization for known-safe contexts", async () => { assertEquals((await normalizeAttachmentArrays({ "@context": ["https://www.w3.org/ns/activitystreams", "https://w3id.org/security/data-integrity/v1"], type: "Note", attachment: { type: "Document", mediaType: "image/png", url: "https://example.com/image.png" } }, () => { throw new Error("context loader should not be called"); })).attachment, [{ type: "Document", mediaType: "image/png", url: "https://example.com/image.png" }]); }); test("isPreloadedContextAttachmentSafe() checks scoped contexts", () => { assertEquals(isPreloadedContextAttachmentSafe({ "@context": { attachment: { "@id": "as:attachment", "@type": "@id" }, Example: { "@context": { attachment: { "@id": "as:attachment", "@type": "@id" } } } } }), true); assertEquals(isPreloadedContextAttachmentSafe({ "@context": { Example: { "@context": { attachment: "https://example.com/custom-attachment" } } } }), false); }); test("normalizeAttachmentArrays() does not wrap JSON-LD list objects", async () => { const attachment = { "@list": [{ type: "Document", url: "https://example.com/image.png" }] }; assertEquals((await normalizeAttachmentArrays({ "@context": "https://www.w3.org/ns/activitystreams", type: "Note", attachment }, () => { throw new Error("context loader should not be called"); })).attachment, attachment); }); test("normalizeAttachmentArrays() does not traverse JSON-LD value payloads", async () => { const output = await normalizeAttachmentArrays({ "@context": "https://www.w3.org/ns/activitystreams", type: "Note", attachment: { type: "Document" }, content: { "@type": "@json", "@value": { "@context": { attachment: "https://example.com/custom-attachment" }, attachment: "https://example.com/metadata" } } }, () => { throw new Error("context loader should not be called"); }); assertEquals(output.attachment, [{ type: "Document" }]); assertEquals(output.content, { "@type": "@json", "@value": { "@context": { attachment: "https://example.com/custom-attachment" }, attachment: "https://example.com/metadata" } }); }); test("normalizeAttachmentArrays() leaves attachment arrays unchanged", async () => { const attachment = [{ type: "Document", mediaType: "image/png", url: "https://example.com/image.png" }]; assertEquals((await normalizeAttachmentArrays({ "@context": "https://www.w3.org/ns/activitystreams", type: "Note", attachment })).attachment, attachment); }); test("normalizeAttachmentArrays() leaves documents without attachments unchanged", async () => { const input = { "@context": "https://www.w3.org/ns/activitystreams", type: "Note", content: "Hello" }; assertEquals(await normalizeAttachmentArrays(input), input); }); test("normalizeAttachmentArrays() leaves @context subtrees untouched", async () => { const output = await normalizeAttachmentArrays({ "@context": ["https://www.w3.org/ns/activitystreams", { attachment: "https://example.com/custom-attachment" }], type: "Note", attachment: "https://example.com/attachment" }); const context = output["@context"]; assertEquals(context[1], { attachment: "https://example.com/custom-attachment" }); assertEquals(output.attachment, ["https://example.com/attachment"]); }); test("normalizeAttachmentArrays() bails out when wrapping changes semantics", async () => { assertEquals((await normalizeAttachmentArrays({ "@context": { attachment: { "@id": "https://example.com/custom-attachment", "@type": "@json" } }, attachment: { custom: true } })).attachment, { custom: true }); }); test("normalizeAttachmentArrays() does not poison the global prototype via a __proto__ key", async () => { await normalizeAttachmentArrays(JSON.parse(`{ "@context": "https://www.w3.org/ns/activitystreams", "type": "Note", "attachment": { "type": "Document" }, "__proto__": { "polluted": true } }`)); assertEquals(Object.prototype.polluted, void 0); }); test("normalizeAttachmentArrays() stops before blowing the stack on pathological nesting", async () => { let deep = { attachment: { type: "Document" } }; for (let i = 0; i < 256; i++) deep = { object: deep }; const input = { "@context": "https://www.w3.org/ns/activitystreams", type: "Create", object: deep }; assertStrictEquals(await normalizeAttachmentArrays(input), input); }); test("normalizeAttachmentArrays() skips canonicalization for pathological nesting", async () => { let deep = { type: "Note" }; for (let i = 0; i < 256; i++) deep = { object: deep }; assertEquals((await normalizeAttachmentArrays({ "@context": ["https://www.w3.org/ns/activitystreams", "https://example.com/context"], type: "Note", attachment: { type: "Document" }, object: deep }, () => { throw new Error("context loader should not be called"); })).attachment, { type: "Document" }); }); test("normalizeOutgoingActivityJsonLd() applies outgoing JSON-LD workarounds", async () => { const compact = await new Create({ id: new URL("https://example.com/activities/1"), actor: new URL("https://example.com/alice"), object: new Note({ id: new URL("https://example.com/notes/1"), tos: [PUBLIC_COLLECTION], attachments: [new Document({ mediaType: "image/png", url: new URL("https://example.com/image.png") })] }), tos: [PUBLIC_COLLECTION] }).toJsonLd({ format: "compact" }); assertEquals(compact.to, "as:Public"); const compactObject = compact.object; assertEquals(Array.isArray(compactObject.attachment), false); const normalized = await normalizeOutgoingActivityJsonLd(compact, mockDocumentLoader); assertEquals(normalized.to, PUBLIC_COLLECTION.href); const normalizedObject = normalized.object; assertEquals(Array.isArray(normalizedObject.attachment), true); }); //#endregion export {};