131 lines
5.0 KiB
TypeScript
131 lines
5.0 KiB
TypeScript
/**
|
|
* Characterization + API-surface test: usageAnalytics.ts god-file decomposition.
|
|
*
|
|
* The two pure SQL-source-string builders (buildUnifiedSource,
|
|
* buildPresetUnifiedSource) + their types were extracted verbatim from
|
|
* src/lib/db/usageAnalytics.ts into the pure leaf
|
|
* src/lib/db/usageAnalytics/sources.ts (no DB, no imports). The ~20 query
|
|
* functions stay in the host.
|
|
*
|
|
* Verifies that:
|
|
* 1. buildUnifiedSource's needsAggregated branching is preserved (pure logic).
|
|
* 2. The host usageAnalytics.ts still exposes the FULL public API (39 names).
|
|
* 3. The sources leaf exports the builders directly.
|
|
*
|
|
* Pure value assertions — no DB handle is opened.
|
|
*/
|
|
|
|
import { describe, it } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import {
|
|
buildUnifiedSource,
|
|
buildPresetUnifiedSource,
|
|
} from "../../src/lib/db/usageAnalytics/sources.ts";
|
|
|
|
// ── 1. buildUnifiedSource — pure branching ───────────────────────────────────
|
|
|
|
describe("usageAnalytics/sources — buildUnifiedSource", () => {
|
|
it("includes the daily_usage_summary leg for a wide window with no api-key filter", () => {
|
|
const { unifiedSource, unifiedParams } = buildUnifiedSource({
|
|
sinceIso: "2024-06-01T00:00:00.000Z",
|
|
untilIso: null,
|
|
rawCutoffDate: "2024-06-15",
|
|
apiKeyWhere: "",
|
|
apiKeyParams: {},
|
|
});
|
|
assert.ok(typeof unifiedSource === "string" && unifiedSource.length > 0);
|
|
// needsAggregated = (sinceDate < rawCutoffDate) && !apiKeyWhere => true
|
|
assert.ok(
|
|
unifiedSource.includes("daily_usage_summary"),
|
|
"aggregated leg must be present when the window predates the raw cutoff"
|
|
);
|
|
assert.equal(unifiedParams.rawCutoff, "2024-06-15");
|
|
assert.equal(unifiedParams.rawCutoffDate, "2024-06-15");
|
|
});
|
|
|
|
it("drops the aggregated leg when an api-key filter is active (raw-only)", () => {
|
|
const { unifiedSource, unifiedParams } = buildUnifiedSource({
|
|
sinceIso: "2024-06-01T00:00:00.000Z",
|
|
untilIso: null,
|
|
rawCutoffDate: "2024-06-15",
|
|
apiKeyWhere: "(api_key_id IN (@apiKey0))",
|
|
apiKeyParams: { apiKey0: "k1" },
|
|
});
|
|
// needsAggregated = ... && !apiKeyWhere => false
|
|
assert.ok(
|
|
!unifiedSource.includes("daily_usage_summary"),
|
|
"aggregated leg must be absent once an api-key filter scopes the query to raw rows"
|
|
);
|
|
// raw leg floors at @since (not @rawCutoff) and carries the api-key params
|
|
assert.equal(unifiedParams.since, "2024-06-01T00:00:00.000Z");
|
|
assert.equal(unifiedParams.apiKey0, "k1");
|
|
assert.equal(unifiedParams.rawCutoff, undefined);
|
|
});
|
|
|
|
it("buildPresetUnifiedSource returns the unifiedSource/unifiedParams shape", () => {
|
|
const result = buildPresetUnifiedSource({
|
|
sinceIso: null,
|
|
untilIso: null,
|
|
rawCutoffDate: "2024-06-15",
|
|
apiKeyWhere: "",
|
|
apiKeyParams: {},
|
|
});
|
|
assert.equal(typeof result.unifiedSource, "string");
|
|
assert.equal(typeof result.unifiedParams, "object");
|
|
assert.ok(result.unifiedParams !== null);
|
|
});
|
|
});
|
|
|
|
// ── 2. usageAnalytics.ts — full public API surface preserved ─────────────────
|
|
|
|
const host = await import("../../src/lib/db/usageAnalytics.ts");
|
|
|
|
describe("usageAnalytics.ts public API surface", () => {
|
|
// the 22 runtime functions (the 17 row/param interfaces are type-only and
|
|
// erased at runtime, so they are asserted via typecheck, not here)
|
|
const expectedFns = [
|
|
"buildUnifiedSource", // re-exported from sources
|
|
"buildPresetUnifiedSource", // re-exported from sources
|
|
"getUsageSummary",
|
|
"getDailyUsage",
|
|
"getDailyCostRows",
|
|
"getHeatmapRows",
|
|
"getModelUsageRows",
|
|
"getProviderCostRows",
|
|
"getProviderUsageRows",
|
|
"getAccountCostRows",
|
|
"getAccountUsageRows",
|
|
"getApiKeyUsageRows",
|
|
"getServiceTierUsageRows",
|
|
"getApiKeyMetadataRows",
|
|
"getWeeklyPatternRows",
|
|
"getPresetCostModelRows",
|
|
"getEndpointUsageRows",
|
|
"getAllUsageHistory",
|
|
"getAllDomainCostHistory",
|
|
"getAllDomainBudgets",
|
|
];
|
|
|
|
for (const name of expectedFns) {
|
|
it(`exposes ${name} as a function`, () => {
|
|
assert.equal(typeof host[name], "function", `${name} must be a function on the host module`);
|
|
});
|
|
}
|
|
|
|
it("loses no public runtime function in the split", () => {
|
|
const missing = expectedFns.filter((n) => typeof host[n] !== "function");
|
|
assert.deepEqual(missing, [], `missing: ${missing.join(", ")}`);
|
|
});
|
|
});
|
|
|
|
// ── 3. sources leaf exports the builders directly ────────────────────────────
|
|
|
|
describe("sources.ts exports the builders directly", () => {
|
|
it("buildUnifiedSource / buildPresetUnifiedSource are functions on the leaf", async () => {
|
|
const sources = await import("../../src/lib/db/usageAnalytics/sources.ts");
|
|
assert.equal(typeof sources.buildUnifiedSource, "function");
|
|
assert.equal(typeof sources.buildPresetUnifiedSource, "function");
|
|
});
|
|
});
|