Commit the accumulated infrastructure work that was living only in the working tree: monitoring stack, emergency access/bot, gyro allocator, grimmory, adguard, backup audit and the OpenCode agent definitions. Also ignore Python bytecode, local archives and Nix/direnv artifacts. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTocXkGUUazHdKKd3r9k71
103 lines
3.3 KiB
JavaScript
103 lines
3.3 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import { GrimmoryClient, query, unwrap } from "../src/client.js";
|
|
|
|
test("unwrap handles Grimmory API response envelope", () => {
|
|
assert.deepEqual(unwrap({ status: 200, data: { id: 7 } }), { id: 7 });
|
|
assert.deepEqual(unwrap([1, 2]), [1, 2]);
|
|
});
|
|
|
|
test("query repeats array values and skips empty values", () => {
|
|
assert.equal(
|
|
query({ page: 0, status: ["READING", "READ"], search: "" }),
|
|
"page=0&status=READING&status=READ",
|
|
);
|
|
});
|
|
|
|
test("libraries falls back to the current user on the v3.2.4 endpoint bug", async () => {
|
|
const responses = [
|
|
new Response(JSON.stringify({ message: "broken" }), { status: 500 }),
|
|
new Response(JSON.stringify({ data: { assignedLibraries: [{ id: 3 }] } })),
|
|
];
|
|
const client = new GrimmoryClient({
|
|
baseUrl: "https://example.test",
|
|
username: "ada",
|
|
passwordFile: "/unused",
|
|
fetchImpl: async () => responses.shift(),
|
|
});
|
|
client.accessToken = "test";
|
|
assert.deepEqual(await client.libraries(), [{ id: 3 }]);
|
|
});
|
|
|
|
test("springPage supports the nested Spring page metadata", async () => {
|
|
let request = 0;
|
|
const client = new GrimmoryClient({
|
|
baseUrl: "https://example.test",
|
|
username: "ada",
|
|
passwordFile: "/unused",
|
|
fetchImpl: async () => {
|
|
const page = request++;
|
|
return new Response(
|
|
JSON.stringify({
|
|
data: {
|
|
content: page === 0 ? Array.from({ length: 100 }, (_, id) => id) : [100],
|
|
page: { number: page, totalPages: 2 },
|
|
},
|
|
}),
|
|
);
|
|
},
|
|
});
|
|
client.accessToken = "test";
|
|
assert.equal((await client.springPage("/sessions")).length, 101);
|
|
assert.equal(request, 2);
|
|
});
|
|
|
|
test("allBooks follows nested pagination and rejects missing metadata", async () => {
|
|
let request = 0;
|
|
const client = new GrimmoryClient({
|
|
baseUrl: "https://example.test",
|
|
username: "ada",
|
|
passwordFile: "/unused",
|
|
fetchImpl: async () => {
|
|
const page = request++;
|
|
return new Response(JSON.stringify({ data: {
|
|
content: page === 0 ? Array.from({ length: 50 }, (_, id) => ({ id })) : [{ id: 50 }],
|
|
page: { number: page, totalPages: 2 },
|
|
} }));
|
|
},
|
|
});
|
|
client.accessToken = "test";
|
|
assert.equal((await client.allBooks()).length, 51);
|
|
assert.equal(request, 2);
|
|
});
|
|
|
|
test("concurrent first requests share one login", async () => {
|
|
let logins = 0;
|
|
const client = new GrimmoryClient({
|
|
baseUrl: "https://example.test",
|
|
username: "ada",
|
|
passwordFile: "/unused",
|
|
fetchImpl: async () => new Response(JSON.stringify({ data: { ok: true } })),
|
|
});
|
|
client.login = async () => {
|
|
logins += 1;
|
|
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
client.accessToken = "test";
|
|
};
|
|
await Promise.all([client.request("/one"), client.request("/two")]);
|
|
assert.equal(logins, 1);
|
|
});
|
|
|
|
test("springPage rejects missing pagination metadata on a full page", async () => {
|
|
const client = new GrimmoryClient({
|
|
baseUrl: "https://example.test",
|
|
username: "ada",
|
|
passwordFile: "/unused",
|
|
fetchImpl: async () => new Response(JSON.stringify({ data: {
|
|
content: Array.from({ length: 100 }, (_, id) => ({ id })),
|
|
} })),
|
|
});
|
|
client.accessToken = "test";
|
|
await assert.rejects(() => client.springPage("/sessions"), /no pagination metadata/);
|
|
});
|