Skip to content

Regular expressions

A regular expression (regex) is a pattern for matching text. Instead of asking “is this string exactly equal to /orders/42?” a regex lets you ask “does this string look like /orders/ followed by some number?” The course leans on regex constantly for URL and text assertions, like this one from Module 3:

await expect(page).toHaveURL(/\/orders\/\d+/);

That reads: “the URL contains /orders/ followed by one or more digits” — so it passes for /orders/1, /orders/42, or /orders/9999 without you hard-coding the id. This page explains every piece of a pattern like that.

In JavaScript a regex is written between forward slashes, not quotes:

/login/ // a regex that matches the text "login"
'login' // a plain string — NOT a regex

Playwright’s matchers (toHaveURL, toHaveText, getByText, filter, waitForURL) accept either a string (exact/substring match) or a regex (pattern match). The slashes are how you signal “this is a pattern.”

Most characters in a regex match themselves — these are literals. /cart/ matches the text cart. The one common exception is the dot ., which matches any single character:

/c.t/ // matches "cat", "cut", "c9t" — any char between c and t

By default a regex matches anywhere inside the string. Anchors pin it to an edge:

AnchorMeans
^start of the string
$end of the string
/\/admin/ // URL CONTAINS /admin (anywhere)
/^https/ // string STARTS WITH https
/\/checkout$/ // string ENDS WITH /checkout

This is why toHaveURL(/\/orders\/\d+/) passes on a full URL like http://localhost:3000/orders/42 — without anchors, it only needs to find the pattern somewhere in the string.

A character class matches one character out of a set.

ClassMatches
\da digit 0–9
\wa word character: letter, digit, or _
\swhitespace (space, tab, newline)
[abc]any one of a, b, c
[a-z]any lowercase letter (a range)
[^0-9]any character that is not a digit (^ inside [] negates)
/\/orders\/\d+/ // /orders/ then digits — the course's order-id pattern
/[?&]search=/ // a ? OR & before search= (query-string matching, Module 4)

Quantifiers say how many times the preceding item may repeat.

QuantifierMeans
*zero or more
+one or more
?zero or one (optional)
{3}exactly 3
{2,5}between 2 and 5
/\d+/ // one or more digits → "42", "9999"
/colou?r/ // "color" OR "colour" → the u is optional
/\d{4}/ // exactly four digits → a year, a zip code

In /\/orders\/\d+/, the + after \d is what lets it match an id of any length.

Escaping — matching special characters literally

Section titled “Escaping — matching special characters literally”

Characters with a special meaning (. / \ + * ? ( ) [ ] { } ^ $ |) must be escaped with a backslash to match them literally. The slash matters a lot in URL patterns:

/\/orders\// // matches the literal text "/orders/"
// // every \/ is an escaped forward slash

\/ is a literal /; \. is a literal dot; \\ is a literal backslash. Without the backslash, . would match any character and / would close the regex early.

  • ( … ) groups part of a pattern so a quantifier or alternation applies to the whole group.
  • | means “or”.
/(cat|dog)s?/ // "cat", "cats", "dog", or "dogs"
/(\d{1,3}\.){3}\d{1,3}/ // four dot-separated number groups (an IP shape)

A letter after the closing slash changes how the whole pattern behaves.

FlagEffect
icase-insensitive
gglobal — find all matches, not just the first
mmultiline — ^/$ match each line
page.getByText(/login/i) // "Login", "LOGIN", "login" — Module 2
await expect(page.locator('.result')).toHaveText(/success/i) // Module 5
await expect(page.locator('#search')).toHaveValue(/widget/i) // Module 4

The i flag is the one you’ll use most in tests — it makes assertions survive capitalization changes in the UI.

PatternWhereWhy a regex
toHaveURL(/\/orders\/\d+/)Modules 3, 4, 5, 7the order id is dynamic
toHaveURL(/[?&]search=Wireless/)Modules 4, 5match a query param in any position
not.toHaveURL(/\/admin/)Module 4assert you did not reach an area
getByText(/login/i)Module 2case-insensitive text match
filter({ hasText: /…/ })Module 2narrow a set by a text pattern
/abc/ literal text "abc"
. any one character
^ $ start / end of string
\d \w \s digit / word char / whitespace
[abc] [a-z] one char from a set / range
[^0-9] NOT in the set
* + ? zero+ / one+ / optional
{3} {2,5} exactly 3 / between 2 and 5
\/ \. escaped literal / or .
( ) | group / OR
/…/i /…/g case-insensitive / global flag