|
1 | 1 | import { describe, expect, it } from "vitest"; |
2 | | -import { listAiCostByTenantSince, recordAiUsageEvent, sumAiCostForTenantSince } from "../../src/db/repositories"; |
| 2 | +import { listAiCostByTenantSince, listRowCountByTenantSince, recordAiUsageEvent, sumAiCostForTenantSince } from "../../src/db/repositories"; |
3 | 3 | import { createTestEnv } from "../helpers/d1"; |
4 | 4 |
|
5 | 5 | // #7176: ai_usage_events gained a nullable installation_id tenant column for centralized hosted billing, plus a |
@@ -98,3 +98,41 @@ describe("listAiCostByTenantSince (#4916): fleet-wide per-tenant breakdown for t |
98 | 98 | expect(await listAiCostByTenantSince(env, "2026-07-10T00:00:00.000Z")).toEqual([]); |
99 | 99 | }); |
100 | 100 | }); |
| 101 | + |
| 102 | +describe("listRowCountByTenantSince (#4890): per-tenant storage breakdown for the operator dashboard", () => { |
| 103 | + it("groups by tenant, counts correctly, and orders highest-count-first", async () => { |
| 104 | + const env = createTestEnv(); |
| 105 | + const since = "2026-07-10T00:00:00.000Z"; |
| 106 | + await seedCostEvent(env, "inst-1", 1.25, "2026-07-11T00:00:00.000Z"); |
| 107 | + await seedCostEvent(env, "inst-1", 0.75, "2026-07-12T00:00:00.000Z"); // inst-1: 2 rows |
| 108 | + await seedCostEvent(env, "inst-2", 4.0, "2026-07-13T00:00:00.000Z"); |
| 109 | + await seedCostEvent(env, "inst-2", 4.0, "2026-07-13T00:00:00.000Z"); |
| 110 | + await seedCostEvent(env, "inst-2", 4.0, "2026-07-13T00:00:00.000Z"); // inst-2: 3 rows (highest) |
| 111 | + await seedCostEvent(env, "inst-3", 0.5, "2026-07-13T00:00:00.000Z"); // inst-3: 1 row (lowest) |
| 112 | + |
| 113 | + const rows = await listRowCountByTenantSince(env, since); |
| 114 | + |
| 115 | + expect(rows).toEqual([ |
| 116 | + { installationId: "inst-2", rowCount: 3 }, |
| 117 | + { installationId: "inst-1", rowCount: 2 }, |
| 118 | + { installationId: "inst-3", rowCount: 1 }, |
| 119 | + ]); |
| 120 | + }); |
| 121 | + |
| 122 | + it("excludes self-host rows (null installation_id) and rows outside the time window", async () => { |
| 123 | + const env = createTestEnv(); |
| 124 | + const since = "2026-07-10T00:00:00.000Z"; |
| 125 | + await seedCostEvent(env, "inst-1", 2.0, "2026-07-11T00:00:00.000Z"); // in window |
| 126 | + await seedCostEvent(env, "inst-1", 9.0, "2026-07-01T00:00:00.000Z"); // before the window |
| 127 | + await seedCostEvent(env, null, 5.0, "2026-07-11T00:00:00.000Z"); // self-host, must never appear |
| 128 | + |
| 129 | + const rows = await listRowCountByTenantSince(env, since); |
| 130 | + |
| 131 | + expect(rows).toEqual([{ installationId: "inst-1", rowCount: 1 }]); |
| 132 | + }); |
| 133 | + |
| 134 | + it("returns an empty list, not an error, when there are no hosted rows at all (the self-host default)", async () => { |
| 135 | + const env = createTestEnv(); |
| 136 | + expect(await listRowCountByTenantSince(env, "2026-07-10T00:00:00.000Z")).toEqual([]); |
| 137 | + }); |
| 138 | +}); |
0 commit comments