npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

playwright-testing-library

v4.5.0

Published

playwright + dom-testing-library

Downloads

11,738

Readme

Build Status Test Coverage Code Style Package Version MIT License Conventional Commits Maintenance

🎛 Features

All of your favorite user-centric querying functions from @testing-library/react and @testing-library/dom available from within Playwright!

  • Test fixture for @playwright/test via @playwright-testing-library/test
    • NewLocator queries fixture (locatorFixtures)
    • ElementHandle queries fixture (fixtures)
  • Standalone queries for playwright via playwright-testing-library
    • ElementHandle queries (getDocument + queries)
    • Asynchronous waitFor assertion helper (via wait-for-expect)

🌱 Installation

# 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

📝 Usage

There are currently a few different ways to use Playwright Testing Library, depending on how you use Playwright. However, the recommended approach is using the Locator queries fixture with Playwright Test (@playwright/test).

⚠️ The ElementHandle query APIs were created before Playwright introduced its Locator API 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 the ElementHandle query API, but a migration path will be provided when we switch to the new Locator APIs.

Playwright Test Fixture

🔖 Added in 4.4.0

Using the Locator Playwright Test (@playwright/test) fixture with @playwright-testing-library/test.

Setup

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 protected]')
  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 protected]')
})

Async Methods

The findBy queries work the same way as they do in Testing Library core in that they return Promise<Locator> and are intended to be used to defer test execution until an element appears on the page.

test('my modal', async ({screen, within}) => {
  // Here we wait for a modal to appear asynchronously before continuing
  // Note: the timeout for `findBy` queries is configured with `asyncUtilTimeout`
  const modalLocator = await screen.findByRole('dialog')

  // Once the modal is visible, we can interact with its contents and assert
  await expect(modalLocator).toHaveText(/My Modal/)
  await within(modalLocator).getByRole('button', {name: 'Okay'}).click()

  // We can also use `queryBy` methods to take advantage of Playwright's `Locator` auto-waiting
  // See: https://playwright.dev/docs/actionability
  // Note: this will use Playwright's timeout, not `asyncUtilTimeout`
  await expect(screen.queryByRole('dialog')).toBeHidden()
})

Chaining

🔖 Added in 4.5.0

As an alternative to the within(locator: Locator) function you're familiar with from Testing Library, Playwright Testing Library also supports chaining queries together.

All synchronous queries (get* + query*) return Locator instances are augmented with a .within() method (TestingLibraryLocator). All asynchronous queries (find*) return a special LocatorPromise that also supports .within(). This makes it possible to chain queries, including chaining get*, query* and find* interchangeably.

⚠️ Note that including any find* query in the chain will make the entire chain asynchronous

Synchronous
test('chaining synchronous queries', async ({screen}) => {
  const locator = screen.getByRole('figure').within().findByRole('img')

  expect(await locator.getAttribute('alt')).toEqual('Some image')
})
Synchronous + Asynchronous
test('chaining synchronous queries + asynchronous queries', ({screen}) => {
  //              ↓↓↓↓↓ including any `find*` queries makes the whole chain asynchronous
  const locator = await screen
    .getByTestId('modal-container') // Get "modal container" or throw (sync)
    .within()
    .findByRole('dialog') // Wait for modal to appear (async, until `asyncUtilTimeout`)
    .within()
    .getByRole('button', {name: 'Close'}) // Get close button within modal (sync)

  expect(await locator.textContent()).toEqual('Close')
})

Configuration

The Locator query API is configured using Playwright's use API. See Playwright's documentation for global, project, and test.

Global

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
Local

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}) => {
    // ...
  })
})

Legacy Playwright Test Fixture

Using the ElementHandle Playwright Test (@playwright/test) fixture with @playwright-testing-library/test.

⚠️ See note in Usage as you should be using the Locator fixture if possible

Setup

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 protected]')
  await emailInputHandle.press('Enter')

  page.goto('/account')

  const emailHandle = queries.getByRole('heading', {level: 2})

  // Assert via `ElementHandle` APIs
  expect(await emailHandle.textContent()).toEqual('[email protected]')
})

Configuration

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}) => {
    // ...
  })
})

Standalone Playwright 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 Locator fixture if possible. The Locator queries 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 protected]')
  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 protected]')
})

Configuration

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}) => {
    // ...
  })
})

🔌 API

Testing Library

All queries from @testing-library/dom are supported.

📝 The find* queries for the Locator queries return Promise<Locator> which resolves when the element is found before the timeout specified via asyncUtilTimeout

Additional

Unique methods, not part of @testing-library/dom

⚠️ These only apply to the ElementHandle queries

  • 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<{}>

Known Limitations

  • Only testIdAttribute and asyncUtilTimeout are supported as configuration options
  • Async utilities waitForElement, waitForElementToBeRemoved and waitForDomChange are not exposed. Consider using a find* query or a Playwright built-in like Locator.waitFor().
  • The fireEvent method is not exposed, use Playwright's built-ins instead.
  • Assertion extensions from jest-dom are not compatible, use Playwright Test if possible.

Locator Queries

  • The getNodeText() function is currently unsupported.

  • When using a function for TextMatch, the function cannot reference its closure scope

    // ✅ This is supported
    screen.getByText(content => content.startsWith('Foo'))
    
    // ❌ This is not supported
    const startsWithFoo = (content: string) => content.startsWith('Foo')
    
    screen.getByText(content => startsWithFoo(content))

Special Thanks

Related Playwright Test Utilities

LICENSE

MIT

Maintenance

This project is actively maintained by engineers at @hoverinc 😀.