microsoft/playwright · error · Error

"expected" argument in toContainClass cannot be a RegExp val

Error message

"expected" argument in toContainClass cannot be a RegExp value

What it means

The single-value form of expect(locator).toContainClass() rejects a RegExp `expected` (matchers.ts:320-322). The matcher sends 'to.contain.class' with the serialized expected text and checks that the class attribute's token list contains the exact string; a regex has no exact-string meaning there, so Playwright throws immediately rather than running a doomed assertion.

Source

Thrown at packages/playwright/src/matchers/matchers.ts:322

  }
}

export function toContainClass(
  this: ExpectMatcherStateInternal,
  locator: LocatorEx,
  expected: string | string[],
  options?: { timeout?: number, signal?: AbortSignal },
) {
  if (Array.isArray(expected)) {
    if (expected.some(e => isRegExp(e)))
      throw new Error(`"expected" argument in toContainClass cannot contain RegExp values`);
    return toEqual.call(this, 'toContainClass', locator, 'Locator', async (isNot, timeout, signal) => {
      const expectedText = serializeExpectedTextValues(expected);
      return await locator._expect('to.contain.class.array', { expectedText, isNot, timeout, signal, title: this.title });
    }, expected, options);
  } else {
    if (isRegExp(expected))
      throw new Error(`"expected" argument in toContainClass cannot be a RegExp value`);
    return toMatchText.call(this, 'toContainClass', locator, 'Locator', async (isNot, timeout, signal) => {
      const expectedText = serializeExpectedTextValues([expected]);
      return await locator._expect('to.contain.class', { expectedText, isNot, timeout, signal, title: this.title });
    }, expected, options);
  }
}

export function toHaveCount(
  this: ExpectMatcherStateInternal,
  locator: LocatorEx,
  expected: number,
  options?: { timeout?: number, signal?: AbortSignal },
) {
  return toEqual.call(this, 'toHaveCount', locator, 'Locator', async (isNot, timeout, signal) => {
    return await locator._expect('to.have.count', { expectedNumber: expected, isNot, timeout, signal, title: this.title });
  }, expected, options);
}

View on GitHub (pinned to deda92d15e)

Solutions

  1. Use the exact class name: `await expect(locator).toContainClass('btn-primary')`, or an array for several tokens.
  2. For pattern matching, use a matcher with regex support against the attribute: `await expect(locator).toHaveAttribute('class', /btn-/)`.
  3. Add a runtime type guard on dynamic expected values before asserting (see typeGuard).

Example fix

// before
await expect(page.getByTestId('icon')).toContainClass(/^-icon-/);
// Error: "expected" argument in toContainClass cannot be a RegExp value

// after
await expect(page.getByTestId('icon')).toContainClass('my-icon');
// or:
await expect(page.getByTestId('icon')).toHaveAttribute('class', /-icon-/);
Defensive patterns

Strategy: type-guard

Validate before calling

const expected: unknown = getExpectedFromFixture();
if (expected instanceof RegExp)
  throw new Error('toContainClass needs an exact class name; use toHaveAttribute for regex matching');
await expect(locator).toContainClass(expected as string);

Type guard

function isExactClassNames(value: unknown): value is string | string[] {
  if (typeof value === 'string') return true;
  return Array.isArray(value) && value.every(item => typeof item === 'string');
}

// usage
if (!isExactClassNames(expected)) throw new Error(`Invalid class expectation: ${String(expected)}`);
await expect(locator).toContainClass(expected);

Prevention

When it happens

Trigger: Calling `await expect(locator).toContainClass(/btn-/)` where `isRegExp(expected)` is true. The TS signature (`expected: string | string[]`) prevents it in typed code, so it typically appears in plain-JS specs or when `expected` arrives from untyped data and bypasses type checking.

Common situations: Copy-pasting from toHaveText/toHaveAttribute examples that do allow regexes; trying to match generated class names (CSS modules, Tailwind hashes) with a pattern; passing fixture-driven values whose type is not controlled.

Related errors


AI-assisted analysis of microsoft/playwright@deda92d15e (2026-08-21). Data as JSON: /api/errors/da845032092b26a8. Report an issue: GitHub.