addition of new dashboard
This commit is contained in:
97
backend/http/dashboardPassthrough.test.js
Normal file
97
backend/http/dashboardPassthrough.test.js
Normal file
@@ -0,0 +1,97 @@
|
||||
import { jest } from "@jest/globals";
|
||||
import { makePassthrough } from "./dashboardPassthrough.js";
|
||||
|
||||
const LOCAL = { core: { url: null, key: null }, audit: { url: null, key: null } };
|
||||
const FED = { core: { url: "http://core", key: "ck" }, audit: { url: "http://audit", key: "ak" } };
|
||||
|
||||
const localService = () => ({
|
||||
summary: jest.fn(async () => ({ apiUsage: { core: 2, audit: 1, total: 3 }, apiKeys: 4, endpoints: 2, storage: {} })),
|
||||
transactions: jest.fn(async () => ({ rows: [], total: 0 })),
|
||||
series: jest.fn(async () => ({ usage: [], storage: [] })),
|
||||
verify: jest.fn(async () => ({ results: [] })),
|
||||
event: jest.fn(async () => ({ eventId: "x" })),
|
||||
});
|
||||
|
||||
describe("passthrough — local mode (no remote sources)", () => {
|
||||
it("serves every endpoint from the local service and never fetches", async () => {
|
||||
const service = localService();
|
||||
const fetchImpl = jest.fn();
|
||||
const p = makePassthrough({ service, config: { dashboard: LOCAL }, fetchImpl });
|
||||
|
||||
expect(await p.summary(7, { from: "a", to: "b" })).toMatchObject({ apiKeys: 4 });
|
||||
await p.transactions(7, { type: "audit" });
|
||||
await p.series(7, {});
|
||||
expect(service.summary).toHaveBeenCalled();
|
||||
expect(service.transactions).toHaveBeenCalled();
|
||||
expect(fetchImpl).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("scopes every local call to the caller's own user id (per-tenant isolation)", async () => {
|
||||
const service = localService();
|
||||
const p = makePassthrough({ service, config: { dashboard: LOCAL }, fetchImpl: jest.fn() });
|
||||
|
||||
await p.summary(7, { from: "a", to: "b" });
|
||||
await p.transactions(9, { type: "core" });
|
||||
await p.event(9, "uuid-1");
|
||||
|
||||
// The passthrough never substitutes another user's id — each call carries the
|
||||
// id it was handed (which the route sets from req.user.id), so user 7 can
|
||||
// never be served user 9's rows and vice versa.
|
||||
expect(service.summary).toHaveBeenCalledWith(7, { from: "a", to: "b" });
|
||||
expect(service.transactions.mock.calls[0][0]).toBe(9);
|
||||
expect(service.event).toHaveBeenCalledWith(9, "uuid-1");
|
||||
});
|
||||
});
|
||||
|
||||
describe("passthrough — federated mode", () => {
|
||||
const fetchImpl = jest.fn(async (url) => ({
|
||||
ok: true,
|
||||
json: async () =>
|
||||
url.includes("//core")
|
||||
? { apiUsage: { core: 10, audit: 0, total: 10 }, apiKeys: 5, endpoints: 2, storage: { onDisk: { core: 100, audit: 0, total: 100 }, logical: { core: 100, audit: 0, total: 100 } } }
|
||||
: { apiUsage: { core: 0, audit: 7, total: 7 }, apiKeys: 0, endpoints: 0, storage: { onDisk: { core: 0, audit: 50, total: 50 }, logical: { core: 0, audit: 50, total: 50 } } },
|
||||
}));
|
||||
|
||||
beforeEach(() => fetchImpl.mockClear());
|
||||
|
||||
it("merges summary: core fields from core source, audit fields from audit source", async () => {
|
||||
const p = makePassthrough({ service: {}, config: { dashboard: FED }, fetchImpl });
|
||||
const out = await p.summary(7, { from: "a", to: "b" });
|
||||
expect(out.apiUsage).toEqual({ core: 10, audit: 7, total: 17 });
|
||||
expect(out.storage.onDisk).toEqual({ core: 100, audit: 50, total: 150 });
|
||||
expect(out.apiKeys).toBe(5); // from the core source
|
||||
expect(fetchImpl).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("forwards with the source's API key and NO user id in the body (the key is the tenant scope)", async () => {
|
||||
const p = makePassthrough({ service: {}, config: { dashboard: FED }, fetchImpl });
|
||||
await p.summary(7, { from: "a", to: "b" });
|
||||
const coreCall = fetchImpl.mock.calls.find(([u]) => u.includes("//core"));
|
||||
expect(coreCall[0]).toBe("http://core/api/v1/data/dashboard/summary");
|
||||
expect(coreCall[1].headers.Authorization).toBe("Bearer ck");
|
||||
const body = JSON.parse(coreCall[1].body);
|
||||
expect(body).toEqual({ from: "a", to: "b" }); // only the window — never a userId
|
||||
expect(body).not.toHaveProperty("userId");
|
||||
});
|
||||
|
||||
it("routes the audit transactions tab to the audit source", async () => {
|
||||
const p = makePassthrough({ service: {}, config: { dashboard: FED }, fetchImpl });
|
||||
await p.transactions(7, { type: "audit", limit: 50, offset: 0 });
|
||||
const [url] = fetchImpl.mock.calls[0];
|
||||
expect(url).toBe("http://audit/api/v1/data/dashboard/transactions");
|
||||
});
|
||||
|
||||
it("merges the combined usage+storage series by date", async () => {
|
||||
const seriesFetch = jest.fn(async (url) => ({
|
||||
ok: true,
|
||||
json: async () =>
|
||||
url.includes("//core")
|
||||
? { usage: [{ date: "2026-06-01", core: 3, audit: 0, total: 3 }], storage: [{ date: "2026-06-01", coreDisk: 100, auditDisk: 0, totalDisk: 100 }] }
|
||||
: { usage: [{ date: "2026-06-01", core: 0, audit: 5, total: 5 }], storage: [{ date: "2026-06-01", coreDisk: 0, auditDisk: 50, totalDisk: 50 }] },
|
||||
}));
|
||||
const p = makePassthrough({ service: {}, config: { dashboard: FED }, fetchImpl: seriesFetch });
|
||||
const out = await p.series(7, { from: "a", to: "b" });
|
||||
expect(out.usage).toEqual([{ date: "2026-06-01", core: 3, audit: 5, total: 8 }]);
|
||||
expect(out.storage).toEqual([{ date: "2026-06-01", coreDisk: 100, auditDisk: 50, totalDisk: 150 }]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user