BACK
Use casesMarble test typeahead — verifying debounce/switchMap
Use cases · 65

Marble test typeahead — verifying debounce/switchMap

Pattern

Typeahead depends on TIME (debounce) and on CANCELLATION (switchMap). Testing it with setTimeout and real timers is slow and flaky on CI. Marble tests give virtual time: 100ms passes instantly, but the stream "thinks" 100ms went by.

The problem it solves

If a test waits 300 real ms, on a busy CI it can hang or produce a flaky result. And you want to test the ALGORITHM's idea (cancelled the old request, handled the last one), not real time.

Operators and why they matter

  • TestScheduler — gives virtual time. debounce, timer, interval run instantly on that scale.
  • Input marble string ('-a-ab--abc') — describes events on a timeline.
  • Expected marble — describes the expected result, including exactly when it should arrive.

Gotchas

  • Real timers in debounce tests are a recipe for flaky tests. Passes locally, fails on CI.
  • The mock HTTP must be a cold observable, so switchMap cancellation is actually tested.
  • Marbles check not just the values but the TIMING of emissions. A test "received abc" doesn't cover "cancelled a and ab".

What you get

Typeahead timing becomes a deterministic test contract. Tests are fast and stable.

script.ts // TypeScript
CONSOLE · Console output
Hit Run to see the result...