Skip to content

test: add tests for NonExhaustiveError, otherwise, and combined patterns#350

Open
matannturgeman wants to merge 6 commits intogvergnaud:mainfrom
matannturgeman:test/non-exhaustive-error-otherwise-combining-patterns
Open

test: add tests for NonExhaustiveError, otherwise, and combined patterns#350
matannturgeman wants to merge 6 commits intogvergnaud:mainfrom
matannturgeman:test/non-exhaustive-error-otherwise-combining-patterns

Conversation

@matannturgeman
Copy link
Copy Markdown

Summary

  • tests/non-exhaustive-error.test.ts (new, 14 tests): covers NonExhaustiveError throwing behavior, message formatting for all value types (string, number, object, array, null, circular references), the .input property, and instanceof checks
  • tests/otherwise.test.ts (expanded 1 → 12 tests): handler not called on match, fallthrough behavior, multiple .with() chains, type inference, undefined return, and throw support
  • tests/combining-patterns.test.ts (new, 16 tests): combinations of P.select() + guard, P.intersection(), P.optional(), P.array(), P.union(), and P.not() — including a test that documents the OR semantics of multiple patterns per .with()

No source changes — tests only.

Test plan

  • All 50 test suites pass (494 tests)
  • New tests cover both runtime behavior and TypeScript type inference

matannturgeman and others added 6 commits April 14, 2026 14:17
- tests/non-exhaustive-error.test.ts: 14 tests covering error throwing,
  message formatting (string/number/object/array/null/circular refs),
  the .input property, and instanceof checks
- tests/otherwise.test.ts: expand from 1 to 12 tests covering handler
  not called on match, fallthrough, multiple .with() chains, type
  inference, and throw support
- tests/combining-patterns.test.ts: 16 tests for combining P.select(),
  P.when() guards, P.intersection(), P.optional(), P.array(), P.union(),
  and P.not() together; also documents OR semantics of multiple patterns
  per .with()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers gaps not in record.test.ts:
- isMatching with P.record (curried form, type narrowing, as filter)
- P.when / P.not in value position
- P.record inside P.union
- Null-prototype objects (Object.create(null))
- Records with undefined/null values
- Named select in both key and value simultaneously
- Documents that empty-record selections are undefined (no entries to iterate)
- Documents runtime behavior of invalid key pattern (P.array() FIXME)
- Prototype properties are ignored (Reflect.ownKeys only checks own keys)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers gaps not in is-matching.test.ts:
- All primitive wildcards (P.string, P.boolean, P.bigint, P.symbol, P.nullish, P._)
- P.not and P.when as standalone patterns with type narrowing
- P.optional for present/absent/wrong-type fields
- String predicates: startsWith, endsWith, includes, regex
- Number predicates: gt, lt, between, int, positive, negative
- Tuple patterns including nested and type narrowing
- P.instanceOf including subclass handling
- P.set and P.map patterns
- P.select behavior: isMatching returns boolean, selections are not surfaced
- Composing isMatching as Array.filter/find predicates and logical AND

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers gaps not in variadic-tuples.test.ts:
- isMatching with variadic patterns ([head, ...rest], [...rest, tail],
  [head, ...mid, tail]) including type narrowing
- Named select at head + variadic + tail with 0, 1, and N middle elements
- Nested object patterns inside variadic arrays with P.select
- P.when guard inside variadic array elements
- Multiple ...P.array() in one pattern throws the expected error
- .select() chain method on variadic array (empty and non-empty middle)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers gaps not in large-exhaustive.test.ts:
- Runtime matching of all 26 BigUnion members, one-by-one
- P.union() groups covering a large union, verifying runtime + missing group throws
- P._ and P.string as catch-alls completing exhaustiveness
- 10-variant discriminated object union with full and partial coverage
- Cross-product exhaustiveness (two fields, each multi-member union)
- Mixed-type union (string | number | boolean | null | object variants)

Each "not exhaustive" test validates both the @ts-expect-error compile check
and that .exhaustive() throws NonExhaustiveError at runtime.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
run.test.ts (9 tests):
- Dedicated tests for .run() as an alias for .exhaustive()
- Covers: matched value, NonExhaustiveError on no match, .input property,
  first-branch-wins, object patterns, P.select(), type inference, and
  equivalence with .exhaustive()

real-world-2.test.ts (18 tests):
- Fetch state machine: idle/loading/success/error transitions using
  nested object patterns and .otherwise() for invalid transitions
- Command parser: tuple patterns to parse CLI-like string commands
  including get/set/delete/list with P.select() extractions
- API response normalizer: isMatching as a type guard inside P.when()
  to validate and normalize unknown API responses with field stripping

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant