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
- Use the exact class name: `await expect(locator).toContainClass('btn-primary')`, or an array for several tokens.
- For pattern matching, use a matcher with regex support against the attribute: `await expect(locator).toHaveAttribute('class', /btn-/)`.
- 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
- Treat toContainClass as an exact-token membership check; only toHaveText/toHaveAttribute accept regexes.
- Validate fixture- or user-supplied class values are strings before asserting.
- For hashed/generated class names, match the whole class attribute with a regex via toHaveAttribute instead.
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
- "expected" argument in toContainClass cannot contain RegExp
- "role" argument in toHaveRole must be a string
- "${param.target}" does not match any elements.
- Ref ${param.target} not found in the current page snapshot.
- Error while parsing selector `${selector}`: ${e.message}
AI-assisted analysis of microsoft/playwright@deda92d15e (2026-08-21).
Data as JSON: /api/errors/da845032092b26a8.
Report an issue: GitHub.