TraceShift

Master Playwright trace debugging and eliminate flaky tests for good. Hands-on HTMX hypermedia mentorship from a practitioner who's...
City of Muntinlupa, PH
•Created byProfile picturewiryamount
1 joined
Profile picture
@wiryamountProfile pictureJun 10
Pinned post

Welcome to TraceShift — What You'll Learn

TraceShift teaches you to diagnose and eliminate flaky E2E tests using Playwright's trace viewer, with specialized techniques for HTMX applications.


Course Structure


  • Chapter 1: Foundations — understand WHY tests flake

  • Chapter 2: Trace Viewer Deep Dive — master the diagnostic tool

  • Chapter 3: Diagnosing Flaky Failures — timing, network, DOM races, console logs

  • Chapter 4: Fixing Strategies — deterministic locators, HTMX wait helpers, isolation, smart retries

  • Chapter 5: CI Hardening — trace-on-failure config, dashboards, flake budgets

  • Chapter 6: Final Assessment — 8-question knowledge check (75% to pass, certificate on completion)


The course includes a community chat for sharing traces and discussing edge cases, plus an updates feed for new content and resources.


Start with Chapter 1, bring a real flaky test from your codebase, and let's fix it.

Profile picture
@wiryamountProfile pictureJun 10

The 3 Playwright Trace Patterns That Diagnose 80% of Flaky HTMX Tests

Most flaky test debugging starts with "just add a sleep" and ends with a longer sleep. Here are three trace viewer patterns that actually tell you what's wrong.


Pattern 1: The Swap-Settle Gap


What you see: Your assertion fires between htmx:afterSwap and htmx:afterSettle. The DOM snapshot shows the element exists but has intermediate content.


What it means: HTMX has swapped the HTML into the DOM, but CSS transitions haven't completed. Playwright sees the element as "visible" and runs your assertion against half-baked state.


The fix: Wait for settle, not swap.


const settlePromise = page.evaluate(() =>
  new Promise(resolve => {
    document.body.addEventListener('htmx:afterSettle', resolve, { once: true });
  })
);
await page.click('#my-button');
await settlePromise;


Pattern 2: The Missing Network Response


What you see: The Network panel shows a request to your HTMX endpoint that either times out or returns a 500. The Console tab shows htmx:responseError.


What it means: The server request failed, so the swap never happened. Your test asserts on DOM content that was never updated.


The fix: Intercept the route and return deterministic HTML.


await page.route('/api/my-endpoint', route =>
  route.fulfill({
    status: 200,
    contentType: 'text/html',
    body: '<div id="target">Expected Content</div>'
  })
);


Pattern 3: The OOB Race


What you see: The main swap target has correct content, but an out-of-band target (hx-swap-oob) still shows stale data at assertion time.


What it means: OOB swaps execute after the main swap but within the same microtask. Asserting on an OOB target immediately after the main swap means you're racing the OOB processing.


The fix: Wait for the DOM to fully stabilize.


await page.waitForFunction(() =>
  !document.querySelector('.htmx-settling') &&
  !document.querySelector('.htmx-swapping')
);


---


These three patterns account for the vast majority of HTMX-related test flakes. Learn to spot them in the trace viewer and you'll stop guessing forever.