/** * Spec-conformance — type-level pins for the generic threading on * {@link TestEnvironment}, {@link HealthPoller}, and the public * {@link createIntegrationSetup}/{@link skipIfUnavailable} façade. * * These tests exist purely to fail at compile time if the generics * regress. They emit no runtime assertions other than a single * `expectTypeOf(...).toEqualTypeOf<…>()` per scenario. */ import { describe, expectTypeOf, it } from "@suaveplan/testing/runner"; import type { ServiceFixture } from "../fixture/service-fixture.js"; import { HealthPoller } from "../helpers/health-poller.js"; import { skipIfUnavailable } from "../helpers/skip-if-unavailable.js"; import { createIntegrationSetup } from "../setup/create-integration-setup.js"; import { TestEnvironment } from "./test-environment.js"; interface RedisConfig extends Record { url: string; host: string; port: number; } interface PostgresConfig extends Record { url: string; database: string; } const fakeRedis: ServiceFixture = { name: "redis", start: async () => ({ url: "r", host: "h", port: 1 }), stop: async () => {}, healthCheck: async () => true, }; const fakePg: ServiceFixture = { name: "postgres", start: async () => ({ url: "p", database: "d" }), stop: async () => {}, healthCheck: async () => true, }; const fixtures = { redis: fakeRedis, postgres: fakePg }; describe("TestEnvironment generic conformance", () => { it("setup() configs[K] is the precise fixture TConfig", { timeout: 5000, }, async () => { const env = new TestEnvironment(fixtures); const result = await env.setup(); expectTypeOf(result.configs.redis).toEqualTypeOf< RedisConfig | undefined >(); expectTypeOf(result.configs.postgres).toEqualTypeOf< PostgresConfig | undefined >(); expectTypeOf(result.failed).toEqualTypeOf(); await env.teardown(); }); it("default generic parameter keeps existing call sites compiling", { timeout: 5000, }, () => { // Equivalent to pre-generic call sites; should still typecheck. const env: TestEnvironment = new TestEnvironment( {} as Record>> ); expectTypeOf(env).toMatchTypeOf(); }); }); describe("HealthPoller.poll generic conformance", () => { it("accepts any ServiceFixture without widening cast", { timeout: 5000, }, async () => { const poller = new HealthPoller({ timeoutMs: 1, intervalMs: 1, sleep: async () => {}, }); // Compile-time check: precise TConfig is preserved. const fn = poller.poll; expectTypeOf(fn).parameters.toMatchTypeOf< [Pick, "name" | "healthCheck">] >(); await poller.poll(fakeRedis); }); }); describe("createIntegrationSetup typed inject() conformance", () => { it("inject(key) returns the precise per-fixture config type", { timeout: 5000, }, () => { const { inject } = createIntegrationSetup(fixtures); expectTypeOf(inject).parameter(0).toEqualTypeOf<"redis" | "postgres">(); expectTypeOf< ReturnType> >().toEqualTypeOf(); expectTypeOf< ReturnType> >().toEqualTypeOf(); }); }); describe("skipIfUnavailable typed-name conformance", () => { it("constrains fixtureName via TName generic", { timeout: 5000 }, () => { type Names = "redis" | "postgres"; const cb = skipIfUnavailable("redis"); expectTypeOf(cb).toMatchTypeOf<(ctx: { skip: () => void }) => void>(); }); });