All challenges · Core Interactions

Challenge 9 of 29 · Building fluency · Core Interactions

Test Form Error Messages

Good tests cover failure too. Submit a form with wrong details on purpose; the hidden check confirms the page shows the right error.

Skills you will practise

  • negative paths
  • label locators
  • form submission

The concept

Happy-path tests prove a feature works when everything goes right. Users, though, mistype passwords, leave fields blank and paste emails with spaces. Negative-path tests check that the application responds sensibly: it shows a clear error, it does not log anyone in, and it does not lose what they typed.

The pattern is the same as a normal form test, with deliberately wrong input. The important part is the assertion. Check the specific error text, and ideally that it is exposed accessibly, for example in an element with role="alert" or linked to the field through aria-describedby.

Also assert what should not happen: no redirect to the dashboard, no success message.

The fragile version

Fragile
await page.getByLabel('Password').fill('wrong');
await page.getByRole('button', { name: 'Sign in' }).click();
await page.waitForTimeout(2000);
expect(await page.locator('.error').isVisible()).toBe(true);

Why it breaks: The fixed sleep is slow and still flaky, isVisible() checks once with no retry, and .error might match an unrelated element.

A robust Playwright version

Robust
await page.getByLabel('Username').fill('ada');
await page.getByLabel('Password').fill('wrong-password');
await page.getByRole('button', { name: 'Sign in' }).click();
await expect(page.getByRole('alert')).toHaveText(/invalid username or password/i);
await expect(page).not.toHaveURL(/dashboard/);

The assertion retries, checks the actual message, and confirms the user was not let in.

This is a general example on a made-up page, not the challenge’s reference solution.

Common mistakes

  • Only testing the happy path.
  • Asserting that some error exists without checking its text.
  • Using waitForTimeout to wait for the message.

FAQ

What is a negative test?

A test that supplies invalid input on purpose and checks the app handles it correctly.

How do I assert an error message in Playwright?

Use await expect(locator).toHaveText(...) or toContainText(...), which retry automatically.

Should error messages use role=alert?

It is a common accessible pattern so screen readers announce the error; check what your app uses.

Try it

Practise this in Challenge 9. You write the code in the browser editor with no setup. It runs in a fresh Chromium, a hidden validator checks what actually happened, and you get pass or fail, the logs and a video of the run. Challenges 1 to 10 are open without an account; create a free one any time to keep your progress. The reference solution and the hidden validator are shown only after you pass. We never publish solutions here.