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
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
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 correspondants | Exemple 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
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
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
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
// <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
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éthode | Scénario d'application | Priorité |
|---|---|---|
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 placeholder | Deuxiè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
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
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
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
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
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
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 de
getByRole、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
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
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
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
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éthode | Condition d'utilisation |
|---|---|---|
| 1 (La plus recommandée) | getByRole() | L'élément a un rôle ARIA clair |
| 2 | getByLabel() | L'élément de formulaire a une étiquette associée |
| 3 | getByPlaceholder() | Le champ de saisie a un attribut placeholder |
| 4 | getByText() | L'élément a un contenu textuel clair |
| 5 | getByAltText() | L'image a un attribut alt |
| 6 | getByTitle() | 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 |