Skip to content

Commit 2e9971d

Browse files
committed
test(cached-adapter-store): rewrite test surface around prime() and middleware-driven trigger
Public-API surface tests (new): - Returned module has exactly {getAll, getById, getOrFailById, generateNew, prime} — five enumerable keys. - `expect(store).not.toHaveProperty('retrieveAll')` — verifies the narrowing. - `expect(store).not.toHaveProperty('retrieveById')` — verifies the narrowing. prime() behavior (new group): - Cold start (localHash null, no header) → exactly one inner fetch. - localHash set but no header → exactly one inner fetch. - Already in sync → no inner fetch. - Mismatch on cold-start with header already seen → fires inner once, persists new hash. - Idempotency: two rapid prime() calls → exactly one inner fetch (in-flight dedup). - Post-success no-op: after successful prime, second prime returns immediately. - Post-success no-op requires localHash !== null — if persist did not happen (no header), second prime CAN fire again (pins the localHash !== null clause of the guard). Middleware-driven trigger (new group): - Response with hash differing from localHash (cold + warm) → middleware fires inner exactly once and updates persisted hash on success. - Response with hash equal to localHash → middleware does NOT fire inner. - Response with header missing/malformed (5a/5b/5c) → middleware does NOT fire inner. prime + middleware race coordination (new group): - Mid-flight response arriving during a prime() call → ONE inner fetch via shared in-flight ref (v1 once-per-burst contract; later mismatches handled by the NEXT header). Persist-after-success timing (rewritten): - ONLY after inner success does storageService.put fire — verified with a pending Promise that holds the inner fetch open so we can assert the negative before resolving. - Inner rejection (prime path) → no persist; rejection surfaces to caller. - Inner rejection (middleware path) → no persist; rejection swallowed (fire-and-forget; no unhandled-rejection escape). Idempotent middleware registration (rewritten): - Existing assertions preserved; entry-point swapped from retrieveAll() to prime(). Parser branches (rewritten): - All malformed-header tests now drive through prime() instead of retrieveAll. Setup-rig comment updated to describe the new entry point. Exception-safe response middleware (Architecture Lock #10, rewritten): - Existing 5a/5b/5c contract-pin tests preserved (no longer chain to a removed retrieveAll on the rig, just verify no-throw on delivery). - 5-success: rewritten to await store.prime() so the assertion rendezvous with the middleware-triggered inner fetch. - NEW: inner.retrieveAll rejection on the middleware path does NOT propagate back through the middleware — verified via `process.on('unhandledRejection', ...)` capturing during microtask drain. types.spec.ts (rewritten): - Asserts the factory's return type is `CachedStoreModuleForAdapter<DemoItem, DemoAdapted, DemoNewAdapted>` (was `StoreModuleForAdapter<...>`). - Adds a `@ts-expect-error` assertion that the wrapper's return is NOT assignable to `StoreModuleForAdapter<...>`. If a future refactor re-adds retrieveAll/retrieveById, the directive becomes unused and tsc errors out. - Type-test body guarded by `if (false as boolean)` so the type-level assignment is checked but the runtime call into the real factory (against an empty config) never executes. Test count: 69 → 80 (+11, well above the order's ≥69 baseline). Coverage: 100% statements/branches/functions/lines on src/cached-adapter-store.ts and src/types.ts. Mutation: 94.81% on cached-adapter-store.ts (≥90% threshold; 4 surviving mutants are documented equivalent — parser try/catch fall-throughs and the post-success hasCompletedAtLeastOnce/early-return optimization, observationally indistinguishable from the unmutated form because skip-when-equal in triggerInnerRetrieveAll catches the same case).
1 parent e130993 commit 2e9971d

2 files changed

Lines changed: 422 additions & 150 deletions

File tree

0 commit comments

Comments
 (0)