ux

Click a link and assert the next page

The smallest useful UX test: open the sample UI, click a nav link, and assert the destination. Compare Playwright and Cypress on the same js-ui pages.

SUT: js-ui · id: ux.navigate-and-assert

Cached CI results from 10/3/2026, 10:14:14 AM (ci · d7784ca)

Testing tool

Playwright · Browser UX / E2E runner · Apache-2.0

Playwright launches a real browser (Chromium here), gives you a page object, and uses locators plus expect() to assert what the user sees. Traces and auto-waiting make flaky clicks easier to debug than raw WebDriver.

webServer starts samples/js-ui. Each test opens a page, interacts through roles and CSS, and asserts URL or visible text. The SUT is HTML/CSS/JS in the browser — not an imported function.

Testing architecture

UX / E2E tests drive a real browser against samples/js-ui. The test is a user path: click a link or submit a form, then assert what appears on screen or in the URL. Failures point at markup, CSS, or client JS — not at a unit-tested helper alone.

A real Chromium (Playwright) or Electron/Chrome (Cypress) loads samples/js-ui over HTTP. The test clicks the About link like a user, then asserts the URL contains about.html and the h1 is “About this counter”. No unit-style imports — the browser is the client.

SUT: js-ui · samples/js-ui/public/index.html · run npm test in examples/ux/navigate-and-assert/playwright

Code under test · samples/js-ui/public/index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Counter · js-ui</title>
    <link rel="stylesheet" href="./styles.css" />
  </head>
  <body>
    <header>
      <!-- Primary nav: UX tests click these links and assert the next URL/heading -->
      <a href="./index.html">Home</a>
      <a href="./about.html">About</a>
      <a href="./signup.html">Sign up</a>
    </header>
    <main>
      <h1>Counter</h1>
      <p>A tiny UI used as the system under test for UX examples.</p>
      <p>Count: <output id="count">0</output></p>
      <button type="button" id="increment">Increment</button>
    </main>
    <script src="./app.js"></script>
  </body>
</html>
Test · examples/ux/navigate-and-assert/playwright/navigate.spec.js · Apache-2.0 · run in examples/ux/navigate-and-assert/playwright: npm test
// Playwright browser test — real Chromium, not APIRequest
import { test, expect } from "@playwright/test";

test("clicking About shows the about heading", async ({ page }) => {
  // Load the home page served by samples/js-ui
  await page.goto("./index.html");
  // Click the same nav control a user would
  await page.getByRole("link", { name: "About" }).click();
  // URL and heading are the observable UX contract
  await expect(page).toHaveURL(/about\.html/);
  await expect(page.getByRole("heading", { name: "About this counter" })).toBeVisible();
});

Playwright starts samples/js-ui via webServer, then drives Chromium.