Browser runner for Vitest enabling tests to run in actual browser environments with real DOM APIs and browser-specific features
—
Client-side testing environment providing the core API for browser tests including user interaction simulation, element location, server communication, and browser-specific utilities.
Handler for user interactions with comprehensive support for keyboard, mouse, and form manipulation across different browser providers.
/**
* Handler for user interactions. The support is provided by the browser provider (playwright or webdriverio).
* If used with preview provider, fallbacks to simulated events via @testing-library/user-event.
*/
const userEvent: UserEvent;
interface UserEvent {
/** Creates a new user event instance with separate keyboard state */
setup(): UserEvent;
/** Cleans up the user event instance, releasing any resources */
cleanup(): Promise<void>;
/** Click on an element using provider's API */
click(element: Element | Locator, options?: UserEventClickOptions): Promise<void>;
/** Triggers a double click event on an element */
dblClick(element: Element | Locator, options?: UserEventDoubleClickOptions): Promise<void>;
/** Triggers a triple click event on an element */
tripleClick(element: Element | Locator, options?: UserEventTripleClickOptions): Promise<void>;
/** Type text on the keyboard (supports user-event keyboard syntax like {Shift}) */
keyboard(text: string): Promise<void>;
/** Types text into an element (slower but supports keyboard syntax) */
type(element: Element | Locator, text: string, options?: UserEventTypeOptions): Promise<void>;
/** Fills an input element with text (faster, no keyboard syntax support) */
fill(element: Element | Locator, text: string, options?: UserEventFillOptions): Promise<void>;
/** Removes all text from an element */
clear(element: Element | Locator, options?: UserEventClearOptions): Promise<void>;
/** Choose one or more values from a select element */
selectOptions(
element: Element,
values: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[],
options?: UserEventSelectOptions
): Promise<void>;
/** Hovers over an element */
hover(element: Element | Locator, options?: UserEventHoverOptions): Promise<void>;
/** Moves cursor position to the body element */
unhover(element: Element | Locator, options?: UserEventHoverOptions): Promise<void>;
/** Change a file input element to have the specified files */
upload(element: Element | Locator, files: File | File[] | string | string[], options?: UserEventUploadOptions): Promise<void>;
/** Drags a source element on top of the target element */
dragAndDrop(source: Element | Locator, target: Element | Locator, options?: UserEventDragAndDropOptions): Promise<void>;
/** Sends a Tab key event */
tab(options?: UserEventTabOptions): Promise<void>;
/** Copies the selected content */
copy(): Promise<void>;
/** Cuts the selected content */
cut(): Promise<void>;
/** Pastes the copied or cut content */
paste(): Promise<void>;
}Usage Examples:
import { userEvent, page } from "@vitest/browser/context";
// Basic interactions
await userEvent.click(page.getByRole("button"));
await userEvent.type(page.getByLabelText("Username"), "john");
await userEvent.fill(page.getByPlaceholder("Email"), "john@example.com");
// Keyboard shortcuts
await userEvent.keyboard("{Ctrl}a"); // Select all
await userEvent.keyboard("{Ctrl}c"); // Copy
await userEvent.keyboard("{Ctrl}v"); // Paste
// File upload
const fileInput = page.getByLabelText("Upload file");
await userEvent.upload(fileInput, [
new File(["content"], "test.txt", { type: "text/plain" })
]);
// Create separate instance with its own state
const userEvent2 = userEvent.setup();
await userEvent2.type(input, "text");
await userEvent2.cleanup();Browser page interface providing locator methods, viewport management, and screenshot capabilities.
/**
* Browser page object with locator methods and screenshot capabilities
*/
const page: BrowserPage;
interface BrowserPage {
/** Change the size of iframe's viewport */
viewport(width: number, height: number): Promise<void>;
/** Make a screenshot of the test iframe or a specific element */
screenshot(options?: ScreenshotOptions): Promise<string>;
screenshot(options: Omit<ScreenshotOptions, 'base64'> & { base64: true }): Promise<{
path: string;
base64: string;
}>;
/** Extend default page object with custom methods */
extend(methods: Partial<BrowserPage>): BrowserPage;
/** Wrap an HTML element in a Locator */
elementLocator(element: Element): Locator;
// Locator selector methods
/** Creates a locator by ARIA role */
getByRole(role: string, options?: LocatorByRoleOptions): Locator;
/** Creates a locator by label text */
getByLabelText(text: string | RegExp, options?: LocatorOptions): Locator;
/** Creates a locator by alt text */
getByAltText(text: string | RegExp, options?: LocatorOptions): Locator;
/** Creates a locator by placeholder text */
getByPlaceholder(text: string | RegExp, options?: LocatorOptions): Locator;
/** Creates a locator by text content */
getByText(text: string | RegExp, options?: LocatorOptions): Locator;
/** Creates a locator by title attribute */
getByTitle(text: string | RegExp, options?: LocatorOptions): Locator;
/** Creates a locator by test ID attribute */
getByTestId(text: string | RegExp): Locator;
}Usage Examples:
import { page } from "@vitest/browser/context";
// Viewport management
await page.viewport(1024, 768);
// Screenshots
const imagePath = await page.screenshot({ path: "test-result.png" });
const { path, base64 } = await page.screenshot({ base64: true });
// Element location
const button = page.getByRole("button", { name: "Submit" });
const input = page.getByLabelText("Username");
const link = page.getByText("Click here");
// Extend with custom methods
const extendedPage = page.extend({
async loginUser(username: string, password: string) {
await userEvent.fill(this.getByLabelText("Username"), username);
await userEvent.fill(this.getByLabelText("Password"), password);
await userEvent.click(this.getByRole("button", { name: "Login" }));
}
});File system operations accessible from browser context for reading/writing files on the server.
/**
* Available commands for the browser - server-side file operations
*/
const commands: BrowserCommands;
interface BrowserCommands {
/** Read file from server filesystem */
readFile(path: string, options?: BufferEncoding | FsOptions): Promise<string>;
/** Write file to server filesystem */
writeFile(path: string, content: string, options?: BufferEncoding | (FsOptions & { mode?: number | string })): Promise<void>;
/** Remove file from server filesystem */
removeFile(path: string): Promise<void>;
}
interface FsOptions {
encoding?: BufferEncoding;
flag?: string | number;
}Usage Examples:
import { commands } from "@vitest/browser/context";
// Read configuration files
const config = await commands.readFile("./config.json");
const parsed = JSON.parse(config);
// Write test outputs
await commands.writeFile("./output.json", JSON.stringify(testResults));
// Clean up test files
await commands.removeFile("./temp-test-file.txt");
// Read with specific encoding
const content = await commands.readFile("./data.txt", "utf8");Information about the server environment and browser configuration.
/**
* Server and browser metadata
*/
const server: ServerInfo;
interface ServerInfo {
/** Platform the Vitest server is running on (same as process.platform) */
platform: Platform;
/** Runtime version of the Vitest server (same as process.version) */
version: string;
/** Name of the browser provider (playwright, webdriverio, preview) */
provider: string;
/** Name of the current browser */
browser: string;
/** Available commands for the browser */
commands: BrowserCommands;
/** Serialized test config */
config: SerializedConfig;
}
type Platform = 'aix' | 'android' | 'darwin' | 'freebsd' | 'haiku' | 'linux' | 'openbsd' | 'sunos' | 'win32' | 'cygwin' | 'netbsd';Usage Examples:
import { server } from "@vitest/browser/context";
// Check browser environment
if (server.provider === "playwright") {
// Playwright-specific test logic
}
// Platform-specific behavior
if (server.platform === "win32") {
// Windows-specific paths
}
// Access browser info
console.log(`Running on ${server.browser} via ${server.provider}`);
// Access configuration
const testIdAttribute = server.config.browser.locators.testIdAttribute;Factory for creating locator selectors and extending locator functionality.
/**
* Locator factory and extension methods
*/
const locators: BrowserLocators;
interface BrowserLocators {
/** Create element locator selectors for an existing element */
createElementLocators(element: Element): LocatorSelectors;
/** Extend locators with custom selector methods */
extend(methods: {
[K in keyof LocatorSelectors]?: (this: BrowserPage | Locator, ...args: Parameters<LocatorSelectors[K]>) => ReturnType<LocatorSelectors[K]> | string
}): void;
}
interface LocatorSelectors {
getByRole(role: string, options?: LocatorByRoleOptions): Locator;
getByLabelText(text: string | RegExp, options?: LocatorOptions): Locator;
getByAltText(text: string | RegExp, options?: LocatorOptions): Locator;
getByPlaceholder(text: string | RegExp, options?: LocatorOptions): Locator;
getByText(text: string | RegExp, options?: LocatorOptions): Locator;
getByTitle(text: string | RegExp, options?: LocatorOptions): Locator;
getByTestId(text: string | RegExp): Locator;
}Usage Examples:
import { locators, page } from "@vitest/browser/context";
// Create locator selectors for existing element
const existingElement = document.querySelector("#my-element");
const elementLocators = locators.createElementLocators(existingElement);
const childButton = elementLocators.getByRole("button");
// Extend with custom locator methods
locators.extend({
getByDataCy(this: BrowserPage | Locator, value: string) {
return this.locator(`[data-cy="${value}"]`);
}
});
// Now available on page and locators
const customElement = page.getByDataCy("submit-button");Chrome DevTools Protocol access for advanced browser automation (Playwright provider only).
/**
* Chrome DevTools Protocol session access (Playwright provider only)
*/
const cdp: () => CDPSession;
interface CDPSession {
/** Send CDP command */
send<T extends keyof Protocol.CommandParameters>(
method: T,
params?: Protocol.CommandParameters[T]
): Promise<Protocol.CommandReturnValues[T]>;
/** Add event listener */
on<T extends keyof Protocol.Events>(
event: T,
listener: (payload: Protocol.Events[T]) => void
): this;
/** Add one-time event listener */
once<T extends keyof Protocol.Events>(
event: T,
listener: (payload: Protocol.Events[T]) => void
): this;
/** Remove event listener */
off<T extends keyof Protocol.Events>(
event: T,
listener: (payload: Protocol.Events[T]) => void
): this;
}Usage Examples:
import { cdp } from "@vitest/browser/context";
// Get CDP session (Playwright only)
const session = cdp();
// Enable runtime domain
await session.send('Runtime.enable');
// Listen to console events
session.on('Runtime.consoleAPICalled', (event) => {
console.log('Browser console:', event.args);
});
// Evaluate JavaScript
const result = await session.send('Runtime.evaluate', {
expression: 'document.title'
});Option interfaces for user events and locators:
interface UserEventClickOptions {}
interface UserEventDoubleClickOptions {}
interface UserEventTripleClickOptions {}
interface UserEventFillOptions {}
interface UserEventClearOptions {}
interface UserEventHoverOptions {}
interface UserEventSelectOptions {}
interface UserEventUploadOptions {}
interface UserEventDragAndDropOptions {}
interface UserEventTabOptions {
shift?: boolean;
}
interface UserEventTypeOptions {
skipClick?: boolean;
skipAutoClose?: boolean;
}Install with Tessl CLI
npx tessl i tessl/npm-vitest--browser