vitest-dev/vitest · error · Error

Exact option does not support RegExp expected class names

Error message

Exact option does not support RegExp expected class names

What it means

Thrown by toHaveClass (packages/browser/src/client/tester/expect/toHaveClass.ts:40-43) when the { exact: true } option is combined with one or more RegExp expected class names. Exact mode (lines 45-63) requires the expected class set to equal the received class set by length and content, which is meaningless for a RegExp (a pattern has no fixed length/count), so the combination is rejected as a hard error rather than silently producing a confusing result.

Source

Thrown at packages/browser/src/client/tester/expect/toHaveClass.ts:42

): MatcherResult {
  const htmlElement = getElementFromUserInput(actual, toHaveClass, this)
  const { expectedClassNames, options } = getExpectedClassNamesAndOptions(params)

  const received = splitClassNames(htmlElement.getAttribute('class'))
  const expected = expectedClassNames.reduce(
    (acc, className) => {
      return acc.concat(
        typeof className === 'string' || !className
          ? splitClassNames(className)
          : className,
      )
    },
    [] as (string | RegExp)[],
  )

  const hasRegExp = expected.some(className => className instanceof RegExp)
  if (options.exact && hasRegExp) {
    throw new Error('Exact option does not support RegExp expected class names')
  }

  if (options.exact) {
    return {
      pass: isSubset(expected, received) && expected.length === received.length,
      message: () => {
        const to = this.isNot ? 'not to' : 'to'
        return getMessage(
          this,
          this.utils.matcherHint(
            `${this.isNot ? '.not' : ''}.toHaveClass`,
            'element',
            this.utils.printExpected(expected.join(' ')),
          ),
          `Expected the element ${to} have EXACTLY defined classes`,
          expected.join(' '),
          'Received',
          received.join(' '),

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Drop exact when using regex: expect(el).toHaveClass(/btn-.*/).
  2. If you need exactness, convert the regex to literal class names: expect(el).toHaveClass('btn-primary', 'btn-lg', { exact: true }).
  3. Split into two assertions: a regex match without exact, plus a separate exact string check.

Example fix

// before
expect(el).toHaveClass(/btn-\w+/, { exact: true })
// after
expect(el).toHaveClass('btn-primary', 'btn-lg', { exact: true })
Defensive patterns

Strategy: validation

Validate before calling

function hasRegExpExpected(classes: (string | RegExp)[]): boolean {
  return classes.some(c => c instanceof RegExp)
}
const expected: (string | RegExp)[] = [/btn-\w+/]
const exact = !hasRegExpExpected(expected)
expect(el).toHaveClass(...(exact ? expected.map(String) : expected), { exact })

Prevention

When it happens

Trigger: Calling expect(el).toHaveClass(/btn-.*/, { exact: true }) or expect(el).toHaveClass('active', /icon-\w+/, { exact: true }).

Common situations: Copy-paste from a string-based exact assertion where a regex was later substituted; mixing exact class-set checks with flexible pattern matches.

Related errors


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/79cc1f6b60587c90.json. Report an issue: GitHub.