Playwright i stabilne selektory - atrybut data-testid

Playwright i stabilne selektory - atrybut data-testid

Wstęp

Selektory zbudowane na :nth-child i długich łańcuchach klas pękają przy pierwszym refaktorze UI. W best practices Cypressa zaleca się wybieranie elementów po dedykowanych atrybutach data-* (w przykładach Cypressa i w równoległym wpisie pojawia się m.in. data-cy). W przykładach Playwright poniżej używam wyłącznie data-testid: tak nazywa atrybut, którego szuka getByTestId - to ten sam pomysł co rekomendacja Cypressa, bez mieszania konwencji nazw w kodzie testów.

Poprzedni odcinek: URL-e i konfiguracja.

Atrybut data-testid

Playwright domyślnie mapuje getByTestId(...) na selektor [data-testid=...] - nie trzeba nic zmieniać w playwright.config.ts, żeby pisać zgodnie z dokumentacją narzędzia.

Przykład w Login.js (odpowiednik refaktoryzacji z serii o Cypressie, z atrybutem pod Playwright):

<input
  className="form-control form-control-lg"
  type="email"
  data-testid="email-input"
  ...
/>
<input
  type="password"
  data-testid="password-input"
  ...
/>
<button type="submit" data-testid="sign-in-button">
  Sign in
</button>

Test

import { test, expect } from "@playwright/test"

test("loguje użytkownika", async ({ page }) => {
  await page.goto("/login")
  await page.getByTestId("email-input").fill("test@test.com")
  await page.getByTestId("password-input").fill("test")
  await page.getByTestId("sign-in-button").click()
  await expect(page).toHaveURL(/localhost:4100\/$/)
})

getByTestId łączy się z innymi lokatorami (filter, and) i korzysta z tego samego auto-waitu co pozostałe API.

Materiały wideo

Nagrania z tamtego wpisu nadal dobrze ilustrują dodawanie atrybutu w React:

Selector playground (mp4)

Email input (mp4)

Kod na GitHubie

Zmiany w aplikacji i testach z oryginalnej serii:

https://github.com/12masta/react-redux-realworld-example-app/tree/5-cypress

https://github.com/12masta/react-redux-realworld-example-app/pull/6/files

Następny odcinek: Wiele przeglądarek z Playwright.