vitest-dev/vitest · error · TypeError
.toContainHTML() expects a string value, got
Error message
.toContainHTML() expects a string value, got ${htmlText} What it means
The .toContainHTML() matcher requires its second argument (the expected HTML snippet) to be a string so it can be normalized and injected into a detached div for comparison. Passing a non-string (number, object, null, undefined) throws a TypeError before any comparison occurs. This is a strict input-type guard, not a comparison failure.
Solutions
- Ensure the expected argument is always a string literal or a string-typed variable.
- Add a typeof check before the assertion if the value comes from dynamic input.
- Use String(value) only if a coercion is genuinely intended.
Example fix
// before
const html = parts.length
expect(el).toContainHTML(html)
// after
const html = parts.join('')
expect(el).toContainHTML(html) Defensive patterns
Strategy: validation
Validate before calling
if (typeof htmlText !== 'string') {
throw new TypeError('expected HTML must be a string')
}
expect(el).toContainHTML(htmlText) Type guard
function isString(v: unknown): v is string {
return typeof v === 'string'
} Prevention
- Type expected HTML parameters as string in helper signatures.
- Verify dynamic HTML builders return strings before assertion.
- Add a typeof check in shared assertion utilities.
When it happens
Trigger: Calling expect(el).toContainHTML(123) or .toContainHTML({ tag: 'div' }); passing a variable holding null because the expected HTML was never assigned; interpolating a non-string template result.
Common situations: Building expected HTML dynamically and accidentally passing a number/object; refactoring that changed a string constant to an object; null defaults from optional config.
Related errors
- toHaveFormValues must be called on a form or a fieldset…
- Exact option does not support RegExp expected class names
- Invalid element or locator
- .toHaveDisplayValue() currently does not support input
- .toHaveDisplayValue() currently supports only input…
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/d9c03e3a82c597a3.
Report an issue: GitHub.
Appendix: source
Thrown at packages/browser/src/client/tester/expect/toContainHTML.ts:34
import type { MatcherResult, MatcherState } from 'vitest'
import type { Locator } from '../locators'
import { getElementFromUserInput } from './utils'
function getNormalizedHtml(container: HTMLElement | SVGElement, htmlText: string) {
const div = container.ownerDocument.createElement('div')
div.innerHTML = htmlText
return div.innerHTML
}
export default function toContainHTML(
this: MatcherState,
actual: Element | Locator,
htmlText: string,
): MatcherResult {
const htmlElement = getElementFromUserInput(actual, toContainHTML, this)
if (typeof htmlText !== 'string') {
throw new TypeError(`.toContainHTML() expects a string value, got ${htmlText}`)
}
return {
pass: htmlElement.outerHTML.includes(getNormalizedHtml(htmlElement, htmlText)),
message: () => {
return [
this.utils.matcherHint(
`${this.isNot ? '.not' : ''}.toContainHTML`,
'element',
'',
),
'Expected:',
` ${this.utils.EXPECTED_COLOR(htmlText)}`,
'Received:',
` ${this.utils.printReceived(htmlElement.cloneNode(true))}`,
].join('\n')
},
}View on GitHub (pinned to 1fa9837ec2)