or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

async-utilities.mdasync.mdconfig.mdconfiguration.mddebugging.mdevents.mdindex.mdqueries.mdquery-helpers.mdrole-utilities.mdscreen.mdutilities.mdwithin.md
tile.json

tessl/npm-testing-library--dom

Simple and complete DOM testing utilities that encourage good testing practices.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@testing-library/dom@10.4.x

To install, run

npx @tessl/cli install tessl/npm-testing-library--dom@10.4.1

index.mddocs/

@testing-library/dom

Simple and complete DOM testing utilities that encourage good testing practices by querying the DOM in the way users find elements. Promotes accessibility-focused testing through queries based on ARIA roles, labels, text content, and other accessible attributes.

Package Information

{
  "name": "@testing-library/dom",
  "version": "10.4.1",
  "install": "npm install --save-dev @testing-library/dom"
}

Core Imports

import {screen, within, waitFor, fireEvent} from '@testing-library/dom';

// All query methods
import {
  getByRole, queryByRole, findByRole,
  getByLabelText, queryByLabelText, findByLabelText,
  getByPlaceholderText, queryByPlaceholderText, findByPlaceholderText,
  getByText, queryByText, findByText,
  getByAltText, queryByAltText, findByAltText,
  getByTitle, queryByTitle, findByTitle,
  getByDisplayValue, queryByDisplayValue, findByDisplayValue,
  getByTestId, queryByTestId, findByTestId
} from '@testing-library/dom';

// Plural variants
import {
  getAllBy*, queryAllBy*, findAllBy*
} from '@testing-library/dom';

// Namespace imports for grouped access
import {queries, queryHelpers} from '@testing-library/dom';

// Access queries through namespace
const element = queries.getByRole(container, 'button', {name: /submit/i});

// Access query helpers through namespace
const customQuery = queryHelpers.buildQueries(...);

Core Concepts

Query Variants

Every query has three variants with different error handling:

  • getBy* - Returns element, throws if 0 or 2+ matches found
  • queryBy* - Returns element or null if not found, throws if 2+ found
  • findBy* - Returns Promise, waits up to 1000ms (async)

Plural variants return arrays and have different throwing behavior.

Query Priority

Use queries in this order (most accessible to least):

  1. getByRole - Accessible to everyone (ARIA roles)
  2. getByLabelText - Form fields
  3. getByPlaceholderText - Form alternative
  4. getByText - Non-interactive content
  5. getByDisplayValue - Current form values
  6. getByAltText - Images
  7. getByTitle - Title attribute
  8. getByTestId - Last resort

Screen vs Container

// Use screen - queries entire document
const button = screen.getByRole('button', {name: /submit/i});

// Use within for scoped queries
const form = screen.getByRole('form');
const emailInput = within(form).getByLabelText('Email');

Quick Start Examples

import {screen, fireEvent, waitFor} from '@testing-library/dom';

// Basic query
const button = screen.getByRole('button', {name: /submit/i});
fireEvent.click(button);

// Form interaction
const email = screen.getByLabelText('Email');
fireEvent.change(email, {target: {value: 'user@example.com'}});

// Async content
await waitFor(() => {
  expect(screen.getByText('Success')).toBeInTheDocument();
});

// Or use findBy directly
const message = await screen.findByText('Success');

Architecture

Query System

  • 8 query types: Role, LabelText, PlaceholderText, Text, DisplayValue, AltText, Title, TestId
  • 3 variants each: get, query, find (plus plural variants)
  • Screen: Global queries bound to document.body
  • Within: Scoped queries to containers

Async Utilities

  • waitFor: Poll with MutationObserver support
  • waitForElementToBeRemoved: Wait for element removal

Events

  • fireEvent: Fire DOM events on elements
  • createEvent: Create events without firing

Utilities

  • Debugging: prettyDOM, logDOM, screen.debug, logTestingPlaygroundURL
  • Configuration: configure, getConfig
  • Role tools: getRoles, logRoles, isInaccessible, computeHeadingLevel
  • Query builders: buildQueries, queryByAttribute, queryAllByAttribute
  • Text tools: getNodeText, getDefaultNormalizer
  • Query suggestions: getSuggestedQuery for better query recommendations

Detailed Documentation

  • Queries - All query methods and types
  • Events - Event simulation
  • Async - Async utilities
  • Screen - Screen object API
  • Within - Scoped queries
  • Config - Configuration
  • Debugging - Debug utilities
  • Query Helpers - Custom queries
  • Role Utilities - ARIA utilities

Additional Utilities

Text Utilities

Extract text content as users perceive it.

function getNodeText(node: HTMLElement): string;

Usage:

import {getNodeText} from '@testing-library/dom';

const element = screen.getByRole('button');
const text = getNodeText(element);  // Returns visible text content

Matcher Utilities

Text normalization for customizing query behavior.

function getDefaultNormalizer(
  options?: DefaultNormalizerOptions
): NormalizerFn;

interface DefaultNormalizerOptions {
  trim?: boolean;  // Default: true
  collapseWhitespace?: boolean;  // Default: true
}

type NormalizerFn = (text: string) => string;

Usage:

import {getDefaultNormalizer, getByText} from '@testing-library/dom';

// Custom normalizer
const normalizer = getDefaultNormalizer({trim: false});
const element = getByText(container, 'Text', {normalizer});

// Case-insensitive matching
const caseInsensitive = (text) => text.toLowerCase();
const element = getByText(container, 'submit', {normalizer: caseInsensitive});

Query Suggestions

Get suggested better queries for improving test quality.

function getSuggestedQuery(
  element: HTMLElement,
  variant?: Variant,
  method?: Method
): Suggestion | undefined;

interface Suggestion {
  queryName: string;
  queryMethod: string;
  queryArgs: QueryArgs;
  variant: string;
  warning?: string;
  toString(): string;
}

type Variant = 'find' | 'findAll' | 'get' | 'getAll' | 'query' | 'queryAll';

type Method = 'Role' | 'LabelText' | 'PlaceholderText' | 'Text' |
              'DisplayValue' | 'AltText' | 'Title' | 'TestId';

Usage:

import {getSuggestedQuery} from '@testing-library/dom';

const button = document.querySelector('button');
const suggestion = getSuggestedQuery(button, 'get');

if (suggestion) {
  console.log(suggestion.toString());
  // "getByRole('button', {name: /submit/i})"
}

// Use with throwSuggestions config
import {configure} from '@testing-library/dom';
configure({throwSuggestions: true});

// Errors now include better query suggestions

TypeScript Support

All APIs are fully typed. The library provides TypeScript definitions with generic types for element narrowing.

import {screen} from '@testing-library/dom';

// Automatically typed as HTMLElement
const button = screen.getByRole('button');

// Narrow to specific element type
const button = screen.getByRole('button') as HTMLButtonElement;

// Or use generic
const button = screen.getByRole<HTMLButtonElement>('button');

Common Patterns

Form Testing

import {screen, fireEvent} from '@testing-library/dom';

// Fill form
fireEvent.change(screen.getByLabelText('Name'), {target: {value: 'John'}});
fireEvent.change(screen.getByLabelText('Email'), {target: {value: 'john@example.com'}});
fireEvent.click(screen.getByRole('button', {name: /submit/i}));

// Verify result
expect(screen.getByText('Thank you')).toBeInTheDocument();

Modal Testing

import {screen, within, fireEvent} from '@testing-library/dom';

fireEvent.click(screen.getByRole('button', {name: /open/i}));

const modal = screen.getByRole('dialog');
expect(within(modal).getByText('Modal Title')).toBeInTheDocument();

fireEvent.click(within(modal).getByRole('button', {name: /close/i}));

Async Content

import {screen, fireEvent, waitFor} from '@testing-library/dom';

fireEvent.click(screen.getByRole('button', {name: /load/i}));

// Wait for loading to complete
await waitFor(() => {
  expect(screen.queryByText('Loading')).not.toBeInTheDocument();
});

// Verify loaded content
expect(screen.getByText('Data loaded')).toBeInTheDocument();

Matchers

All text-based queries accept a Matcher type:

type Matcher = string | RegExp | number | MatcherFunction;

type MatcherFunction = (content: string, element: Element | null) => boolean;

type ByRoleMatcher = ARIARole | string;

// Matcher options
interface MatcherOptions {
  exact?: boolean;  // Exact string match (default: false)
  trim?: boolean;  // Trim whitespace (default: true)
  collapseWhitespace?: boolean;  // Collapse whitespace (default: true)
  normalizer?: NormalizerFn;  // Custom text normalizer
  suggest?: boolean;  // Include query suggestions in errors
}

interface SelectorMatcherOptions extends MatcherOptions {
  selector?: string;  // CSS selector to narrow results
  ignore?: boolean | string;  // CSS selectors to ignore
}

Examples:

// String (substring match)
getByText(container, 'Submit');

// Regex
getByText(container, /submit/i);

// Number
getByText(container, 42);

// Function
getByText(container, (content, el) => content.startsWith('Total:'));

// Exact match
getByText(container, 'Submit', {exact: true});

// With selector
getByText(container, 'Click me', {selector: 'button'});

// With normalizer
getByText(container, 'submit', {
  normalizer: str => str.toLowerCase()
});

Core Types

Common type definitions used throughout the library:

// Query function types
type BoundFunction<T> = T extends (
  container: HTMLElement,
  ...args: infer P
) => infer R
  ? (...args: P) => R
  : never;

interface Queries {
  [T: string]: Query;
}

type Query = (
  container: HTMLElement,
  ...args: any[]
) => Error | HTMLElement | HTMLElement[] | Promise<HTMLElement[]> | Promise<HTMLElement> | null;

// Wait options for async utilities
interface waitForOptions {
  container?: HTMLElement;  // Element to observe (default: document)
  timeout?: number;  // Max wait in ms (default: 1000)
  interval?: number;  // Polling interval in ms (default: 50)
  onTimeout?: (error: Error) => Error;  // Custom timeout error
  mutationObserverOptions?: MutationObserverInit;
}

// Query arguments
type QueryArgs = [string, QueryOptions?];

interface QueryOptions {
  [key: string]: RegExp | boolean;
}