IMPORTANT - Résolution des chemins :
Cette compétence peut être installée à différents endroits (système de plugins, installation manuelle, global ou spécifique au projet). Avant d'exécuter toute commande, déterminez le répertoire de la compétence en fonction de l'endroit où vous avez chargé ce fichier SKILL.md, et utilisez ce chemin dans toutes les commandes ci-dessous. Remplacez $SKILL_DIR par le chemin réellement découvert.
Chemins d'installation courants :
- Système de plugins :
~/.claude/plugins/marketplaces/playwright-skill/skills/playwright-skill - Global manuel :
~/.claude/skills/playwright-skill - Spécifique au projet :
<project>/.claude/skills/playwright-skill
Automatisation de navigateur Playwright
Compétence polyvalente d'automatisation de navigateur. J'écrirai du code Playwright personnalisé pour toute tâche d'automatisation que vous demandez et l'exécuterai via l'exécuteur universel.
FLUX DE TRAVAIL CRITIQUE - Suivez ces étapes dans l'ordre :
-
Détection automatique des serveurs de développement - Pour les tests sur localhost, EXÉCUTEZ TOUJOURS la détection des serveurs D'ABORD :
cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(servers => console.log(JSON.stringify(servers)))"- Si 1 serveur trouvé : Utilisez-le automatiquement, informez l'utilisateur
- Si plusieurs serveurs trouvés : Demandez à l'utilisateur lequel tester
- Si aucun serveur trouvé : Demandez l'URL ou proposez d'aider à démarrer le serveur de développement
-
Écrire les scripts dans /tmp - NE JAMAIS écrire les fichiers de test dans le répertoire de compétence ; utilisez toujours
/tmp/playwright-test-*.js -
Utiliser le navigateur visible par défaut - Utilisez toujours
headless: falsesauf si l'utilisateur demande explicitement le mode headless -
Paramétrer les URLs - Rendre toujours les URLs configurables via variable d'environnement ou constante en haut du script
Comment ça marche
- Vous décrivez ce que vous voulez tester/automatiser
- Je détecte automatiquement les serveurs de développement en cours d'exécution (ou demande l'URL pour tester un site externe)
- J'écris du code Playwright personnalisé dans
/tmp/playwright-test-*.js(ne polluera pas votre projet) - Je l'exécute via :
cd $SKILL_DIR && node run.js /tmp/playwright-test-*.js - Les résultats s'affichent en temps réel, fenêtre du navigateur visible pour le débogage
- Les fichiers de test sont auto-nettoyés de /tmp par votre OS
Installation (Première fois)
cd $SKILL_DIR
npm run setup
Cela installe Playwright et le navigateur Chromium. À faire une seule fois.
Modèle d'exécution
Étape 1 : Détecter les serveurs de développement (pour les tests sur localhost)
cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(s => console.log(JSON.stringify(s)))"
Étape 2 : Écrire le script de test dans /tmp avec paramètre d'URL
// /tmp/playwright-test-page.js
const { chromium } = require('playwright');
// URL paramétrée (détectée ou fournie par l'utilisateur)
const TARGET_URL = 'http://localhost:3001'; // <-- Auto-détectée ou de l'utilisateur
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto(TARGET_URL);
console.log('Page chargée:', await page.title());
await page.screenshot({ path: '/tmp/screenshot.png', fullPage: true });
console.log('📸 Capture d\'écran enregistrée dans /tmp/screenshot.png');
await browser.close();
})();
Étape 3 : Exécuter depuis le répertoire de compétence
cd $SKILL_DIR && node run.js /tmp/playwright-test-page.js
Modèles courants
Tester une page (plusieurs viewports)
// /tmp/playwright-test-responsive.js
const { chromium } = require('playwright');
const TARGET_URL = 'http://localhost:3001'; // Auto-détectée
(async () => {
const browser = await chromium.launch({ headless: false, slowMo: 100 });
const page = await browser.newPage();
// Test desktop
await page.setViewportSize({ width: 1920, height: 1080 });
await page.goto(TARGET_URL);
console.log('Desktop - Titre:', await page.title());
await page.screenshot({ path: '/tmp/desktop.png', fullPage: true });
// Test mobile
await page.setViewportSize({ width: 375, height: 667 });
await page.screenshot({ path: '/tmp/mobile.png', fullPage: true });
await browser.close();
})();
Tester un flux de connexion
// /tmp/playwright-test-login.js
const { chromium } = require('playwright');
const TARGET_URL = 'http://localhost:3001'; // Auto-détectée
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto(`${TARGET_URL}/login`);
await page.fill('input[name="email"]', 'test@example.com');
await page.fill('input[name="password"]', 'password123');
await page.click('button[type="submit"]');
// Attendre la redirection
await page.waitForURL('**/dashboard');
console.log('✅ Connexion réussie, redirection vers le tableau de bord');
await browser.close();
})();
Remplir et soumettre un formulaire
// /tmp/playwright-test-form.js
const { chromium } = require('playwright');
const TARGET_URL = 'http://localhost:3001'; // Auto-détectée
(async () => {
const browser = await chromium.launch({ headless: false, slowMo: 50 });
const page = await browser.newPage();
await page.goto(`${TARGET_URL}/contact`);
await page.fill('input[name="name"]', 'John Doe');
await page.fill('input[name="email"]', 'john@example.com');
await page.fill('textarea[name="message"]', 'Message de test');
await page.click('button[type="submit"]');
// Vérifier la soumission
await page.waitForSelector('.success-message');
console.log('✅ Formulaire soumis avec succès');
await browser.close();
})();
Vérifier les liens cassés
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto('http://localhost:3000');
const links = await page.locator('a[href^="http"]').all();
const results = { working: 0, broken: [] };
for (const link of links) {
const href = await link.getAttribute('href');
try {
const response = await page.request.head(href);
if (response.ok()) {
results.working++;
} else {
results.broken.push({ url: href, status: response.status() });
}
} catch (e) {
results.broken.push({ url: href, error: e.message });
}
}
console.log(`✅ Liens fonctionnels : ${results.working}`);
console.log(`❌ Liens cassés :`, results.broken);
await browser.close();
})();
Prendre une capture d'écran avec gestion d'erreurs
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
try {
await page.goto('http://localhost:3000', {
waitUntil: 'networkidle',
timeout: 10000,
});
await page.screenshot({
path: '/tmp/screenshot.png',
fullPage: true,
});
console.log('📸 Capture d\'écran enregistrée dans /tmp/screenshot.png');
} catch (error) {
console.error('❌ Erreur :', error.message);
} finally {
await browser.close();
}
})();
Tester le responsive design
// /tmp/playwright-test-responsive-full.js
const { chromium } = require('playwright');
const TARGET_URL = 'http://localhost:3001'; // Auto-détectée
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
const viewports = [
{ name: 'Desktop', width: 1920, height: 1080 },
{ name: 'Tablet', width: 768, height: 1024 },
{ name: 'Mobile', width: 375, height: 667 },
];
for (const viewport of viewports) {
console.log(
`Test ${viewport.name} (${viewport.width}x${viewport.height})`,
);
await page.setViewportSize({
width: viewport.width,
height: viewport.height,
});
await page.goto(TARGET_URL);
await page.waitForTimeout(1000);
await page.screenshot({
path: `/tmp/${viewport.name.toLowerCase()}.png`,
fullPage: true,
});
}
console.log('✅ Tous les viewports testés');
await browser.close();
})();
Exécution en ligne (Tâches simples)
Pour les tâches ponctuelles rapides, vous pouvez exécuter du code en ligne sans créer de fichiers :
# Prendre une capture d'écran rapide
cd $SKILL_DIR && node run.js "
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto('http://localhost:3001');
await page.screenshot({ path: '/tmp/quick-screenshot.png', fullPage: true });
console.log('Capture d\'écran enregistrée');
await browser.close();
"
Quand utiliser en ligne vs fichiers :
- En ligne : Tâches ponctuelles rapides (capture d'écran, vérifier si un élément existe, obtenir le titre de la page)
- Fichiers : Tests complexes, vérifications de responsive design, n'importe quoi que l'utilisateur pourrait vouloir réexécuter
Fonctions d'aide disponibles
Fonctions utilitaires optionnelles dans lib/helpers.js :
const helpers = require('./lib/helpers');
// Détecter les serveurs de développement en cours d'exécution (CRITIQUE - utilisez ceci d'abord !)
const servers = await helpers.detectDevServers();
console.log('Serveurs trouvés:', servers);
// Clic sécurisé avec retry
await helpers.safeClick(page, 'button.submit', { retries: 3 });
// Saisie sécurisée avec effacement
await helpers.safeType(page, '#username', 'testuser');
// Prendre une capture d'écran avec horodatage
await helpers.takeScreenshot(page, 'test-result');
// Gérer les bannières de cookies
await helpers.handleCookieBanner(page);
// Extraire les données du tableau
const data = await helpers.extractTableData(page, 'table.results');
Consultez lib/helpers.js pour la liste complète.
En-têtes HTTP personnalisés
Configurer les en-têtes personnalisés pour toutes les requêtes HTTP via variables d'environnement. Utile pour :
- Identifier le trafic automatisé vers votre backend
- Obtenir des réponses optimisées pour LLM (par exemple, erreurs en texte brut au lieu de HTML stylisé)
- Ajouter globalement les tokens d'authentification
Configuration
En-tête unique (cas courant) :
PW_HEADER_NAME=X-Automated-By PW_HEADER_VALUE=playwright-skill \
cd $SKILL_DIR && node run.js /tmp/my-script.js
Plusieurs en-têtes (format JSON) :
PW_EXTRA_HEADERS='{"X-Automated-By":"playwright-skill","X-Debug":"true"}' \
cd $SKILL_DIR && node run.js /tmp/my-script.js
Comment ça marche
Les en-têtes sont automatiquement appliqués lors de l'utilisation de helpers.createContext() :
const context = await helpers.createContext(browser);
const page = await context.newPage();
// Toutes les requêtes de cette page incluent vos en-têtes personnalisés
Pour les scripts utilisant l'API Playwright brute, utilisez getContextOptionsWithHeaders() injecté :
const context = await browser.newContext(
getContextOptionsWithHeaders({ viewport: { width: 1920, height: 1080 } }),
);
Utilisation avancée
Pour la documentation complète de l'API Playwright, consultez API_REFERENCE.md :
- Meilleures pratiques pour les sélecteurs et locators
- Interception réseau et mock d'API
- Gestion de l'authentification et des sessions
- Tests de régression visuelle
- Émulation d'appareils mobiles
- Tests de performance
- Techniques de débogage
- Intégration CI/CD
Conseils
- CRITIQUE : Détecter les serveurs D'ABORD - Exécutez toujours
detectDevServers()avant d'écrire le code de test pour les tests sur localhost - En-têtes personnalisés - Utilisez les variables d'environnement
PW_HEADER_NAME/PW_HEADER_VALUEpour identifier le trafic automatisé vers votre backend - Utiliser /tmp pour les fichiers de test - Écrire dans
/tmp/playwright-test-*.js, jamais dans le répertoire de compétence ou le projet de l'utilisateur - Paramétrer les URLs - Mettez l'URL détectée/fournie dans une constante
TARGET_URLen haut de chaque script - PAR DÉFAUT : Navigateur visible - Utilisez toujours
headless: falsesauf si l'utilisateur demande explicitement le mode headless - Mode headless - Utilisez
headless: trueuniquement quand l'utilisateur demande spécifiquement l'exécution en "headless" ou en "arrière-plan" - Ralentir : Utilisez
slowMo: 100pour rendre les actions visibles et plus faciles à suivre - Stratégies d'attente : Utilisez
waitForURL,waitForSelector,waitForLoadStateau lieu de timeouts fixes - Gestion d'erreurs : Utilisez toujours try-catch pour une automatisation robuste
- Sortie console : Utilisez
console.log()pour suivre la progression et montrer ce qui se passe
Dépannage
Playwright non installé :
cd $SKILL_DIR && npm run setup
Module non trouvé :
Assurez-vous d'exécuter depuis le répertoire de compétence via le wrapper run.js
Le navigateur ne s'ouvre pas :
Vérifiez headless: false et assurez-vous qu'un affichage est disponible
Élément non trouvé :
Ajoutez une attente : await page.waitForSelector('.element', { timeout: 10000 })
Exemple d'utilisation
Utilisateur : « Teste si la page marketing a une bonne apparence »
Claude : Je vais tester la page marketing sur plusieurs viewports. Laissez-moi d'abord détecter les serveurs en cours d'exécution...
[Exécute : detectDevServers()]
[Sortie : Serveur trouvé sur le port 3001]
J'ai trouvé votre serveur de développement en cours d'exécution sur http://localhost:3001
[Écrit un script d'automatisation personnalisé vers /tmp/playwright-test-marketing.js avec URL paramétrée]
[Exécute : cd $SKILL_DIR && node run.js /tmp/playwright-test-marketing.js]
[Affiche les résultats avec captures d'écran depuis /tmp/]
Utilisateur : « Vérifier si la connexion redirige correctement »
Claude : Je vais tester le flux de connexion. D'abord, laissez-moi vérifier les serveurs en cours d'exécution...
[Exécute : detectDevServers()]
[Sortie : Serveurs trouvés sur les ports 3000 et 3001]
J'ai trouvé 2 serveurs de développement. Lequel dois-je tester ?
- http://localhost:3000
- http://localhost:3001
Utilisateur : « Utilise 3001 »
[Écrit l'automatisation de connexion vers /tmp/playwright-test-login.js]
[Exécute : cd $SKILL_DIR && node run.js /tmp/playwright-test-login.js]
[Rapporte : ✅ Connexion réussie, redirection vers /dashboard]
Notes
- Chaque automatisation est écrite sur mesure pour votre demande spécifique
- Non limité aux scripts pré-construits - toute tâche de navigateur est possible
- Détecte automatiquement les serveurs de développement en cours d'exécution pour éliminer les URLs en dur
- Scripts de test écrits dans
/tmppour nettoyage automatique (pas de désordre) - Le code s'exécute de manière fiable avec résolution de module appropriée via
run.js - Révélation progressive - API_REFERENCE.md chargé uniquement quand des fonctionnalités avancées sont nécessaires