Files
github-stats-extended/apps/backend/tests/pin.test.js
T
MartinandMarco Pasqualetti d476f8cbe1 extract "core" package, small improvements (#137)
This PR mainly refactors the code by extracting a "core" package which
is then used by the "backend" and "frontend" apps.

Apart from this the PR also contains several smaller changes like fixing
dependabot, upgrading dependencies, aligned "package.json" files, added
tests, ...

addresses step 1 of #32 
closes #136

---------

Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
2026-04-18 10:37:26 +02:00

84 lines
2.3 KiB
JavaScript

// @ts-check
import { beforeEach, describe, expect, it, vi } from "vitest";
const mocks = vi.hoisted(() => ({
pin: vi.fn(),
storeRequest: vi.fn(),
getUserAccessByName: vi.fn(),
}));
vi.mock("@stats-organization/github-readme-stats-core", async () => {
const { mockCore } = await import("./utils.js");
return mockCore({ pin: mocks.pin });
});
vi.mock("../src/common/database.js", () => ({
storeRequest: mocks.storeRequest,
getUserAccessByName: mocks.getUserAccessByName,
}));
import router from "../router.js";
import { CACHE_TTL, DURATIONS } from "../src/common/cache.js";
const createRequest = (search = "") => ({
headers: {},
url: `/api/pin?${search}`,
});
const createResponse = () => ({
end: vi.fn(),
setHeader: vi.fn(),
});
const defaultCacheHeader =
`max-age=${CACHE_TTL.PIN_CARD.DEFAULT}, ` +
`s-maxage=${CACHE_TTL.PIN_CARD.DEFAULT}, ` +
`stale-while-revalidate=${DURATIONS.ONE_DAY}`;
beforeEach(() => {
mocks.pin.mockReset();
mocks.storeRequest.mockReset().mockResolvedValue(undefined);
mocks.getUserAccessByName.mockReset().mockResolvedValue(null);
// CACHE_SECONDS is not set here, this is just to safeguard against CACHE_SECONDS being set externally
delete process.env.CACHE_SECONDS;
});
describe("Test /api/pin backend routing", () => {
it("happy path should pass query params and user PAT, respond with pin content and persist request", async () => {
mocks.getUserAccessByName.mockResolvedValue({ token: "user-pat" });
mocks.pin.mockResolvedValue({
status: "success",
content: "mock-pin-svg",
});
const req = createRequest(
"username=anuraghazra&repo=convoychat&theme=dark",
);
const res = createResponse();
await router(req, res);
expect(mocks.getUserAccessByName).toHaveBeenCalledWith("anuraghazra");
expect(mocks.pin).toHaveBeenCalledWith(
{
username: "anuraghazra",
repo: "convoychat",
theme: "dark",
},
"user-pat",
);
expect(req.query).toEqual({
username: "anuraghazra",
repo: "convoychat",
theme: "dark",
});
expect(res.setHeader.mock.calls).toEqual([
["Cache-Control", defaultCacheHeader],
["Content-Type", "image/svg+xml"],
]);
expect(res.end).toHaveBeenCalledExactlyOnceWith("mock-pin-svg");
expect(mocks.storeRequest).toHaveBeenCalledExactlyOnceWith(req);
});
});