Skip to contentPlayForge

How do I match exact text instead of partial text in Playwright?

Written by Jatin Thacker, Automation Architect · Updated

Pass { exact: true } to the locator, for example getByRole('heading', { name: 'Halcyon Burr Grinder', exact: true }), which makes the match case-sensitive and whole-string. A regular expression with ^ and $ anchors does the same job.

This answer is one piece of Chapter 9: Locators I: What the User Sees.

  • getByRole and the Accessible Name
  • getByText, getByLabel, getByPlaceholder, getByTestId
  • Strict Mode — One Locator, One Element

By default, Playwright's text-based locators look for a substring and ignore case. That is forgiving, and usually what you want, until one name is the start of another.

The catalog has exactly that pair: Halcyon Burr Grinder and Halcyon Burr Grinder Mini. getByRole('heading', { name: 'Halcyon Burr Grinder' }) matches both headings, because the first name is a substring of the second. Click it and strict mode throws.

Adding exact: true changes the rule to whole-string and case-sensitive, so only the heading that reads exactly Halcyon Burr Grinder matches. The test proves both counts with toHaveCount(). The anchored regular expression /^Halcyon Burr Grinder$/ also matches one, because a regular expression is matched as you write it.

The same exact option exists on getByText(), getByLabel(), getByPlaceholder(), getByAltText() and getByTitle(). Exact matching still trims whitespace at the ends, so a name with stray spaces matches.

For assertions the defaults are the other way round: toHaveText() compares the whole text, and toContainText() looks for a part.

qa-049.spec.js(https://practice.learnplayforge.com)
import { test, expect } from '@playwright/test'; test('exact: true stops Grinder matching Grinder Mini', async ({ page }) => { await page.goto('/catalog.html?mock=static&seed=42&autologin=1'); // Substring match: 'Halcyon Burr Grinder' and 'Halcyon Burr Grinder Mini' await expect(page.getByRole('heading', { name: 'Halcyon Burr Grinder' })).toHaveCount(2); // Whole-string match: only the one heading await expect(page.getByRole('heading', { name: 'Halcyon Burr Grinder', exact: true })).toHaveCount(1); // A regular expression with anchors does the same job await expect(page.getByRole('heading', { name: /^Halcyon Burr Grinder$/ })).toHaveCount(1); });
Output
1 passed (2.6s)
Test yourself
The page has headings Halcyon Burr Grinder and Halcyon Burr Grinder Mini. How many does getByRole('heading', { name: 'Halcyon Burr Grinder' }) match?

Practised in the full course: the drill Grinder, not Grinder Mini.

See the chapter

AI can write the test now. The job is knowing whether it checks anything. That's what the course teaches, one chapter at a time.

163 lessons · 226 drills · start free

← All questions

Training a team? Talk to us.