CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-testing-library--dom

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

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

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;
}

docs

async.md

config.md

debugging.md

events.md

index.md

queries.md

query-helpers.md

role-utilities.md

screen.md

within.md

tile.json