Skip to content

v1.12.0

Choose a tag to compare

@kevinccbsg kevinccbsg released this 19 Oct 08:16
· 17 commits to main since this release

Faster and more deterministic request mocking. On real suites of 300 to 550 tests, run time dropped by about 20% and CI retries went to zero.

Update your service worker

npx twd-js init public

The speedups need the new mock-sw.js. With an outdated one everything keeps working as before, without the speedup: each mockRequest waits 100ms and the page warns once in the console.

mockRequest no longer sleeps 100ms

Every twd.mockRequest() used to end with a fixed 100ms sleep, a guess at how long the service worker needs to store the rule. It cost 100ms per mock on every machine, and on a slow CPU the guess could be wrong and the request went out unmocked.

Now the service worker confirms each rule, and mockRequest resolves as soon as it is stored: about 1ms, and it keeps waiting while the worker is busy instead of guessing.

waitForRequest resolves when the request happens

It used to check every 100ms, so each call waited ~50ms on average after the request had already happened. Now it resolves on the hit itself, plus two frames for the response to reach the app.

It guarantees the request happened, not that the UI has updated. If your app processes the response asynchronously, wait for the screen with findBy* or twd.waitFor:

await twd.waitForRequest("filtered");
await twd.waitFor(() => expect(screenDom.queryAllByText("old.csv").length).to.equal(0));

3000ms defaults, like findBy*

twd.waitForRequest() now waits up to 3000ms by default (was 1000ms), and twd.url().should() up to 3000ms (was 500ms). Both were too short for a slow CI runner. Passing tests are not slower, and explicit retries / retryDelay are respected.

If a test turns flaky after upgrading

The old 100ms sleep gave async work your test did not await time to finish, by luck: a logout() or storage cleanup in beforeEach, a helper at the end of a test. Without it, that work can land in the middle of the next steps. Await it:

beforeEach(async () => {
  await logout();
});

@typescript-eslint/no-floating-promises on your test files catches it.

Also in this release

  • A throwing afterEach no longer ends the run. It fails that test, which is retried like any failure, and the run continues. A passing test whose afterEach throws is no longer reported as passed.
  • Re-mocking an alias is reliable. A late request for a replaced rule can no longer mark the new rule as executed.
  • twd.url().should() retries work. An assertion that failed once and passed on a retry used to throw anyway.
  • mock-sw.js is readable. Built unminified, with a header naming the version and how to regenerate it.
  • Docs: findBy* is the default query, with the expected state in the query (findByRole("button", { name: "2", current: "page" })); getRequestCount can lag one hit behind the UI, so check it inside twd.waitFor.
  • Dependencies: dev tooling updates (vitest, jsdom, typescript-eslint, @vitejs/plugin-react, globals).

Full changelog: v1.11.0...v1.12.0