@fedify/fedify
Version:
An ActivityPub server framework
190 lines (189 loc) • 6.96 kB
JavaScript
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 {};