vitest-dev/vitest · error · Error

.toHaveDisplayValue() currently does not support input

Error message

.toHaveDisplayValue() currently does not support input[type="${htmlElement.type}"], try with another matcher instead.

What it means

.toHaveDisplayValue() does not support INPUT elements of type radio or checkbox, because their meaningful state is `checked`, not `value`. Vitest throws with the specific type interpolated when it detects such an input, directing the user to a more appropriate matcher (e.g. toBeChecked()). This guard fires after the tag-name check passes.

Solutions

  1. For radio/checkbox, use expect(el).toBeChecked() (or .not.toBeChecked()) instead.
  2. If you really need the value attribute, assert on el.getAttribute('value') directly.
  3. Branch the assertion helper on input.type before picking a matcher.

Example fix

// before
expect(checkboxEl).toHaveDisplayValue('on')
// after
expect(checkboxEl).toBeChecked()
Defensive patterns

Strategy: type-guard

Validate before calling

if (el instanceof HTMLInputElement && ['radio', 'checkbox'].includes(el.type)) {
  // use toBeChecked instead of toHaveDisplayValue
}
expect(el).toBeChecked()

Type guard

function isToggleInput(el: Element): el is HTMLInputElement & { type: 'radio' | 'checkbox' } {
  return el instanceof HTMLInputElement && ['radio', 'checkbox'].includes(el.type)
}

Prevention

When it happens

Trigger: Calling expect(radioInput).toHaveDisplayValue('on') or expect(checkboxInput).toHaveDisplayValue(...); applying a generic display-value assertion to a form that includes radio/checkbox inputs without distinguishing by type.

Common situations: Reusable form assertion helpers that apply toHaveDisplayValue uniformly to all inputs; copy-pasted assertions across input types.

Related errors


AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11). Data as JSON: /api/errors/806006a4bc3ca3bd. Report an issue: GitHub.

Appendix: source

Thrown at packages/browser/src/client/tester/expect/toHaveDisplayValue.ts:35

import type { Locator } from '../locators'
import { getElementFromUserInput, getMessage, getTag, isInputElement } from './utils'

export default function toHaveDisplayValue(
  this: MatcherState,
  actual: Element | Locator,
  expectedValue: string | RegExp | Array<string | RegExp>,
): MatcherResult {
  const htmlElement = getElementFromUserInput(actual, toHaveDisplayValue, this)
  const tagName = getTag(htmlElement)

  if (!['SELECT', 'INPUT', 'TEXTAREA'].includes(tagName)) {
    throw new Error(
      '.toHaveDisplayValue() currently supports only input, textarea or select elements, try with another matcher instead.',
    )
  }

  if (isInputElement(htmlElement) && ['radio', 'checkbox'].includes(htmlElement.type)) {
    throw new Error(
      `.toHaveDisplayValue() currently does not support input[type="${htmlElement.type}"], try with another matcher instead.`,
    )
  }

  const values = getValues(tagName, htmlElement)
  const expectedValues = getExpectedValues(expectedValue)
  const numberOfMatchesWithValues = expectedValues.filter(expected =>
    values.some(value =>
      expected instanceof RegExp
        ? expected.test(value)
        : this.equals(value, String(expected), this.customTesters),
    ),
  ).length

  const matchedWithAllValues = numberOfMatchesWithValues === values.length
  const matchedWithAllExpectedValues
    = numberOfMatchesWithValues === expectedValues.length

View on GitHub (pinned to 1fa9837ec2)