Playwright gère les éléments natifs <select> avec selectOption(). Les composants dropdown personnalisés construits avec <div> et <ul> nécessitent une approche différente : cliquer pour ouvrir, puis sélectionner par rôle ou texte.
Éléments <select> natifs
Le cas le plus simple : un élément HTML <select> standard.
<label for="country">Pays</label>
<select id="country">
<option value="">Sélectionner un pays</option>
<option value="us">États-Unis</option>
<option value="de">Allemagne</option>
<option value="pl">Pologne</option>
</select>// Sélectionner par texte visible
await page.getByLabel('Pays').selectOption('Allemagne');
// Sélectionner par attribut value
await page.getByLabel('Pays').selectOption({ value: 'de' });
// Sélectionner par index (base 0, à éviter — fragile)
await page.getByLabel('Pays').selectOption({ index: 2 });
// Vérifier la sélection
await expect(page.getByLabel('Pays')).toHaveValue('de');
// Sélection multiple (pour <select multiple>)
await page.getByLabel('Tags').selectOption(['playwright', 'typescript']);selectOption() fonctionne uniquement sur les éléments <select>. Pour les dropdowns personnalisés, vous avez besoin d'une approche différente.
Composants dropdown personnalisés
La plupart des applications web modernes utilisent des composants dropdown personnalisés (React Select, Headless UI, Material UI) au lieu du <select> natif. Ils ressemblent à des dropdowns mais fonctionnent différemment sous le capot.
Schéma 1 : cliquer pour ouvrir, puis cliquer l'option
Le schéma dropdown personnalisé le plus courant :
// Dropdown personnalisé : cliquer pour ouvrir, cliquer pour sélectionner
await page.getByRole('combobox', { name: 'Pays' }).click();
await page.getByRole('option', { name: 'Allemagne' }).click();
// Vérifier
await expect(page.getByRole('combobox', { name: 'Pays' })).toHaveText('Allemagne');Si le dropdown utilise un rôle listbox :
await page.getByRole('button', { name: 'Pays' }).click();
await page.getByRole('listbox').getByRole('option', { name: 'Allemagne' }).click();Schéma 2 : taper pour filtrer, puis sélectionner
Beaucoup de dropdowns personnalisés supportent la recherche et le filtrage :
// Taper pour filtrer
await page.getByRole('combobox', { name: 'Pays' }).fill('All');
// Attendre que les résultats filtrés apparaissent
await page.getByRole('option', { name: 'Allemagne' }).waitFor();
// Cliquer l'option
await page.getByRole('option', { name: 'Allemagne' }).click();Schéma 3 : navigation au clavier
Certains dropdowns sont pilotés au clavier :
await page.getByLabel('Pays').focus();
await page.keyboard.press('ArrowDown'); // Ouvrir le dropdown
await page.keyboard.press('ArrowDown'); // Aller à la première option
await page.keyboard.press('ArrowDown'); // Aller à la deuxième option
await page.keyboard.press('Enter'); // SélectionnerOu tapez pour sauter aux options correspondantes :
await page.getByLabel('Pays').focus();
await page.keyboard.type('A'); // Sauter à Allemagne
await page.keyboard.press('Enter');Inspecter l'implémentation réelle du dropdown
Avant d'écrire le test, inspectez l'élément dans les DevTools :
- Clic droit sur le dropdown → Inspecter
- Vérifiez le type d'élément :
<select>ou un<div>/<button>? - Si c'est personnalisé, interagissez avec manuellement et observez les changements du DOM
- Vérifiez l'attribut
roleou les rôles ARIA
La bonne approche de test dépend entièrement de l'implémentation. Ne supposez pas.
React Select (une bibliothèque courante)
React Select est l'une des bibliothèques dropdown les plus utilisées. Elle a un comportement spécifique :
// Combobox React Select
const dropdown = page.locator('.react-select__control');
await dropdown.click();
// Taper pour filtrer
await dropdown.locator('input').fill('All');
await page.locator('.react-select__option', { hasText: 'Allemagne' }).click();
// Vérifier
await expect(page.locator('.react-select__single-value')).toHaveText('Allemagne');
// Effacer la sélection
await page.locator('.react-select__clear-indicator').click();React Select utilise des classes CSS spécifiques. Si votre version génère des noms de classe différents, adaptez en conséquence. Préférez getByRole quand c'est possible :
// Meilleur — utilise les rôles sémantiques
await page.getByRole('combobox', { name: 'Pays' }).click();
await page.getByRole('option', { name: 'Allemagne' }).click();Dropdowns à sélection multiple
// <select multiple> natif
await page.getByLabel('Compétences').selectOption(['playwright', 'typescript', 'cicd']);
// Sélection multiple personnalisée : cliquer plusieurs options
await page.getByRole('button', { name: 'Compétences' }).click();
await page.getByRole('option', { name: 'Playwright' }).click();
await page.getByRole('option', { name: 'TypeScript' }).click();
await page.getByRole('option', { name: 'CI/CD' }).click();
// Fermer le dropdown
await page.keyboard.press('Escape');
// Vérifier les sélections
await expect(page.getByTestId('selected-skills')).toContainText('Playwright');
await expect(page.getByTestId('selected-skills')).toContainText('TypeScript');Dropdowns de date (sélecteurs jour, mois, année)
Champs de date avec dropdowns séparés pour le mois, le jour et l'année :
await page.getByLabel('Mois').selectOption('Juin');
await page.getByLabel('Jour').selectOption('15');
await page.getByLabel('Année').selectOption('1990');Pour les <input type="date"> :
// Fonctionne sur tous les navigateurs
await page.getByLabel('Date de naissance').fill('1990-06-15');
// Vérifier
await expect(page.getByLabel('Date de naissance')).toHaveValue('1990-06-15');Vérifier les options du dropdown
// Vérifier que toutes les options sont présentes
const options = await page.getByLabel('Pays').locator('option').allTextContents();
expect(options).toContain('Allemagne');
expect(options).toContain('Pologne');
// Vérifier qu'une option spécifique est désactivée
await expect(page.getByRole('option', { name: 'Article épuisé' })).toBeDisabled();
// Vérifier le nombre d'options
const optionCount = await page.getByLabel('Catégorie').locator('option').count();
expect(optionCount).toBeGreaterThan(0);Erreurs courantes
Utiliser selectOption() sur un dropdown personnalisé. Fonctionne uniquement sur les <select>. Les dropdowns personnalisés nécessitent des interactions au clic ou au clavier.
Ne pas attendre que les options apparaissent. Après avoir ouvert un dropdown qui charge les options de façon asynchrone, attendez que l'option soit visible avant de cliquer.
Sélectionner par index. Fragile : une nouvelle option ajoutée avant la vôtre casse le test. Utilisez le texte ou la valeur plutôt que l'index.
Ne pas vérifier ce que le dropdown affiche après la sélection. Assertez que la valeur sélectionnée est correcte, pas juste que le clic n'a pas levé d'erreur.
→ Voir aussi: Locators Playwright: getByRole, getByLabel, getByText, getByTestId Comparés | Assertions dans Playwright: Le Guide Complet | Gestion des Onglets Multiples, Fenêtres et iFrames dans Playwright