Localisateurs Playwright

Un Locator est l'un des concepts fondamentaux de Playwright. Il représente un moyen de trouver des éléments sur une page.

Ce chapitre présente les méthodes de localisation recommandées par Playwright : localiser des éléments par rôle, texte, libellé et placeholder.


Qu'est-ce qu'un Locator

Un Locator est un objet abstrait que Playwright utilise pour trouver des éléments sur une page.

Contrairement auxdocument.querySelector()façons, le Locator de Playwright possèdel'attente automatique et le réessai automatique en tant quecapacités.

Lorsque le contenu de la page change dynamiquement, le Locator recherche continuellement à nouveau des éléments jusqu'à ce qu'il trouve un élément correspondant ou que le délai expire.

Exemple

// Créer un Locator (aucune recherche d'élément n'a lieu immédiatement)
const button = page.getByRole('button', { name: 'Submit' });

// Lors de l'exécution d'une action, Playwright attend automatiquement que le bouton apparaisse et devienne actionnable
await button.click();

Comment fonctionnent les Locators

Lorsque vous créez un Locator, Playwright enregistre uniquement une règle de recherche.

Lorsque vous appelez.click()、.fill()des actions ouexpect(locator)des assertions, le Locator commence réellement à rechercher des éléments.

Si l'élément ne peut pas être trouvé, le Locator continuera de réessayer jusqu'à ce que l'opération expire.


Localisation par rôle : getByRole()

getByRole()est la méthode de localisation la plus recommandée par Playwright.

Il utilise lerôle d'accessibilité (ARIA Role)de l'élément pour trouver des éléments, ce qui est le plus proche de la façon dont les utilisateurs les perçoivent.

Utilisation de base

Exemple

// Localiser un bouton - par rôle "button"
const submitBtn = page.getByRole('button', { name: 'Submit' });
await submitBtn.click();

// Localiser un lien - par rôle "link"
const homeLink = page.getByRole('link', { name: 'Accueil' });
await homeLink.click();

// Localiser un titre - par rôle "heading"
const mainTitle = page.getByRole('heading', { name: 'Bienvenue sur EXAMPLE' });

// Localiser une zone de texte - par rôle "textbox"
const searchBox = page.getByRole('textbox', { name: 'Recherche' });
await searchBox.fill('Playwright');

Rôles ARIA courants

RôleÉléments HTML correspondantsExemple d'utilisation
'button'<button>、role="button"getByRole('button', { name: '登录' })
'link'<a>getByRole('link', { name: '了解更多' })
'heading'<h1>~<h6>getByRole('heading', { name: 'EXAMPLE 教程' })
'textbox'<input type="text">、<textarea>getByRole('textbox', { name: '用户名' })
'checkbox'<input type="checkbox">getByRole('checkbox', { name: '记住我' })
'radio'<input type="radio">getByRole('radio', { name: '男' })
'combobox'<select>getByRole('combobox', { name: '城市' })
'img'<img>getByRole('img', { name: 'Logo' })
'list'<ul>、<ol>getByRole('list')
'listitem'<li>getByRole('listitem')
'navigation'<nav>getByRole('navigation')
'table'<table>getByRole('table')

L'option name

nameL'option utilise lenom accessible de l'élémentpour réduire la portée.

Les sources du nom accessible comprennent : le contenu textuel de l'élément,aria-labelattributs, associés<label>etc.

Exemple

// Correspondance par le texte du bouton
page.getByRole('button', { name: 'Login' });

// Correspondance par aria-label
page.getByRole('button', { name: 'Close dialog' });

// Correspondance par expression régulière
page.getByRole('link', { name: /EXAMPLE|rookie/ });

Options d'état

En plus dename,getByRoleil prend également en charge plusieurs options d'état :

Exemple

// Localiser la case à cocher cochée
page.getByRole('checkbox', { checked: true });

// Localiser le bouton désactivé
page.getByRole('button', { disabled: true });

// Localiser le menu déroulant développé
page.getByRole('button', { expanded: true });

// Localiser l'option sélectionnée
page.getByRole('option', { selected: true });

// Combiner plusieurs états
page.getByRole('checkbox', { name: 'Accepter les conditions', checked: false });

Localisation par texte : getByText()

getByText()Pour localiser par lecontenu textuelde l'élément.

Exemple

// Correspondance exacte du texte
page.getByText('Welcome to EXAMPLE');

// Correspondance partielle (par défaut)
page.getByText('EXAMPLE');

// Forcer la correspondance exacte
page.getByText('EXAMPLE', { exact: true });

// Correspondance par expression régulière
page.getByText(/EXAMPLE|rookie tutorial/);

getByTextIl correspond au contenu textuel complet de l'élément, doncgetByText('EXAMPLE', { exact: true })il ne correspondra qu'aux éléments dont le contenu textuel est exactement "EXAMPLE".

Par défaut, lorsque la correspondance exacte n'est pas utilisée, la correspondance de sous-chaîne suffit (par exemple,getByText('EXAMPLE')il correspondra à "Welcome to EXAMPLE").


Localisation par libellé : getByLabel()

getByLabel()Utilisé pour localiser<label>les contrôles de formulaire associés.

Exemple

// Structure HTML :
// <label for="username">Username</label>
// <input id="username" type="text" />

// Localiser le champ via le texte de l'étiquette
await page.getByLabel('Username').fill('example_user');

// Structure HTML :
// <label>Password <input type="password" /></label>

// Les étiquettes imbriquées sont également valides
await page.getByLabel('Password').fill('password123');

Il prend également en charge{ exact: true }les options de correspondance exacte.


Localisation par placeholder : getByPlaceholder()

getByPlaceholder()Grâce à laplaceholderattribut placeholder pour localiser les champs de saisie.

Exemple

// Structure HTML : <input placeholder="Please enter a search keyword" />
await page.getByPlaceholder('Please enter a search keyword').fill('Playwright');

// Structure HTML : <textarea placeholder="Tell us what you think..."></textarea>
await page.getByPlaceholder('Tell us what you think...').fill('The EXAMPLE tutorial is great!');

Choisir entre getByLabel et getByPlaceholder

MéthodeScénario d'applicationPriorité
getByLabel()Lorsqu'il y a un élément <label>L'utiliser en premier
getByPlaceholder()Lorsqu'il n'y a pas de label, mais qu'il y a un placeholderDeuxième choix

getByRoleest la méthode de localisation la plus recommandée de Playwright car elle simule la façon dont les utilisateurs identifient les éléments par leur rôle. La suivante estgetByLabeletgetByPlaceholder. N'envisagez de l'utiliser que lorsqu'il n'y a pas d'éléments sémantiques.getByTestIdou les sélecteurs CSS.


getByAltText() pour localiser une image

getByAltText()Grâce à l'attributaltalt de l'image pour localiser<img>l'élément <img>.

Exemple

// HTML:<img src="logo.png" alt="EXAMPLE Logo" />
await expect(page.getByAltText('EXAMPLE Logo')).toBeVisible();

// Correspondance par expression régulière
await expect(page.getByAltText(/logo/i)).toBeVisible();

getByTitle() pour la localisation par attribut title

getByTitle()Grâce à l'attributtitletitle de l'élément pour localiser.

Exemple

// HTML: <button title="Close current page">X</button>
await page.getByTitle('Fermer la page actuelle').click();

getByAltTextetgetByTitleUtilisé moins fréquemment ; uniquement lorsque l’élément possède un attribut alt ou title explicite et ne peut pas être localisé par d’autres moyens.


getByTestId() pour la localisation par Test ID

getByTestId()OuiSolution de repli, viadata-testidattribut pour localiser l’élément.

Exemple

// HTML : <button data-testid="submit-btn">Soumettre</button>
await page.getByTestId('submit-btn').click();

// Peut contenir plusieurs correspondances (par ex., éléments de liste)
const items = page.getByTestId('todo-item');
await expect(items).toHaveCount(3);

Personnalisation de l’attribut testId

Si votre projet n’utilise pasdata-testid, vous pouvezplaywright.config.tspersonnalisez le nom de l’attribut dans :

Exemple

// Chemin du fichier : playwright.config.ts
export default defineConfig({
  use: {
    // Utiliser data-cy au lieu de data-testid (pour la migration Cypress)
    testIdAttribute: 'data-cy',
    // Ou utiliser id comme testId
    // testIdAttribute: 'id',
  },
});

Localisation CSS et XPath avec page.locator()

page.locator()Prend en charge les sélecteurs CSS et XPath, servant de solution de secours plus flexible.

Sélecteurs CSS

Exemple

// Par nom de classe CSS
await page.locator('.submit-btn').click();

// Par ID
await page.locator('#username').fill('example_user');

// Par attribut
await page.locator('[data-type="primary"]').click();

// Par combinaison de balise + classe
await page.locator('button.primary').click();

// Par relation parent-enfant
await page.locator('nav a').first().click();

// Sélecteur CSS contenant un texte spécifique
await page.locator('button:has-text("Submit")').click();

Localisation XPath

Exemple

// Localiser avec XPath
await page.locator('xpath=//button[@type="submit"]').click();

// Localiser par texte
await page.locator('xpath=//h1[contains(text(), "EXAMPLE")]').click();

Les sélecteurs CSS et XPath sont en dernier recours ; privilégiez l'utilisation degetByRole、getByTextméthodes de localisation sémantiques. Les sélecteurs CSS sont susceptibles de casser en raison de la refactorisation de style, et XPath a une mauvaise lisibilité et des performances plus lentes.


Chaînage de Locator

Le Locator de Playwright prend en charge le chaînage, permettant un filtrage supplémentaire sur les résultats correspondants actuels.

.first()、.last()、.nth()

Exemple

// Obtenir le premier élément de liste correspondant
const firstItem = page.getByRole('listitem').first();

// Obtenir le dernier
const lastItem = page.getByRole('listitem').last();

// Obtenir le 2e (l'index commence à 0)
const secondItem = page.getByRole('listitem').nth(1);

.filter() Filtrage

Exemple

// Filtrer les boutons contenant un texte spécifique
page.getByRole('button').filter({ hasText: 'Save' });

// Exclure ceux qui ne contiennent pas un texte spécifique
page.getByRole('listitem').filter({ hasNotText: 'Deleted' });

// Filtrer ceux qui contiennent un élément enfant spécifique
page.getByRole('listitem').filter({ has: page.getByRole('button') });

// Filtrer ceux qui ne contiennent pas un élément enfant spécifique
page.getByRole('listitem').filter({ hasNot: page.getByTestId('badge') });

.locator() pour la localisation d'éléments enfants

Exemple

// Localisez d'abord le conteneur de la liste, puis trouvez les boutons qu'il contient
const list = page.getByTestId('todo-list');
const deleteBtn = list.locator('button.delete');
await deleteBtn.click();

// Imbrication à plusieurs niveaux
page
  .getByRole('dialog')
  .locator('div.content')
  .locator('button')
  .filter({ hasText: 'Confirm' })
  .click();

.and() et .or() Combinaisons logiques (1.63+)

Exemple

// Satisfaire les deux conditions simultanément
const btn = page.getByRole('button')
  .et(page.getByText('Submit'));

// Satisfaire l'une ou l'autre condition
const target = page.getByText('EXAMPLE')
  .ou(page.getByTitle('EXAMPLE'));

Résumé de la priorité de la stratégie de localisation

Classées de la plus recommandée à la moins recommandée :

PrioritéMéthodeCondition d'utilisation
1 (La plus recommandée)getByRole()L'élément a un rôle ARIA clair
2getByLabel()L'élément de formulaire a une étiquette associée
3getByPlaceholder()Le champ de saisie a un attribut placeholder
4getByText()L'élément a un contenu textuel clair
5getByAltText()L'image a un attribut alt
6getByTitle()L'élément a un attribut title
7 (Solution de secours)getByTestId()Lorsqu'il est impossible de localiser à l'aide des méthodes ci-dessus
8 (Dernier recours)locator()Sélecteurs CSS / XPath
Autres extensions