vitest-dev/vitest · error · Error
expected selection must be a string or undefined
Error message
expected selection must be a string or undefined
What it means
Thrown by `toHaveSelection` at toHaveSelection.ts:29-30 when the second argument is defined and not a string. The matcher accepts either an expected selection string or `undefined` (meaning 'any non-empty selection'); numbers, objects, booleans, or arrays are rejected.
Source
Thrown at packages/browser/src/client/tester/expect/toHaveSelection.ts:30
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*/
import type { MatcherResult, MatcherState } from 'vitest'
import type { Locator } from '../locators'
import { arrayAsSetComparison, getElementFromUserInput, getMessage, getTag } from './utils'
export default function toHaveSelection(
this: MatcherState,
element: HTMLElement | SVGElement | Locator,
expectedSelection: string,
): MatcherResult {
const htmlElement = getElementFromUserInput(element, toHaveSelection, this)
const expectsSelection = expectedSelection !== undefined
if (expectsSelection && typeof expectedSelection !== 'string') {
throw new Error(`expected selection must be a string or undefined`)
}
const receivedSelection = getSelection(htmlElement)
return {
pass: expectsSelection
? this.equals(receivedSelection, expectedSelection, [arrayAsSetComparison, ...this.customTesters])
: Boolean(receivedSelection),
message: () => {
const to = this.isNot ? 'not to' : 'to'
const matcher = this.utils.matcherHint(
`${this.isNot ? '.not' : ''}.toHaveSelection`,
'element',
expectedSelection,
)
return getMessage(
this,
matcher,View on GitHub (pinned to d568f8ce37)
Solutions
- Pass the literal selected text as a string: `expect(el).toHaveSelection('hello')`.
- If you only want to assert *some* selection exists, pass `undefined` or omit the argument: `expect(el).toHaveSelection()`.
- Coerce with `String(...)` only if the value really is text; otherwise fix the source of the wrong type.
Example fix
// before
expect(el).toHaveSelection(selectionLength) // number
// after
expect(el).toHaveSelection('expected substring') Defensive patterns
Strategy: type-guard
Validate before calling
function isStringOrUndefined(v: unknown): v is string | undefined {
return v === undefined || typeof v === 'string'
}
if (!isStringOrUndefined(selection)) throw new Error('selection must be string or undefined') Type guard
function isStringOrUndefined(v: unknown): v is string | undefined {
return v === undefined || typeof v === 'string'
} Prevention
- Type the expected selection parameter as string | undefined at call sites.
- If you only care that some selection exists, omit the argument entirely.
- Avoid passing numeric offsets/range objects; this matcher compares selected text.
When it happens
Trigger: Calling `expect(el).toHaveSelection(123)`, `expect(el).toHaveSelection(['a','b'])`, `expect(el).toHaveSelection({ start: 0 })`, or passing a number-typed value. The guard runs only when `expectedSelection !== undefined`.
Common situations: Passing a character offset or range object by mistake. Migrating from a different selection API and assuming an index is accepted. Building the expected value from `JSON.parse` of user input that yields a non-string.
Related errors
- toHaveFormValues must be called with an object of expected f
- toHaveFormValues must be called on a form or a fieldset, ins
- Multiple form elements with the same name must be of the sam
- input with type=checkbox or type=radio cannot be used with .
- 'toMatchScreenshot' cannot be used with "not"
AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03).
Data as JSON: /data/errors/2acada4c7fda6269.json.
Report an issue: GitHub.