Skip to main content
Version: v4.43

API Reference

Complete reference for the @stencil/vitest testing utilities.

Render Function

render(VNode)

Renders a Stencil component for testing.

import { render, h } from '@stencil/vitest';

const result = await render(<my-component name="World" />);

Returns:

PropertyTypeDescription
rootHTMLElementThe rendered component element
waitForChanges() => Promise<void>Wait for component re-renders
setProps(props: object) => Promise<void>Update props and wait for changes
unmount() => voidRemove the component from the DOM
spyOnEvent(eventName: string) => EventSpyCreate a spy for custom events

Custom Matchers

Class Matchers

toHaveClass(className)

Checks if an element has a specific CSS class:

expect(element).toHaveClass('active');
expect(element).toHaveClass('btn-primary');
expect(element).not.toHaveClass('disabled');

toHaveClasses(classNames)

Checks if an element has all specified CSS classes (partial match):

expect(element).toHaveClasses(['btn', 'btn-primary']);
expect(element).toHaveClasses(['active', 'visible']);

toMatchClasses(classNames)

Checks if an element has exactly the specified CSS classes (exact match):

expect(element).toMatchClasses(['btn', 'btn-primary']);
// Fails if element has additional classes

Attribute Matchers

toHaveAttribute(name, value?)

Checks if an element has a specific attribute, optionally with a specific value:

expect(element).toHaveAttribute('aria-label', 'Close');
expect(element).toHaveAttribute('disabled');
expect(element).not.toHaveAttribute('hidden');

toEqualAttribute(name, value)

Checks if an element has an attribute with an exact value:

expect(element).toEqualAttribute('type', 'button');
expect(element).toEqualAttribute('aria-label', 'Submit form');

toEqualAttributes(attributes)

Checks multiple attributes and their values at once:

expect(element).toEqualAttributes({
type: 'button',
disabled: true,
'aria-label': 'Submit',
});

Property Matchers

toHaveProperty(name, value)

Checks if an element has a specific property value:

expect(element).toHaveProperty('value', 'test');
expect(element).toHaveProperty('checked', true);

Text Content Matchers

toHaveTextContent(text)

Checks if an element contains specific text (includes shadow DOM):

expect(element).toHaveTextContent('Hello World');

toHaveLightTextContent(text)

Checks if an element contains specific text (light DOM only):

expect(element).toHaveLightTextContent('Slotted content');

toEqualText(text)

Checks if an element's text content exactly matches (includes shadow DOM):

expect(element).toEqualText('Exact text match');

toEqualLightText(text)

Checks if an element's text content exactly matches (light DOM only):

expect(element).toEqualLightText('Exact slotted text');

Shadow DOM Matchers

toHaveShadowRoot()

Checks if an element has a shadow root:

expect(element).toHaveShadowRoot();

toEqualHtml(html)

Compares the element's HTML including shadow DOM:

await expect(element).toEqualHtml(`
<my-component>
<mock:shadow-root>
<div class="container">
<slot></slot>
</div>
</mock:shadow-root>
Slotted content
</my-component>
`);

toEqualLightHtml(html)

Compares only the light DOM HTML:

await expect(element).toEqualLightHtml(`
<my-component first="John" last="Doe">
<span>Child content</span>
</my-component>
`);

Event Matchers

These matchers work with EventSpy objects returned by spyOnEvent:

toHaveReceivedEvent()

Checks if an event has been received at least once:

expect(eventSpy).toHaveReceivedEvent();

toHaveReceivedEventTimes(count)

Checks if an event has been received a specific number of times:

expect(eventSpy).toHaveReceivedEventTimes(3);
expect(eventSpy).toHaveReceivedEventTimes(0); // No events

toHaveReceivedEventDetail(detail)

Checks if the last received event has the expected detail:

expect(eventSpy).toHaveReceivedEventDetail({
value: 'test',
timestamp: expect.any(Number),
});

Screenshot Matchers

toMatchScreenshot()

Compares the element's visual appearance (browser tests only):

await expect(element).toMatchScreenshot();

Utility Functions

serializeHtml(element, options?)

Serializes an HTML element to a string, including shadow DOM content.

import { serializeHtml } from '@stencil/vitest';

const html = serializeHtml(element, {
serializeShadowRoot: true, // Include shadow DOM (default: true)
pretty: true, // Prettify output (default: true)
excludeStyles: true, // Exclude <style> tags (default: true)
});

Options:

OptionTypeDefaultDescription
serializeShadowRootbooleantrueInclude shadow DOM content
prettybooleantrueFormat with indentation
excludeStylesbooleantrueRemove <style> tags

prettifyHtml(html)

Formats an HTML string with indentation for readability.

import { prettifyHtml } from '@stencil/vitest';

const formatted = prettifyHtml('<div><span>Hello</span></div>');
// Returns:
// <div>
// <span>
// Hello
// </span>
// </div>

waitForStable(elementOrSelector, timeout?)

Waits for an element to be rendered and visible in the DOM. Browser tests only.

import { waitForStable } from '@stencil/vitest';

// Wait for an element
await waitForStable(element);

// Wait using a selector
await waitForStable('my-component .inner-element');

// Custom timeout (default: 5000ms)
await waitForStable('my-component', 10000);
note

In non-browser environments, waitForStable logs a warning and returns immediately.

waitForExist(selector, timeout?)

Waits for an element matching the selector to exist in the DOM. Works in all environments.

import { waitForExist } from '@stencil/vitest';

// Wait for an element to appear
const element = await waitForExist('my-component .lazy-loaded');

// Custom timeout (default: 5000ms)
const element = await waitForExist('#dynamic-content', 10000);

Returns: The element if found, or null if timeout is reached.

EventSpy API

The spyOnEvent function returns an EventSpy object:

const spy = spyOnEvent('myEvent');

Properties:

PropertyTypeDescription
eventsCustomEvent[]Array of all received events
firstEventCustomEvent | undefinedFirst received event
lastEventCustomEvent | undefinedMost recent event

Re-exports

@stencil/vitest re-exports common Vitest utilities for convenience:

import {
describe,
it,
expect,
beforeEach,
afterEach,
beforeAll,
afterAll,
vi,
h, // Stencil's h function for JSX
} from '@stencil/vitest';