Skip to content

Jest String Matchers

Strings are rarely tested with exact equality alone — you often care whether a substring or pattern appears. This lesson covers .toMatch() and practical string-testing techniques.

Matching Strings with toMatch()

.toMatch() checks whether a string contains a substring, or matches a regular expression. Passing a plain string checks for a direct substring match; passing a RegExp allows for flexible pattern matching.

This is more resilient than .toBe() for strings that include dynamic content (like timestamps or generated IDs) where you only care about part of the output.

expect('Order #A102 confirmed').toMatch('confirmed');
expect('Order #A102 confirmed').toMatch(/^Order #[A-Z]\d+/);

The regex example checks the string's shape (an order number prefix) without hardcoding the exact generated ID.

toMatch() Syntax

expect(receivedString).toMatch('substring');
expect(receivedString).toMatch(/regex-pattern/);
expect(receivedString).not.toMatch(/pattern/);
  • Pass a plain string to check for a direct substring.
  • Pass a RegExp literal for flexible pattern matching (case sensitivity, anchors, character classes).
  • .not.toMatch() asserts the string does not contain the given substring/pattern.
  • For exact string equality (no partial matching), use .toBe() instead.

String Matchers Cheat Sheet

Common ways to assert on string values in Jest.

Goal Example
Exact match expect(str).toBe('Hello')
Contains substring expect(str).toMatch('World')
Matches pattern expect(str).toMatch(/^\\d{3}-\\d{4}$/)
Case-insensitive expect(str).toMatch(/hello/i)
Does not contain expect(str).not.toMatch('error')
Array of strings contains expect(list).toContain('apple')

When to Use a Regex vs. a Plain Substring

A plain substring is simplest when you only care that specific text appears anywhere in the string. A regex becomes necessary when you need to check position (anchors like ^ and $), structure (digits, whitespace, repetition), or case-insensitivity.

// Plain substring — good enough here
expect(errorMessage).toMatch('required');

// Regex — needed to check exact structure
expect(phoneNumber).toMatch(/^\(\d{3}\) \d{3}-\d{4}$/);

Testing Strings with Dynamic Content

When output includes a timestamp, UUID, or other non-deterministic value, avoid .toBe() on the whole string. Instead, match the static parts with .toMatch() and, if needed, separately assert on structure using a regex that describes the dynamic portion's shape.

const message = greetUser('Ada'); // e.g. "Welcome back, Ada! (session-93af1c)"

expect(message).toMatch('Welcome back, Ada!');
expect(message).toMatch(/\(session-[a-f0-9]+\)$/);

Common Mistakes

  • Using .toBe() on strings that contain dynamic values like timestamps or generated IDs, causing brittle tests.
  • Writing overly complex regexes when a simple substring check would suffice.
  • Forgetting to escape special regex characters when matching literal punctuation.
  • Not adding the i flag when case shouldn't matter for the assertion.

Key Takeaways

  • .toMatch() accepts either a plain substring or a regular expression.
  • Use regex anchors and character classes when the string's structure matters, not just its content.
  • Avoid .toBe() for strings containing dynamic or generated content.
  • .not.toMatch() is useful for asserting an error message or output does not appear.

Pro Tip

When a test needs to check both static and dynamic parts of a string, split the assertion into two .toMatch() calls instead of building one giant, hard-to-read regex.