test(ai): settle the ratchets after the empty-chain change

The resolver tests queue their fixture rows through one helper instead of
an `as never` per row, the no-provider status case also proves the
single-provider resolver is never asked, and the size and comment
baselines take the lower numbers the change left behind.
This commit is contained in:
Marc-André Bombeck committed 2026-11-11 20:37:48 +01:00
1 parent 17fd1a0906
commit 1d5236a326
6 files changed
+67 -65

No files matched your search

@@ -1,7 +1,7 @@
{
"$comment": "Production files over 800 lines and their length. Maintained by src/__tests__/source-size-ratchet.test.ts.",
"count": 84,
"total": 94047,
"total": 93880,
"entries": {
"app/medications/page-client.tsx": 839,
"components/charts/mood-chart.tsx": 1166,
@@ -30,7 +30,7 @@
"lib/ai/coach/types.ts": 1008,
"lib/ai/codex-client.ts": 907,
"lib/ai/prompts/insight-generator.ts": 1115,
"lib/ai/provider.ts": 1628,
"lib/ai/provider.ts": 1497,
"lib/analytics/score/reader.ts": 998,
"lib/analytics/sleep-night.ts": 1345,
"lib/analytics/summaries-slice.ts": 1178,
@@ -56,7 +56,7 @@
"lib/import/health-connect/import.ts": 1689,
"lib/import/unzip-export-xml.ts": 825,
"lib/insights/comprehensive-aggregator.ts": 868,
"lib/insights/comprehensive-generate.ts": 1674,
"lib/insights/comprehensive-generate.ts": 1670,
"lib/insights/correlation-channel-series.ts": 1339,
"lib/insights/correlation-discovery.ts": 1240,
"lib/insights/correlations.ts": 1026,
@@ -1,7 +1,7 @@
{
"$comment": "Production functions over 200 lines, keyed \"file :: name\", and their length. Maintained by src/__tests__/source-size-ratchet.test.ts.",
"count": 344,
"total": 111520,
"count": 343,
"total": 111236,
"entries": {
"app/achievements/page.tsx :: AchievementsPage": 206,
"app/api/admin/backups/upload/route.ts :: apiHandler(arg)": 275,
@@ -287,7 +287,7 @@
"lib/import/labs-csv.ts :: importLabsCsv": 307,
"lib/import/labs-csv.ts :: importLabsCsv > flush": 229,
"lib/insights/comprehensive-aggregator.ts :: buildFromRollups": 217,
"lib/insights/comprehensive-generate.ts :: generateComprehensiveInsight": 876,
"lib/insights/comprehensive-generate.ts :: generateComprehensiveInsight": 872,
"lib/insights/features.ts :: extractFeatures": 796,
"lib/insights/mood-aggregates.ts :: fetchMoodAggregates": 246,
"lib/insights/status-provider.ts :: runStatusCompletion": 215,
+3 -3
View File
@@ -1,7 +1,7 @@
{
"$comment": "as never casts in tests, per test file under src/. Maintained by src/__tests__/test-realism-ratchet.test.ts.",
"count": 523,
"total": 5475,
"total": 5464,
"entries": {
"__tests__/api/auth/login/mfa-branch.test.ts": 10,
"__tests__/api/auth/mfa/verify.test.ts": 9,
@@ -196,7 +196,7 @@
"app/api/medications/[id]/intake/import/__tests__/route.test.ts": 9,
"app/api/medications/[id]/schedule-revisions/__tests__/route.test.ts": 24,
"app/api/medications/compliance/__tests__/route.test.ts": 10,
"app/api/medications/extract/__tests__/route.test.ts": 38,
"app/api/medications/extract/__tests__/route.test.ts": 37,
"app/api/medications/intake/__tests__/route.test.ts": 59,
"app/api/medications/intake/bulk/__tests__/dose-arrival-scope.test.ts": 9,
"app/api/medications/intake/bulk/__tests__/route.test.ts": 68,
@@ -300,7 +300,7 @@
"lib/ai/__tests__/provider-reasoning-effort.test.ts": 5,
"lib/ai/__tests__/provider-response-timeout.test.ts": 2,
"lib/ai/__tests__/provider.test.ts": 35,
"lib/ai/__tests__/resolve-chain.test.ts": 12,
"lib/ai/__tests__/resolve-chain.test.ts": 2,
"lib/ai/__tests__/server-provider-health.test.ts": 1,
"lib/ai/capabilities/__tests__/egress.test.ts": 1,
"lib/ai/capabilities/__tests__/gate.test.ts": 1,
@@ -1,7 +1,7 @@
{
"$comment": "Comment lines that open with a release version, per file under src/. Maintained by src/__tests__/version-stamp-ratchet.test.ts.",
"count": 2892,
"total": 9220,
"total": 9217,
"entries": {
"__tests__/account-payload-consumer-guard.test.ts": 2,
"__tests__/acting-account-boundary-guard.test.ts": 7,
@@ -331,7 +331,7 @@
"app/api/insights/ecg/[id]/route.ts": 2,
"app/api/insights/ecg/route.ts": 1,
"app/api/insights/feedback/route.ts": 2,
"app/api/insights/generate/__tests__/route.test.ts": 12,
"app/api/insights/generate/__tests__/route.test.ts": 11,
"app/api/insights/glp1-plateau/route.ts": 2,
"app/api/insights/glp1-timeline/route.ts": 4,
"app/api/insights/health-status/route.ts": 3,
+52 -38
View File
@@ -24,6 +24,17 @@ beforeEach(() => {
vi.resetAllMocks();
});
/** Queue the user rows the resolver reads, in the order it reads them. */
function userRows(...rows: Record<string, unknown>[]) {
const findUnique = vi.mocked(prisma.user.findUnique);
for (const row of rows) findUnique.mockResolvedValueOnce(row as never);
}
/** The operator's settings row. */
function operator(settings: Record<string, unknown>) {
vi.mocked(prisma.appSettings.findUnique).mockResolvedValue(settings as never);
}
describe("resolveProviderChain", () => {
it("returns the default chain when user.aiProviderChain is null", async () => {
vi.mocked(decryptCodexCreds).mockReturnValue({
@@ -32,9 +43,9 @@ describe("resolveProviderChain", () => {
accountId: "acct",
expiresAt: new Date(Date.now() + 3600_000),
});
vi.mocked(prisma.user.findUnique)
userRows(
// user-level config read
.mockResolvedValueOnce({
{
aiProvider: null,
aiModel: null,
aiBaseUrl: null,
@@ -42,19 +53,20 @@ describe("resolveProviderChain", () => {
aiLocalKeyEncrypted: null,
aiOpenaiKeyEncrypted: null,
aiProviderChain: null,
} as never)
},
// codex tokens read
.mockResolvedValueOnce({
{
codexAccessTokenEncrypted: "enc-a",
codexRefreshTokenEncrypted: "enc-r",
codexTokenExpiresAt: new Date(Date.now() + 3600_000),
codexConnectionStatus: "connected",
} as never);
vi.mocked(prisma.appSettings.findUnique).mockResolvedValue({
},
);
operator({
adminAiKeyEncrypted: "enc-admin",
adminAiModel: "gpt-4o-mini",
adminAiBaseUrl: "https://api.openai.com/v1",
} as never);
});
const chain = await resolveProviderChain("user-1");
// Default chain trims out entries with no creds; codex (tokens
@@ -69,7 +81,7 @@ describe("resolveProviderChain", () => {
});
it("respects user-defined chain priority order", async () => {
vi.mocked(prisma.user.findUnique).mockResolvedValueOnce({
userRows({
aiProvider: null,
aiModel: null,
aiBaseUrl: null,
@@ -82,12 +94,12 @@ describe("resolveProviderChain", () => {
{ providerType: "anthropic", priority: 2, enabled: true },
{ providerType: "admin-openai", priority: 3, enabled: false },
],
} as never);
vi.mocked(prisma.appSettings.findUnique).mockResolvedValue({
});
operator({
adminAiKeyEncrypted: "enc-admin",
adminAiModel: "gpt-4o-mini",
adminAiBaseUrl: "https://api.openai.com/v1",
} as never);
});
const chain = await resolveProviderChain("user-1");
const types = chain.map((c) => c.providerType);
@@ -95,7 +107,7 @@ describe("resolveProviderChain", () => {
});
it("filters out chain entries the user has not credentialed", async () => {
vi.mocked(prisma.user.findUnique).mockResolvedValueOnce({
userRows({
aiProvider: null,
aiModel: null,
aiBaseUrl: null,
@@ -106,12 +118,12 @@ describe("resolveProviderChain", () => {
{ providerType: "anthropic", priority: 1, enabled: true },
{ providerType: "openai", priority: 2, enabled: true },
],
} as never);
vi.mocked(prisma.appSettings.findUnique).mockResolvedValue({
});
operator({
adminAiKeyEncrypted: null,
adminAiModel: "gpt-4o-mini",
adminAiBaseUrl: "https://api.openai.com/v1",
} as never);
});
const chain = await resolveProviderChain("user-1");
const types = chain.map((c) => c.providerType);
@@ -119,7 +131,7 @@ describe("resolveProviderChain", () => {
});
it("skips disabled entries even if the credential is present", async () => {
vi.mocked(prisma.user.findUnique).mockResolvedValueOnce({
userRows({
aiProvider: null,
aiModel: null,
aiBaseUrl: null,
@@ -130,12 +142,12 @@ describe("resolveProviderChain", () => {
{ providerType: "openai", priority: 1, enabled: false }, // disabled
{ providerType: "admin-openai", priority: 2, enabled: true },
],
} as never);
vi.mocked(prisma.appSettings.findUnique).mockResolvedValue({
});
operator({
adminAiKeyEncrypted: "enc-admin",
adminAiModel: "gpt-4o-mini",
adminAiBaseUrl: "https://api.openai.com/v1",
} as never);
});
const chain = await resolveProviderChain("user-1");
const types = chain.map((c) => c.providerType);
@@ -143,8 +155,8 @@ describe("resolveProviderChain", () => {
});
it("returns an empty array when nothing is configured at all", async () => {
vi.mocked(prisma.user.findUnique)
.mockResolvedValueOnce({
userRows(
{
aiProvider: null,
aiModel: null,
aiBaseUrl: null,
@@ -152,18 +164,19 @@ describe("resolveProviderChain", () => {
aiLocalKeyEncrypted: null,
aiOpenaiKeyEncrypted: null,
aiProviderChain: null,
} as never)
.mockResolvedValueOnce({
},
{
codexAccessTokenEncrypted: null,
codexRefreshTokenEncrypted: null,
codexTokenExpiresAt: null,
codexConnectionStatus: "disconnected",
} as never);
vi.mocked(prisma.appSettings.findUnique).mockResolvedValue({
},
);
operator({
adminAiKeyEncrypted: null,
adminAiModel: "gpt-4o-mini",
adminAiBaseUrl: "https://api.openai.com/v1",
} as never);
});
const chain = await resolveProviderChain("user-1");
expect(chain).toEqual([]);
@@ -173,7 +186,7 @@ describe("resolveProviderChain", () => {
// Only the local model on, its address missing; the person's own key and
// the operator's key are both switched off. Nothing may serve behind those
// switches, however the record's single provider field reads.
vi.mocked(prisma.user.findUnique).mockResolvedValueOnce({
userRows({
aiProvider: "OPENAI",
aiModel: null,
aiBaseUrl: null,
@@ -185,12 +198,12 @@ describe("resolveProviderChain", () => {
{ providerType: "openai", priority: 2, enabled: false },
{ providerType: "admin-openai", priority: 3, enabled: false },
],
} as never);
vi.mocked(prisma.appSettings.findUnique).mockResolvedValue({
});
operator({
adminAiKeyEncrypted: "enc-admin",
adminAiModel: "gpt-4o-mini",
adminAiBaseUrl: "https://api.openai.com/v1",
} as never);
});
expect(await resolveProviderChain("user-1")).toEqual([]);
});
@@ -208,26 +221,27 @@ describe("resolveProviderChain", () => {
aiCompatModel: "llama-3",
role: "USER",
};
vi.mocked(prisma.user.findUnique)
.mockResolvedValueOnce({ ...gatewayRow, aiProviderChain: null } as never)
.mockResolvedValueOnce({
userRows(
{ ...gatewayRow, aiProviderChain: null },
{
codexAccessTokenEncrypted: null,
codexRefreshTokenEncrypted: null,
codexTokenExpiresAt: null,
codexConnectionStatus: "disconnected",
} as never);
vi.mocked(prisma.appSettings.findUnique).mockResolvedValue({
},
);
operator({
adminAiKeyEncrypted: null,
} as never);
});
const chain = await resolveProviderChain("user-1");
expect(chain.map((c) => c.providerType)).toEqual(["openai-compatible"]);
// A saved chain without the gateway is the person's word.
vi.mocked(prisma.user.findUnique).mockResolvedValueOnce({
userRows({
...gatewayRow,
aiProviderChain: [{ providerType: "local", priority: 1, enabled: true }],
} as never);
});
expect(await resolveProviderChain("user-1")).toEqual([]);
});
});
@@ -167,22 +167,6 @@ describe("runStatusCompletion — capability at the wire", () => {
expect(ledgerTotal).toBe(0);
});
it("sends nothing on an empty chain, whatever the single-provider resolver holds", async () => {
// The chain carries the person's provider switches; an empty one is no
// provider, never a quiet hop to one they switched off.
resolveProviderChain.mockResolvedValue([]);
resolveProvider.mockResolvedValue({ type: "admin-key" });
const outcome = await runStatusCompletion(
completionArgs({ capability: "statusText" }) as never,
);
expect(outcome).toEqual({ kind: "none", reason: "no_provider" });
expect(resolveProvider).not.toHaveBeenCalled();
expect(runRawCompletionWithFallback).not.toHaveBeenCalled();
expect(ledgerTotal).toBe(0);
});
it("re-checks exactly the resolved chain and refuses before any budget or provider work", async () => {
resolveProviderChain.mockResolvedValue([
{ providerType: "anthropic", instance: {} },
@@ -240,9 +224,13 @@ describe("runStatusCompletion — capability at the wire", () => {
});
it("returns none with reason no_provider when the chain is empty", async () => {
// The chain carries the person's provider switches; an empty one is no
// provider, never a quiet hop to the single-provider resolver's pick.
resolveProviderChain.mockResolvedValue([]);
resolveProvider.mockResolvedValue({ type: "admin-key" });
const outcome = await runStatusCompletion(completionArgs() as never);
expect(outcome).toEqual({ kind: "none", reason: "no_provider" });
expect(resolveProvider).not.toHaveBeenCalled();
expect(runRawCompletionWithFallback).not.toHaveBeenCalled();
});
});