React Forum
Blog & Guide Responses
Jul 09, 2022 · 04:00 AM

Playwright Intro - discussion (2022-07-09)

Started by Noah Vance
externalplaywrighttestinge2esignals

We're trying to get serious about route-flow testing and we keep bouncing between "test like a user" and "assert the contract" styles.

Read the docs

If your app renders signals (nav, fetch, cache lanes), do you assert on those directly in E2E tests? How do you keep Playwright tests stable when the UI changes but behavior shouldn't? And what do you do to debug flake (traces, screenshots, deterministic data, signals)?

Comments (10)

Back to latest
Maya Henson
Jul 09, 2022 · 04:06 AM

If it's flaky, it's usually data. I try to make data deterministic before I fight selectors.

Dmitri Kline
Jul 09, 2022 · 04:14 AM

I assert on signals for the "why", not the "what".

Example: assert the user sees the right screen using roles/text, then assert navIntent.reason or cacheLane to prove the contract path.

We borrowed the pattern from Testing and Debugging.

Salma Qureshi
Jul 09, 2022 · 04:22 AM

Our most stable tests do both: user-facing assertions + signal assertions.

ts
test('checkout route contract', async ({ page }) => {
  await page.goto('/checkout');
  await expect(page.getByRole('heading', { name: /checkout/i })).toBeVisible();

  const nav = await page.getAttribute('[data-signal="navIntent"]', 'data-value');
  expect(JSON.parse(nav ?? 'null')).toMatchObject({ to: 'checkout' });
});

If the UI changes, the heading assertion might need updates, but the signal assertion catches accidental behavior drift.

Keira Santos
Jul 09, 2022 · 04:31 AM

Counterpoint: signals can turn tests into "assert internal state" and you stop noticing broken UX.

We require at least one focus/a11y assertion per flow (focus trap, modal close, keyboard nav), then signals for routing/fetch behavior.

Noah Vance
Jul 09, 2022 · 04:36 AM

That makes sense. The failures we're seeing are mostly "why did it refetch twice" and "why did it redirect", not "button label changed".

So signals feel like the right tool for the hard part, but we shouldn't lose UX coverage.

Keira Santos
Jul 09, 2022 · 04:39 AM

Yep. Use signals to explain behavior, not as the only truth you test.

Theo Bennett
Jul 09, 2022 · 04:44 AM

Playwright traces are the only thing that made us stop arguing about flake.

But you still need contracts to make the trace explainable.

Hana Saito
Jul 09, 2022 · 04:52 AM

We reduced selector fragility by leaning on roles, but the big win was stable signals.

If fetchSignal says status=ready, we don't have to guess whether a spinner was supposed to disappear yet.

Amina Farouk
Jul 09, 2022 · 05:03 AM

We had a back/forward bug that only reproduced in E2E because it depended on a popstate path no one clicked manually.

Once we rendered navIntent and historySignal, the test failures became actionable instead of spooky.

Jules Kwon
Jul 09, 2022 · 05:15 AM

If you can, build a single test helper that reads signals, so tests don't import internal modules.

Keeping it as DOM data makes it feel more like behavior than implementation.

Inez Park
Jul 09, 2022 · 05:27 AM

When a test fails, a screenshot + signals should already tell you what happened. If it can't, add one signal, don't add ten waits.

Benji Rios
Jul 09, 2022 · 05:41 AM

Treat your signal schema like API and tests like clients.

If you change signal shape casually, you just moved the instability from selectors to signals.