
Company News
Socket Named Top Sales Organization by RepVue
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.
playwright-testing-library
Advanced tools
🔍 Find elements in playwright like your users with queries from @testing-library/dom
All of your favorite user-centric querying functions from @testing-library/react and @testing-library/dom available from within Playwright!
ElementHandle queries (getDocument + queries) ↓waitFor assertion helper (via wait-for-expect)# For use with Playwright Test (@playwright/test)
npm install --save-dev @playwright-testing-library/test
# For use with Playwright (playwright)
npm install --save-dev playwright-testing-library
There are currently a few different ways to use Playwright Testing Library, depending, however using the Locator queries fixture with Playwright Test (@playwright/test) is the recommended approach.
⚠️ The
ElementHandlequery APIs were created before Playwright introduced itsLocatorAPI and will be replaced in the next major version of Playwright Testing Library. If you can't use @playwright/test at the moment, you'll need to use theElementHandlequery API, but a migration path will be provided when we switch to the newLocatorAPIs.
Using the Locator Playwright Test (@playwright/test) fixture with @playwright-testing-library/test.
import {test as base} from '@playwright/test'
import {
locatorFixtures as fixtures,
LocatorFixtures as TestingLibraryFixtures,
} from '@playwright-testing-library/test/fixture'
const test = base.extend<TestingLibraryFixtures>(fixtures)
const {expect} = test
test('my form', async ({screen, within}) => {
// Screen provides `Locator` queries scoped to current Playwright `Page`
const formLocator = screen.getByTestId('my-form')
// Scope queries to `Locator` with `within`
// (note that this is a fixture from `test`, not the `within` import)
const emailInputLocator = within(formLocator).getByLabelText('Email')
// Interact via `Locator` API 🥳
await emailInputLocator.fill('email@playwright.dev')
await emailInputLocator.press('Enter')
// Screen also provides Playwright's `Page` API
screen.goto('/account')
const emailLocator = screen.getByRole('heading', {level: 2})
// Assert via `Locator` APIs 🎉
await expect(emailLocator).toHaveText('email@playwright.dev')
})
The Locator query API is configured using Playwright's use API. See Playwright's documentation for global, project, and test.
Configuring Testing Library globally in playwright.config.ts
import type {PlaywrightTestConfig} from '@playwright/test'
const config: PlaywrightTestConfig = {
use: {
// These are the defaults
testIdAttribute: 'data-testid',
asyncUtilTimeout: 1000,
asyncUtilExpectedState: 'visible',
},
}
export default config
Scoping Testing Library configuration to test suites or describe blocks
import {test as base} from '@playwright/test'
import {
locatorFixtures as fixtures,
LocatorFixtures as TestingLibraryFixtures,
} from '@playwright-testing-library/test/fixture'
const test = base.extend<TestingLibraryFixtures>(fixtures)
const {describe, expect, use} = test
// Entire test suite
use({testIdAttribute: 'data-custom-test-id'})
describe(() => {
// Specific block
use({
testIdAttribute: 'some-other-test-id',
asyncUtilsTimeout: 5000,
asyncUtilExpectedState: 'attached',
})
test('my form', async ({screen}) => {
// ...
})
})
Using the ElementHandle Playwright Test (@playwright/test) fixture with @playwright-testing-library/test.
⚠️ See note in Usage as you should be using the
Locatorfixture if possible
import {test as base} from '@playwright/test'
import {fixtures, within, TestingLibraryFixtures} from '@playwright-testing-library/test/fixture'
const test = base.extend<TestingLibraryFixtures>(fixtures)
const {expect} = test
test('my form', async ({page, queries}) => {
// Query methods are available in `test` blocks
const formHandle = await queries.getByTestId('my-form')
// Scope queries to an `ElementHandle` with `within`
const emailInputHandle = await within(formHandle).getByLabelText('Email')
// Interact via `ElementHandle` API
await emailInputHandle.fill('email@playwright.dev')
await emailInputHandle.press('Enter')
page.goto('/account')
const emailHandle = queries.getByRole('heading', {level: 2})
// Assert via `ElementHandle` APIs
expect(await emailHandle.textContent()).toEqual('email@playwright.dev')
})
import {test as base} from '@playwright/test'
import {
configure,
fixtures,
within,
TestingLibraryFixtures,
} from '@playwright-testing-library/test/fixture'
const test = base.extend<TestingLibraryFixtures>(fixtures)
const {beforeEach, describe, expect} = test
// Global (these are the defaults)
configure({asyncUtilTimeout: 1000, testIdAttribute: 'data-testid'})
// Specific block
describe('my page', () => {
beforeEach(() => configure({asyncUtilTimeout: 5000, testIdAttribute: 'data-custom-test-id'}))
afterEach(() => configure({}))
test('my form', async ({page, queries}) => {
// ...
})
})
Using the ElementHandle queries with Playwright (playwright) and playwright-testing-library.
⚠️ See note in Usage as you should be using @playwright/test with the
Locatorfixture if possible. TheLocatorqueries will be made available for standalone playwright in the next major release.
import {beforeAll, expect, jest, test} from '@jest/globals'
import {webkit} from 'playwright' // or 'firefox' or 'chromium'
import {getDocument, queries, within} from 'playwright-testing-library'
let browser: playwright.Browser
let page: playwright.Page
beforeAll(() => {
const browser = await webkit.launch()
const page = await browser.newPage()
})
test('my form', () => {
// Get `ElementHandle` for document from `Page`
const documentHandle = await getDocument(page)
// Global query methods take document handle as the first parameter
const formHandle = await queries.getByTestId(documentHandle, 'my-form')
// Scope queries to an `ElementHandle` with `within`
const emailInputHandle = await within(formHandle).getByLabelText('Email')
// Interact via `ElementHandle` API
await emailInputHandle.fill('email@playwright.dev')
await emailInputHandle.press('Enter')
page.goto('/account')
const accountHandle = getDocument(page)
const emailHandle = queries.getByRole(accountHandle, 'heading', {level: 2})
// Assert via `ElementHandle` APIs
expect(await emailHandle.textContent()).toEqual('email@playwright.dev')
})
import {beforeEach, afterEach, expect, jest, test} from '@jest/globals'
import {configure, getDocument, queries, within} from 'playwright-testing-library'
// Global (these are the defaults)
configure({asyncUtilTimeout: 1000, testIdAttribute: 'data-testid'})
// Specific block
describe('my page', () => {
beforeEach(() => configure({asyncUtilTimeout: 5000, testIdAttribute: 'data-custom-test-id'}))
afterEach(() => configure({}))
test('my form', async ({page, queries}) => {
// ...
})
})
All queries from @testing-library/dom are supported.
📝 The
find*queries for theLocatorqueries returnPromise<Locator>which resolves when the element is found before the timeout specified viaasyncUtilTimeout
Unique methods, not part of @testing-library/dom
⚠️ These only apply to the
ElementHandlequeries
Get an ElementHandle for the document
getDocument(page: playwright.Page): ElementHandle
Wait for an assertion (wrapper around wait-for-expect)
waitFor(
expectation: () => void | Promise<void>,
timeout?: number,
interval?: number
): Promise<{}>
testIdAttribute and asyncUtilTimeout are supported as configuration optionswaitForElement, waitForElementToBeRemoved and waitForDomChange are not exposed. Consider using a find* query or a Playwright built-in like Locator.waitFor().fireEvent method is not exposed, use Playwright's built-ins instead.getNodeText() function is not currently supported for Locator.MIT
This project is actively maintained by engineers at @hoverinc 😀.
FAQs
playwright + dom-testing-library
We found that playwright-testing-library demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.

Security News
NIST will stop enriching most CVEs under a new risk-based model, narrowing the NVD's scope as vulnerability submissions continue to surge.

Company News
/Security News
Socket is an initial recipient of OpenAI's Cybersecurity Grant Program, which commits $10M in API credits to defenders securing open source software.