diff --git a/development/testing.md b/development/testing.md index 06a1986..5c674d5 100644 --- a/development/testing.md +++ b/development/testing.md @@ -27,8 +27,8 @@ before the implementation. - Runtime-first (classic red/green): it verifies the value, not the contract, and the contract is the product. -- Testing the type only: it would not catch handler wiring, `exhaustive()` - throwing, or the `otherwise` fallback (see `src/index.test.ts`). +- Testing the type only: it would not catch handler dispatch or the `_` + fallback (see `src/primitive.test.ts`). The runner is `node --test --strip-types "src/**/*.test.ts"` and the tiers are in [CONTRIBUTING.md ยง Development commands](../CONTRIBUTING.md#development-commands). @@ -66,7 +66,7 @@ separated by a blank line; an empty block drops its label. ## Known issues - The type-aware linter misidentifies `expectTypeOf()` as a floating promise, so - test files that use it (`src/index.test.ts`, `src/primitive.test.ts`) carry a + test files that use it (`src/primitive.test.ts`) carry a file-level `oxlint-disable typescript/no-floating-promises` with an explanatory comment. It is a known false positive, not a rule worth disabling project-wide (see diff --git a/src/index.test.ts b/src/index.test.ts deleted file mode 100644 index ef6a58e..0000000 --- a/src/index.test.ts +++ /dev/null @@ -1,71 +0,0 @@ -/* oxlint-disable typescript/no-floating-promises -- expectTypeOf() is a sync type-assertion library that the type-aware linter misidentifies as a promise */ -import { strict as assert } from "node:assert"; -import { test } from "node:test"; - -import { expectTypeOf } from "expect-type"; - -import { type Matcher, P, match } from "./index.ts"; - -test("match returns a builder", () => { - // Act - const builder = match("x"); - - // Assert - expectTypeOf(builder).toHaveProperty("with"); - expectTypeOf(builder).toHaveProperty("exhaustive"); - expectTypeOf(builder).toHaveProperty("otherwise"); -}); - -test("P.literal narrows to its literal type", () => { - // Act - const matcher = P.literal("yes"); - - // Assert - expectTypeOf(matcher).toExtend>(); - assert.equal(matcher.matches("yes"), true); - assert.equal(matcher.matches("no"), false); -}); - -test("P.type narrows to the typeof target", () => { - // Act - const matcher = P.type("string"); - - // Assert - expectTypeOf(matcher).toExtend>(); - assert.equal(matcher.matches("hi"), true); - assert.equal(matcher.matches(42), false); -}); - -test("exhaustive() returns the union of handler return types", () => { - // Act - const result = match<"a" | "b">("a") - .with(P.literal("a"), () => 1 as const) - .with(P.literal("b"), () => "two" as const) - .exhaustive(); - - // Assert - expectTypeOf(result).toEqualTypeOf<1 | "two">(); - assert.equal(result, 1); -}); - -test("otherwise() falls back when no case matches", () => { - // Act - const result = match<"x" | "y" | "z">("z") - .with(P.literal("x"), (v): string => `got ${v}`) - .otherwise((v): string => `fallback ${v}`); - - // Assert - assert.equal(result, "fallback z"); -}); - -test("exhaustive throws when no case matches", () => { - // Assert - assert.throws( - () => - match<"a" | "b" | "c">("c") - .with(P.literal("a"), () => "A") - .with(P.literal("b"), () => "B") - .exhaustive(), - /no matching case/, - ); -});