addition of new dashboard

This commit is contained in:
2026-08-20 15:08:32 +00:00
parent 0622018d95
commit bf59249ed7
161 changed files with 13170 additions and 119 deletions

View File

@@ -0,0 +1,160 @@
import { jest } from "@jest/globals";
// Manual DB mock: getPool() returns whatever fake client the current test set.
let client;
const getPool = jest.fn(async () => client);
jest.unstable_mockModule("../db/index.js", () => ({ getPool }));
const { PgSessionStore, expiryOf } = await import("./sessionStore.js");
const ONE_DAY_MS = 86_400_000;
// A fake pooled client whose query() returns `rows` and that records release().
function mockClient(rows = []) {
return {
query: jest.fn(async () => ({ rows })),
release: jest.fn(async () => {}),
};
}
// Store with the prune timer disabled; memoryTtlMs chosen per test.
const makeStore = (opts = {}) => new PgSessionStore({ pruneIntervalMs: 0, ...opts });
// Promisify express-session's node-style callbacks for cleaner assertions.
const call = (fn) => new Promise((resolve, reject) =>
fn((err, res) => (err ? reject(err) : resolve(res))));
beforeEach(() => {
getPool.mockClear();
client = mockClient();
});
describe("expiryOf", () => {
it("uses the cookie's expiry when present", () => {
const when = new Date("2030-01-01T00:00:00Z");
expect(expiryOf({ cookie: { expires: when } }).getTime()).toBe(when.getTime());
});
it("defaults to ~one day out when no cookie expiry", () => {
const before = Date.now();
const got = expiryOf({}).getTime();
expect(got).toBeGreaterThanOrEqual(before + ONE_DAY_MS - 50);
expect(got).toBeLessThanOrEqual(Date.now() + ONE_DAY_MS + 50);
});
});
describe("PgSessionStore memory + PG fallback", () => {
it("get() falls back to Postgres on a cold cache and filters expired rows in SQL", async () => {
client = mockClient([{ sess: { user_id: 7 }, expire: new Date(Date.now() + ONE_DAY_MS).toISOString() }]);
const store = makeStore();
const sess = await call((cb) => store.get("sid-1", cb));
expect(sess).toEqual({ user_id: 7 });
expect(getPool).toHaveBeenCalledTimes(1);
const [sql, params] = client.query.mock.calls[0];
expect(sql).toContain("expire > NOW()");
expect(params).toEqual(["sid-1"]);
expect(client.release).toHaveBeenCalledTimes(1);
});
it("get() serves a warm in-memory session WITHOUT querying Postgres", async () => {
const store = makeStore({ memoryTtlMs: 10_000 });
await call((cb) => store.set("sid-2", { user_id: 1, cookie: {} }, cb)); // write-through populates memory
getPool.mockClear();
const sess = await call((cb) => store.get("sid-2", cb));
expect(sess).toMatchObject({ user_id: 1 });
expect(getPool).not.toHaveBeenCalled(); // the whole point: no per-request query
});
it("get() re-reads Postgres once the in-memory copy goes stale", async () => {
client = mockClient([{ sess: { user_id: 5 }, expire: new Date(Date.now() + ONE_DAY_MS).toISOString() }]);
const store = makeStore({ memoryTtlMs: 0 }); // memory never counts as fresh
await call((cb) => store.set("sid", { user_id: 5, cookie: {} }, cb));
getPool.mockClear();
const sess = await call((cb) => store.get("sid", cb));
expect(getPool).toHaveBeenCalledTimes(1); // stale -> fell back to Postgres
expect(sess).toEqual({ user_id: 5 });
});
it("get() drops an expired in-memory entry without a query", async () => {
const store = makeStore({ memoryTtlMs: 10_000 });
await call((cb) => store.set("exp", { user_id: 1, cookie: { expires: new Date(Date.now() - 1000) } }, cb));
getPool.mockClear();
const sess = await call((cb) => store.get("exp", cb));
expect(sess).toBeNull();
expect(getPool).not.toHaveBeenCalled();
});
it("get() returns null when no row matches", async () => {
client = mockClient([]);
const sess = await call((cb) => makeStore().get("missing", cb));
expect(sess).toBeNull();
});
it("set() write-through upserts to Postgres (bumping updated_ts) and populates memory", async () => {
const store = makeStore({ memoryTtlMs: 10_000 });
const when = new Date("2030-06-01T00:00:00Z");
await call((cb) => store.set("sid-3", { cookie: { expires: when }, user_id: 1 }, cb));
const [sql, params] = client.query.mock.calls[0];
expect(sql).toContain("ON CONFLICT (sid) DO UPDATE");
expect(sql).toContain("updated_ts = NOW()");
expect(params[0]).toBe("sid-3");
expect(params[2]).toEqual(when);
getPool.mockClear();
const sess = await call((cb) => store.get("sid-3", cb));
expect(getPool).not.toHaveBeenCalled(); // served from memory after the write-through
expect(sess).toMatchObject({ user_id: 1 });
});
it("destroy() removes the session from memory and Postgres", async () => {
const store = makeStore({ memoryTtlMs: 10_000 });
await call((cb) => store.set("sid-4", { user_id: 1, cookie: {} }, cb));
client.query.mockClear();
await call((cb) => store.destroy("sid-4", cb));
expect(client.query.mock.calls[0][0]).toContain("DELETE FROM session WHERE sid = $1");
expect(client.query.mock.calls[0][1]).toEqual(["sid-4"]);
// Memory was cleared -> the next get falls back to Postgres (now empty).
client = mockClient([]);
getPool.mockClear();
expect(await call((cb) => store.get("sid-4", cb))).toBeNull();
expect(getPool).toHaveBeenCalledTimes(1);
});
it("touch() bumps only the expiry", async () => {
await call((cb) => makeStore().touch("sid-5", {}, cb));
expect(client.query.mock.calls[0][0]).toContain("UPDATE session SET expire = $2");
});
it("prune() sweeps expired rows from Postgres", async () => {
const store = makeStore();
await store.prune();
expect(client.query.mock.calls[0][0]).toContain("DELETE FROM session WHERE expire <= NOW()");
expect(client.release).toHaveBeenCalledTimes(1);
});
it("releases the client and surfaces the error when a query fails", async () => {
client = {
query: jest.fn(async () => { throw new Error("db down"); }),
release: jest.fn(async () => {}),
};
await expect(call((cb) => makeStore({ memoryTtlMs: 0 }).get("sid", cb))).rejects.toThrow("db down");
expect(client.release).toHaveBeenCalledTimes(1);
});
it("surfaces the error and calls back exactly once when acquiring a client fails", async () => {
getPool.mockImplementationOnce(async () => { throw new Error("pool exhausted"); });
const store = makeStore({ memoryTtlMs: 0 });
const cb = jest.fn();
await new Promise((resolve) => store.get("sid", (...args) => { cb(...args); resolve(); }));
expect(cb).toHaveBeenCalledTimes(1);
expect(cb.mock.calls[0][0]).toBeInstanceOf(Error);
expect(cb.mock.calls[0][0].message).toBe("pool exhausted");
});
});