From 0886595c29f96823d845654aaeee7cad188ce898 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 27 Aug 2026 00:55:12 +0000 Subject: [PATCH] test(rest): pay down 17 of the test-typecheck ledger's 37 errors Two annotation-only classes, both repaired in the form this package's already-green test files use: - TS18048 x13, all in `export-integration.test.ts`: `getRoutes().find()` is `Route | undefined`, so every `route.handler(...)` below read as possibly-undefined. Asserted non-null at the two lookup sites rather than at the thirteen call sites. `!` erases, so no call receives a different value than it did before. - TS7006 x4: `ReturnType` leaves `mock.calls` untyped, so each `.map`/`.filter` callback parameter was implicitly `any`. Annotated `unknown[]`, the form `rest-5xx-status-passthrough.test.ts` already uses. Ledger regenerated, not hand-edited: four entries reach zero and are deleted, `export-integration.test.ts` re-records 17 -> 4. 37 -> 20 errors across 13 -> 9 files. No number is raised. The remaining 20 are NOT repaired, on purpose: they need a fixture's data or a producer's signature changed, not an annotation. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UjujZN219uFzBhSYfMykCd --- .../analytics-read-scope-refusal-envelope.test.ts | 2 +- packages/rest/src/export-integration.test.ts | 13 +++++++++++-- .../rest/src/rest-expected-error-logging.test.ts | 2 +- packages/rest/src/rest-meta-outage-vs-miss.test.ts | 2 +- .../rest/src/rest-unclassified-fault-status.test.ts | 2 +- packages/rest/test-typecheck-debt.json | 6 +----- 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/packages/rest/src/analytics-read-scope-refusal-envelope.test.ts b/packages/rest/src/analytics-read-scope-refusal-envelope.test.ts index 5596876ab3..6058105940 100644 --- a/packages/rest/src/analytics-read-scope-refusal-envelope.test.ts +++ b/packages/rest/src/analytics-read-scope-refusal-envelope.test.ts @@ -222,7 +222,7 @@ describe('[#5367] POST /analytics/dataset/query — a read-scope failure is a 50 // …and it is in the LOG, which is now its only destination. Asserted rather // than assumed: "withheld" is only acceptable because the operator still // has the whole thing. - const logged = logSpy.mock.calls.map((args) => args.map(String).join(' ')).join('\n'); + const logged = logSpy.mock.calls.map((args: unknown[]) => args.map(String).join(' ')).join('\n'); expect(logged).toMatch(/Analytics dataset query error/); expect(logged).toContain('read-scope-sql'); expect(logged).toContain(c.secret); diff --git a/packages/rest/src/export-integration.test.ts b/packages/rest/src/export-integration.test.ts index a743115955..3673495f35 100644 --- a/packages/rest/src/export-integration.test.ts +++ b/packages/rest/src/export-integration.test.ts @@ -144,9 +144,17 @@ async function boot() { const rest = new RestServer(createMockServer() as any, protocol as any, { api: { requireAuth: false } } as any); (rest as any).resolveExecCtx = async () => ({ userId: 'test-user' }); rest.registerRoutes(); + // [#12573] `Array.prototype.find` is `Route | undefined`, so every + // `route.handler(...)` below read as possibly-undefined (TS18048 x13). + // Asserted non-null HERE, once, rather than at each call site: the + // lookup either finds the registered route or the boot is broken, and + // `registerRoutes()` two lines up is what guarantees it. Same form the + // green siblings in this package already use (e.g. + // `analytics-dataset-where-gate.test.ts`). Type-level only — `!` erases, + // so no call below receives a different value than it did before. const route = rest.getRoutes().find( (r: any) => r.method === 'GET' && r.path === '/api/v1/data/:object/export', - ); + )!; return { engine, protocol, route }; } @@ -394,9 +402,10 @@ describe('export route — FLS column projection via getReadableFields (#3547)', ); (rest as any).resolveExecCtx = async () => ({ userId: 'test-user' }); rest.registerRoutes(); + // [#12573] Non-null for the same reason as `boot()` above. const route = rest.getRoutes().find( (r: any) => r.method === 'GET' && r.path === '/api/v1/data/:object/export', - ); + )!; return { engine, route }; } diff --git a/packages/rest/src/rest-expected-error-logging.test.ts b/packages/rest/src/rest-expected-error-logging.test.ts index 58f322dcea..f923766850 100644 --- a/packages/rest/src/rest-expected-error-logging.test.ts +++ b/packages/rest/src/rest-expected-error-logging.test.ts @@ -110,7 +110,7 @@ async function callDataList(rest: any, object: string) { let errorSpy: ReturnType; /** Only the "[REST] Unhandled error" channel — other console.error noise is not this test's business. */ -const unhandledLogs = () => errorSpy.mock.calls.filter((c) => c[0] === '[REST] Unhandled error:'); +const unhandledLogs = () => errorSpy.mock.calls.filter((c: unknown[]) => c[0] === '[REST] Unhandled error:'); beforeEach(() => { errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); }); afterEach(() => { errorSpy.mockRestore(); }); diff --git a/packages/rest/src/rest-meta-outage-vs-miss.test.ts b/packages/rest/src/rest-meta-outage-vs-miss.test.ts index 259864803c..c0ba44c133 100644 --- a/packages/rest/src/rest-meta-outage-vs-miss.test.ts +++ b/packages/rest/src/rest-meta-outage-vs-miss.test.ts @@ -95,7 +95,7 @@ let errorSpy: ReturnType; beforeEach(() => { errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); }); afterEach(() => { errorSpy.mockRestore(); }); -const loggedText = () => errorSpy.mock.calls.map((c) => JSON.stringify(c.map(String))).join('\n'); +const loggedText = () => errorSpy.mock.calls.map((c: unknown[]) => JSON.stringify(c.map(String))).join('\n'); describe('[#5532] an unreadable metadata store reaches the client as a retryable 503', () => { it('503 + SERVICE_UNAVAILABLE, and the prose is withheld', async () => { diff --git a/packages/rest/src/rest-unclassified-fault-status.test.ts b/packages/rest/src/rest-unclassified-fault-status.test.ts index 3d2c0e3c3a..a46e4c50e6 100644 --- a/packages/rest/src/rest-unclassified-fault-status.test.ts +++ b/packages/rest/src/rest-unclassified-fault-status.test.ts @@ -118,7 +118,7 @@ beforeEach(() => { errorSpy = vi.spyOn(console, 'error').mockImplementation(() = afterEach(() => { errorSpy.mockRestore(); }); /** Everything the error channel printed, flattened for substring searching. */ -const loggedText = () => errorSpy.mock.calls.map((c) => JSON.stringify(c.map(String))).join('\n'); +const loggedText = () => errorSpy.mock.calls.map((c: unknown[]) => JSON.stringify(c.map(String))).join('\n'); // --------------------------------------------------------------------------- // The unit: mapDataError's terminal branch diff --git a/packages/rest/test-typecheck-debt.json b/packages/rest/test-typecheck-debt.json index ee248d0c1a..685eb62539 100644 --- a/packages/rest/test-typecheck-debt.json +++ b/packages/rest/test-typecheck-debt.json @@ -1,17 +1,13 @@ { "_comment": "Per-file tsc error debt of the @objectstack/rest TEST layer (#5286). `tsconfig.test.json` compiles `src/**/*.test.ts` — which `tsconfig.json` excludes and therefore no gate ever read — and every file below still carries errors from before that gate existed, almost all of them fixture literals annotated with a schema OUTPUT type (`z.infer`) while holding an authored INPUT literal. EXACT ratchet, judged by re-running tsc: a file that gains errors is red, a file that loses them is red until its number is re-recorded, a file that reaches zero is red until its entry is deleted, and a file NOT listed here may have no errors at all. Regenerate with: pnpm --filter @objectstack/rest gen:test-typecheck-debt", "entries": { - "src/analytics-read-scope-refusal-envelope.test.ts": 1, - "src/export-integration.test.ts": 17, + "src/export-integration.test.ts": 4, "src/import-dryrun-parity.test.ts": 1, "src/import-integration.test.ts": 3, "src/import-job-integration.test.ts": 2, "src/meta-public-book-grant.test.ts": 1, "src/rest-batch-size-cap.test.ts": 1, - "src/rest-expected-error-logging.test.ts": 1, - "src/rest-meta-outage-vs-miss.test.ts": 1, "src/rest-meta-save-receipt-envelope.test.ts": 3, - "src/rest-unclassified-fault-status.test.ts": 1, "src/rest-write-response-formula.test.ts": 1, "src/rest.test.ts": 4 }