CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vitest--browser

Browser runner for Vitest enabling tests to run in actual browser environments with real DOM APIs and browser-specific features

Pending
Overview
Eval results
Files

locators.mddocs/

Locators

Powerful element location system supporting CSS selectors, accessibility queries, chaining, and filtering for robust element targeting in browser tests.

Capabilities

Locator Interface

Main interface for locating and interacting with elements on the page.

interface Locator {
  /** Selector string that will be used to locate the element by the browser provider */
  readonly selector: string;
  
  // Selector methods
  /** Creates a locator by ARIA role and optional attributes */
  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 (matches any element with alt attribute) */
  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 (matches TextNode nodeValue or input value) */
  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 (configurable via browser.locators.testIdAttribute) */
  getByTestId(text: string | RegExp): Locator;
  
  // Interaction methods
  /** Click on an element */
  click(options?: UserEventClickOptions): Promise<void>;
  /** Triggers a double click event on an element */
  dblClick(options?: UserEventDoubleClickOptions): Promise<void>;
  /** Triggers a triple click event on an element */
  tripleClick(options?: UserEventTripleClickOptions): Promise<void>;
  /** Clears the input element content */
  clear(options?: UserEventClearOptions): Promise<void>;
  /** Moves the cursor position to the selected element */
  hover(options?: UserEventHoverOptions): Promise<void>;
  /** Moves the cursor to the document.body element */
  unhover(options?: UserEventHoverOptions): Promise<void>;
  /** Sets the value of the current input, textarea or contenteditable element */
  fill(text: string, options?: UserEventFillOptions): Promise<void>;
  /** Drags the current element to the target location */
  dropTo(target: Locator, options?: UserEventDragAndDropOptions): Promise<void>;
  /** Choose one or more values from a <select> element */
  selectOptions(
    values: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[],
    options?: UserEventSelectOptions
  ): Promise<void>;
  /** Change a file input element to have the specified files */
  upload(files: File | File[] | string | string[], options?: UserEventUploadOptions): Promise<void>;
  
  // Screenshot
  /** Make a screenshot of an element matching the locator */
  screenshot(options?: LocatorScreenshotOptions): Promise<string>;
  screenshot(options: Omit<LocatorScreenshotOptions, 'base64'> & { base64: true }): Promise<{
    path: string;
    base64: string;
  }>;
  
  // Query methods
  /** Returns an element matching the selector (throws if not found) */
  element(): Element;
  /** Returns an array of elements matching the selector */
  elements(): Element[];
  /** Returns an element matching the selector or null if not found */
  query(): Element | null;
  /** Wraps an array of .elements() matching the selector in new Locators */
  all(): Locator[];
  
  // Filtering methods
  /** Returns a locator for the nth element matching the selector */
  nth(index: number): Locator;
  /** Returns a locator for the first element matching the selector */
  first(): Locator;
  /** Returns a locator for the last element matching the selector */
  last(): Locator;
  /** Returns a locator that matches both the current locator and the provided locator */
  and(locator: Locator): Locator;
  /** Returns a locator that matches either the current locator or the provided locator */
  or(locator: Locator): Locator;
  /** Narrows existing locator according to the options */
  filter(options: LocatorFilterOptions): Locator;
}

Usage Examples:

import { page } from "@vitest/browser/context";

// Basic element location
const submitButton = page.getByRole("button", { name: "Submit" });
const usernameInput = page.getByLabelText("Username");
const errorMessage = page.getByText("Invalid credentials");

// Chaining locators
const formButton = page
  .getByRole("form")
  .getByRole("button", { name: "Submit" });

// Using filter options
const activeTab = page
  .getByRole("tab")
  .filter({ hasText: "Active" });

// Complex selectors
const specificItem = page
  .getByRole("listitem")
  .filter({ hasText: "Important" })
  .first();

// Direct element access
const element = submitButton.element(); // throws if not found
const maybeElement = submitButton.query(); // returns null if not found
const allButtons = page.getByRole("button").elements();

Selector Methods

Individual selector methods for different element targeting strategies.

getByRole

/**
 * Creates a locator by ARIA role, ARIA attributes and accessible name
 * @param role - ARIA role or custom role string
 * @param options - Role-specific options for filtering
 * @returns Locator for elements matching the role criteria
 */
getByRole(role: string, options?: LocatorByRoleOptions): Locator;

interface LocatorByRoleOptions extends LocatorOptions {
  /** Should checked elements be included or not */
  checked?: boolean;
  /** Should disabled elements be included or not */
  disabled?: boolean;
  /** Should expanded elements be included or not */
  expanded?: boolean;
  /** Should normally excluded elements be queried */
  includeHidden?: boolean;
  /** Number attribute for heading, listitem, row, treeitem roles */
  level?: number;
  /** Accessible name to match */
  name?: string | RegExp;
  /** Should pressed elements be included or not */
  pressed?: boolean;
  /** Should selected elements be included or not */
  selected?: boolean;
}

Usage Examples:

// Basic roles
page.getByRole("button");
page.getByRole("textbox");
page.getByRole("link");

// With name matching
page.getByRole("button", { name: "Submit Form" });
page.getByRole("button", { name: /submit/i });

// With state filtering
page.getByRole("checkbox", { checked: true });
page.getByRole("button", { disabled: false });
page.getByRole("tab", { selected: true });

// With level (for headings)
page.getByRole("heading", { level: 2 });

getByText

/**
 * Creates a locator by text content. Matches against TextNode's nodeValue 
 * or input's value if type is button or reset. Always normalizes whitespace.
 * @param text - Text to search for (string or RegExp)
 * @param options - Text matching options
 * @returns Locator for elements containing the text
 */
getByText(text: string | RegExp, options?: LocatorOptions): Locator;

Usage Examples:

// Exact text matching
page.getByText("Welcome back");

// Partial text matching (default)
page.getByText("Welcome"); // matches "Welcome back"

// Exact matching
page.getByText("Welcome", { exact: true }); // only matches "Welcome"

// Regular expressions
page.getByText(/welcome/i); // case insensitive
page.getByText(/error.*occurred/); // pattern matching

getByLabelText

/**
 * Creates a locator by label text association. Finds form controls 
 * associated with labels containing the specified text.
 * @param text - Label text to search for
 * @param options - Label matching options
 * @returns Locator for form controls with matching labels
 */
getByLabelText(text: string | RegExp, options?: LocatorOptions): Locator;

Usage Examples:

// Form inputs with labels
page.getByLabelText("Email address");
page.getByLabelText("Password");
page.getByLabelText("Remember me"); // checkbox

// Partial matching
page.getByLabelText("Email"); // matches "Email address"

// Case insensitive with RegExp
page.getByLabelText(/email/i);

getByTestId

/**
 * Creates a locator by test ID attribute. Uses the configured test ID attribute
 * from browser.locators.testIdAttribute (default: "data-testid").
 * @param testId - Test ID value to match
 * @returns Locator for elements with matching test ID
 */
getByTestId(testId: string | RegExp): Locator;

Usage Examples:

// Standard test IDs
page.getByTestId("submit-button");
page.getByTestId("user-profile");

// Pattern matching
page.getByTestId(/button-\d+/);

// Custom test ID attribute (configured in vitest.config.js)
// browser: { locators: { testIdAttribute: "data-cy" } }
page.getByTestId("login-form"); // looks for data-cy="login-form"

Filtering and Chaining

Methods for refining and combining locators.

Filter Method

/**
 * Narrows existing locator according to filter criteria
 * @param options - Filter criteria
 * @returns New locator with applied filters
 */
filter(options: LocatorFilterOptions): Locator;

interface LocatorFilterOptions {
  /** Text content that element should have */
  hasText?: string | RegExp;
  /** Text content that element should NOT have */
  hasNotText?: string | RegExp;
  /** Child locator that element should contain */
  has?: Locator;
  /** Child locator that element should NOT contain */
  hasNot?: Locator;
}

Usage Examples:

// Filter by text content
page.getByRole("listitem").filter({ hasText: "Active" });
page.getByRole("button").filter({ hasNotText: "Disabled" });

// Filter by child elements
page.getByRole("article").filter({ 
  has: page.getByRole("button", { name: "Edit" }) 
});

// Combined filters
page.getByRole("row").filter({
  hasText: "John",
  has: page.getByRole("cell", { name: "Active" })
});

Logical Operators

/**
 * Returns a locator that matches both the current locator and the provided locator
 */
and(locator: Locator): Locator;

/**
 * Returns a locator that matches either the current locator or the provided locator
 */
or(locator: Locator): Locator;

Usage Examples:

// Element must match both conditions
const specificButton = page
  .getByRole("button")
  .and(page.getByText("Submit"));

// Element can match either condition
const anyInput = page
  .getByRole("textbox")
  .or(page.getByRole("searchbox"));

Position Methods

/**
 * Returns a locator for the nth element matching the selector
 */
nth(index: number): Locator;

/**
 * Returns a locator for the first element matching the selector
 */
first(): Locator;

/**
 * Returns a locator for the last element matching the selector
 */
last(): Locator;

Usage Examples:

// Positional selection
page.getByRole("listitem").first();
page.getByRole("listitem").last();
page.getByRole("listitem").nth(2); // third item (0-indexed)
page.getByRole("listitem").nth(-1); // last item

// Multiple elements
const allItems = page.getByRole("listitem").all();
for (const item of allItems) {
  await item.click();
}

Query Methods

Methods for retrieving actual DOM elements from locators.

/**
 * Returns an element matching the selector. Throws if not found or multiple elements match.
 */
element(): Element;

/**
 * Returns an array of elements matching the selector. Returns empty array if none found.
 */
elements(): Element[];

/**
 * Returns an element matching the selector or null if not found. Throws if multiple elements match.
 */
query(): Element | null;

/**
 * Wraps an array of elements matching the selector in new Locators
 */
all(): Locator[];

Usage Examples:

import { page } from "@vitest/browser/context";

// Get single element (throws if not found)
const button = page.getByRole("button").element();
button.click(); // direct DOM API usage

// Safe element access
const maybeButton = page.getByRole("button").query();
if (maybeButton) {
  maybeButton.click();
}

// Get all matching elements
const inputs = page.getByRole("textbox").elements();
inputs.forEach(input => {
  console.log(input.value);
});

// Get locators for all elements
const itemLocators = page.getByRole("listitem").all();
for (const locator of itemLocators) {
  await locator.click(); // use locator API
}

Types

Core locator option interfaces:

interface LocatorOptions {
  /** Whether to find an exact match: case-sensitive and whole-string */
  exact?: boolean;
}

interface LocatorFilterOptions {
  /** Text content that element should have */
  hasText?: string | RegExp;
  /** Text content that element should NOT have */
  hasNotText?: string | RegExp;
  /** Child locator that element should contain */
  has?: Locator;
  /** Child locator that element should NOT contain */
  hasNot?: Locator;
}

interface LocatorScreenshotOptions extends Omit<ScreenshotOptions, 'element'> {
  path?: string;
  base64?: boolean;
  save?: boolean;
}

Install with Tessl CLI

npx tessl i tessl/npm-vitest--browser

docs

assertions.md

commands.md

context.md

index.md

interactions.md

locators.md

providers.md

server.md

utilities.md

tile.json