Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/utils/services/adminDashboardService.test.ts
T

110 lines
3.8 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
import { getAdminActiveUserKpiCounts, getAdminTenantKpiCounts } from "@toolctrl/db/kpi.server";
import { StatChange } from "~/application/dtos/stats/StatChange";
import { getAdminDashboardStats } from "./adminDashboardService";
import { getMrr } from "./.server/subscriptionService";
vi.mock("@toolctrl/db/kpi.server", () => ({
getAdminActiveUserKpiCounts: vi.fn(),
getAdminTenantKpiCounts: vi.fn(),
}));
vi.mock("./.server/subscriptionService", () => ({
getMrr: vi.fn(),
}));
const translations: Record<string, string> = {
"admin.kpi.accounts.name": "Translated accounts",
"admin.kpi.accounts.hint": "Translated total accounts",
"admin.kpi.mrr.name": "Translated MRR",
"admin.kpi.mrr.hint": "Translated monthly revenue",
"admin.kpi.mrr.previousStat": "{{0}} translated accounts",
"admin.kpi.activeUsers.name": "Translated MAU",
"admin.kpi.activeUsers.hint": "Translated monthly active users",
};
function t(key: string) {
return translations[key] ?? key;
}
describe("getAdminDashboardStats", () => {
beforeEach(() => {
vi.clearAllMocks();
vi.mocked(getMrr).mockResolvedValue({ total: 1234.5, count: 7 });
});
it("builds translated KPI stats from package counts and forwards the selected period", async () => {
const gte = new Date("2026-01-01T00:00:00.000Z");
vi.mocked(getAdminTenantKpiCounts).mockResolvedValue({ added: 3, total: 10 });
vi.mocked(getAdminActiveUserKpiCounts).mockResolvedValue({ added: 2, total: 8 });
const stats = await getAdminDashboardStats({ t, gte });
expect(getAdminTenantKpiCounts).toHaveBeenCalledTimes(1);
expect(getAdminTenantKpiCounts).toHaveBeenCalledWith({ gte });
expect(getAdminActiveUserKpiCounts).toHaveBeenCalledTimes(1);
expect(getAdminActiveUserKpiCounts).toHaveBeenCalledWith({ gte });
expect(getMrr).toHaveBeenCalledTimes(1);
expect(getMrr).toHaveBeenCalledWith("usd");
expect(stats).toEqual([
{
name: "Translated accounts",
hint: "Translated total accounts",
stat: "10",
previousStat: "7",
change: "+3",
changeType: StatChange.Increase,
path: "/accounts",
},
{
name: "Translated MRR",
hint: "Translated monthly revenue",
stat: "$1,234.50",
previousStat: "7 translated accounts",
},
{
name: "Translated MAU",
hint: "Translated monthly active users",
stat: "8",
previousStat: "6",
change: "+2",
changeType: StatChange.Increase,
},
]);
});
it("keeps zero additions visible with equal change type and missing translations as key text", async () => {
vi.mocked(getAdminTenantKpiCounts).mockResolvedValue({ added: 0, total: 5 });
vi.mocked(getAdminActiveUserKpiCounts).mockResolvedValue({ added: 0, total: 0 });
vi.mocked(getMrr).mockResolvedValue({ total: 0, count: 0 });
const stats = await getAdminDashboardStats({ t: (key) => key });
expect(getAdminTenantKpiCounts).toHaveBeenCalledWith({ gte: undefined });
expect(getAdminActiveUserKpiCounts).toHaveBeenCalledWith({ gte: undefined });
expect(stats[0]).toMatchObject({
name: "admin.kpi.accounts.name",
hint: "admin.kpi.accounts.hint",
stat: "5",
previousStat: "5",
change: "+0",
changeType: StatChange.Equal,
path: "/accounts",
});
expect(stats[1]).toMatchObject({
name: "admin.kpi.mrr.name",
hint: "admin.kpi.mrr.hint",
stat: "$0.00",
previousStat: "admin.kpi.mrr.previousStat",
});
expect(stats[2]).toMatchObject({
name: "admin.kpi.activeUsers.name",
hint: "admin.kpi.activeUsers.hint",
stat: "0",
previousStat: "0",
change: "+0",
changeType: StatChange.Increase,
});
});
});