@fedify/fedify
Version:
An ActivityPub server framework
197 lines (196 loc) • 5.87 kB
JavaScript
import { Temporal } from "@js-temporal/polyfill";
import { URLPattern } from "urlpattern-polyfill";
globalThis.addEventListener = () => {};
import { n as kvCache, t as MockKvStore } from "../kv-cache-DYsF2MhP.mjs";
import { mockDocumentLoader, test } from "@fedify/fixture";
import { deepStrictEqual, throws } from "node:assert";
import { preloadedContexts } from "@fedify/vocab-runtime";
//#region src/utils/kv-cache.test.ts
test("kvCache()", async (t) => {
const kv = new MockKvStore();
await t.step("cached", async () => {
const loader = kvCache({
kv,
loader: mockDocumentLoader,
rules: [
["https://example.org/", Temporal.Duration.from({ days: 1 })],
[new URL("https://example.net/"), Temporal.Duration.from({ days: 1 })],
[new URLPattern("https://example.com/*"), Temporal.Duration.from({ days: 30 })]
],
prefix: ["_test", "cached"]
});
const result = await loader("https://example.com/object");
deepStrictEqual(result, {
contextUrl: null,
documentUrl: "https://example.com/object",
document: {
"@context": "https://www.w3.org/ns/activitystreams",
id: "https://example.com/object",
name: "Fetched object",
type: "Object"
}
});
deepStrictEqual(await kv.get([
"_test",
"cached",
"https://example.com/object"
]), result);
await kv.set([
"_test",
"cached",
"https://example.org/"
], {
contextUrl: null,
documentUrl: "https://example.org/",
document: { "id": "https://example.org/" }
});
deepStrictEqual(await loader("https://example.org/"), {
contextUrl: null,
documentUrl: "https://example.org/",
document: { "id": "https://example.org/" }
});
await kv.set([
"_test",
"cached",
"https://example.net/"
], {
contextUrl: null,
documentUrl: "https://example.net/",
document: { "id": "https://example.net/" }
});
deepStrictEqual(await loader("https://example.net/"), {
contextUrl: null,
documentUrl: "https://example.net/",
document: { "id": "https://example.net/" }
});
});
await t.step("not cached", async () => {
deepStrictEqual(await kvCache({
kv,
loader: mockDocumentLoader,
rules: [],
prefix: ["_test", "not cached"]
})("https://example.com/object"), {
contextUrl: null,
documentUrl: "https://example.com/object",
document: {
"@context": "https://www.w3.org/ns/activitystreams",
id: "https://example.com/object",
name: "Fetched object",
type: "Object"
}
});
deepStrictEqual(await kv.get([
"test2",
"not cached",
"https://example.com/object"
]), void 0);
});
await t.step("maximum cache duration", () => {
throws(() => kvCache({
kv,
loader: mockDocumentLoader,
rules: [["https://example.com/", Temporal.Duration.from({
days: 30,
seconds: 1
})]]
}), TypeError, "The maximum cache duration is 30 days");
throws(() => kvCache({
kv,
loader: mockDocumentLoader,
rules: [[new URLPattern("https://example.com/*"), Temporal.Duration.from({
days: 30,
seconds: 1
})]]
}), TypeError, "The maximum cache duration is 30 days");
});
await t.step("on kv store exception", async () => {
class KvStoreThrowsException {
get(_key) {
throw new Error("Failed to get key");
}
set(_key, _value, _options) {
throw new Error("Failed to set key");
}
delete(_key) {
throw new Error("Failed to delete key");
}
async *list(_prefix) {
throw new Error("Failed to list keys");
}
}
deepStrictEqual(await kvCache({
kv: new KvStoreThrowsException(),
loader: mockDocumentLoader,
rules: [
["https://example.org/", Temporal.Duration.from({ days: 1 })],
[new URL("https://example.net/"), Temporal.Duration.from({ days: 1 })],
[new URLPattern("https://example.com/*"), Temporal.Duration.from({ days: 30 })]
],
prefix: ["_test", "not cached"]
})("https://example.com/object"), {
contextUrl: null,
documentUrl: "https://example.com/object",
document: {
"@context": "https://www.w3.org/ns/activitystreams",
id: "https://example.com/object",
name: "Fetched object",
type: "Object"
}
});
});
await t.step("preloaded contexts bypass cache", async () => {
const kv = new MockKvStore();
let loaderCalled = false;
const mockLoader = (url) => {
loaderCalled = true;
return Promise.resolve({
contextUrl: null,
documentUrl: url,
document: { "mock": "document" }
});
};
const loader = kvCache({
kv,
loader: mockLoader,
prefix: ["_test", "preloaded"]
});
const activityStreamsUrl = "https://www.w3.org/ns/activitystreams";
loaderCalled = false;
deepStrictEqual(await loader(activityStreamsUrl), {
contextUrl: null,
documentUrl: activityStreamsUrl,
document: preloadedContexts[activityStreamsUrl]
});
deepStrictEqual(loaderCalled, false, "Loader should not be called for preloaded contexts");
deepStrictEqual(await kv.get([
"_test",
"preloaded",
activityStreamsUrl
]), void 0, "Preloaded contexts should not be cached in KV store");
const securityUrl = "https://w3id.org/security/v1";
loaderCalled = false;
deepStrictEqual(await loader(securityUrl), {
contextUrl: null,
documentUrl: securityUrl,
document: preloadedContexts[securityUrl]
});
deepStrictEqual(loaderCalled, false, "Loader should not be called for preloaded contexts");
const nonPreloadedUrl = "https://example.com/not-preloaded";
loaderCalled = false;
const result3 = await loader(nonPreloadedUrl);
deepStrictEqual(result3, {
contextUrl: null,
documentUrl: nonPreloadedUrl,
document: { "mock": "document" }
});
deepStrictEqual(loaderCalled, true, "Loader should be called for non-preloaded URLs");
deepStrictEqual(await kv.get([
"_test",
"preloaded",
nonPreloadedUrl
]), result3, "Non-preloaded URLs should be cached");
});
});
//#endregion
export {};