Receber por email
← Voltar para o catálogo

playwright-automation

Browser automation and testing with Playwright. Use when testing web applications, automating browser tasks, taking screenshots, or validating UI behavior.

216estrelas
Atualizado há 4 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add majiayu000/claude-arsenal

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/playwright-automation-majiayu000/svg)](https://www.skillteca.com.br/skills/playwright-automation-majiayu000)

Skills relacionadas

Ver todas de Automação →

Alerta por categoria

Receba novas skills de Automação toda segunda

1 email curto, só com as skills novas de Automação. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Playwright Browser Automation

Inspired by lackeyjb/playwright-skill and anthropics/skills

Purpose

Automate browser interactions for testing, scraping, and validation using Playwright.

Core Workflow

1. Server Detection (for localhost testing)

// Check if dev server is running
const http = require('http');

function checkServer(port) {
  return new Promise((resolve) => {
    const req = http.get(`http://localhost:${port}`, (res) => {
      resolve(true);
    });
    req.on('error', () => resolve(false));
    req.setTimeout(1000, () => {
      req.destroy();
      resolve(false);
    });
  });
}

2. Script Creation

Write test scripts to /tmp/playwright-test-*.js:

const { chromium } = require('playwright');

(async () => {
  // Configuration
  const URL = 'http://localhost:3000';

  // Launch browser (visible by default)
  const browser = await chromium.launch({ headless: false });
  const context = await browser.newContext();
  const page = await context.newPage();

  try {
    // Navigate and wait for load
    await page.goto(URL);
    await page.waitForLoadState('networkidle');

    // Your automation here

  } catch (error) {
    console.error('Error:', error.message);
    await page.screenshot({ path: '/tmp/error-screenshot.png' });
  } finally {
    await browser.close();
  }
})();

3. Execution

# Run the script
node /tmp/playwright-test-*.js

# Or with npx
npx playwright test

Common Patterns

Screenshot Capture

// Full page screenshot
await page.screenshot({
  path: '/tmp/screenshot.png',
  fullPage: true
});

// Element screenshot
const element = await page.locator('.hero-section');
await element.screenshot({ path: '/tmp/hero.png' });

// With timestamp
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
await page.screenshot({ path: `/tmp/screenshot-${timestamp}.png` });

Form Automation

// Fill form fields
await page.fill('input[name="email"]', 'test@example.com');
await page.fill('input[name="password"]', 'secretpassword');

// Click submit
await page.click('button[type="submit"]');

// Wait for navigation
await page.waitForURL('**/dashboard');

Login Flow

async function login(page, email, password) {
  await page.goto('/login');
  await page.waitForLoadState('networkidle');

  await page.fill('#email', email);
  await page.fill('#password', password);
  await page.click('button:has-text("Sign In")');

  // Wait for redirect
  await page.waitForURL('**/dashboard', { timeout: 10000 });

  return page.url().includes('/dashboard');
}

Responsive Testing

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) {
  await page.setViewportSize({
    width: viewport.width,
    height: viewport.height
  });
  await page.screenshot({
    path: `/tmp/screenshot-${viewport.name}.png`
  });
}

Link Checking

async function checkLinks(page) {
  const links = await page.locator('a[href]').all();
  const results = [];

  for (const link of links) {
    const href = await link.getAttribute('href');
    if (href.startsWith('http')) {
      try {
        const response = await page.request.head(href);
        results.push({
          url: href,
          status: response.status(),
          ok: response.ok()
        });
      } catch (e) {
        results.push({ url: href, status: 'error', ok: false });
      }
    }
  }

  return results;
}

Table Data Extraction

async function extractTable(page, selector) {
  const rows = await page.locator(`${selector} tr`).all();
  const data = [];

  for (const row of rows) {
    const cells = await row.locator('td, th').allTextContents();
    data.push(cells);
  }

  return data;
}

Console Log Capture

// Listen to console messages
page.on('console', msg => {
  console.log(`[${msg.type()}] ${msg.text()}`);
});

// Listen to errors
page.on('pageerror', error => {
  console.error('Page error:', error.message);
});

Selectors Best Practices

// Prefer: Text content
await page.click('button:has-text("Submit")');

// Prefer: ARIA roles
await page.click('role=button[name="Submit"]');

// Prefer: Test IDs
await page.click('[data-testid="submit-button"]');

// Avoid: Complex CSS paths
// ❌ await page.click('div.container > form > div:nth-child(3) > button');

Wait Strategies

// Wait for network idle (recommended for SPAs)
await page.waitForLoadState('networkidle');

// Wait for specific element
await page.waitForSelector('.dashboard-loaded');

// Wait for response
await page.waitForResponse('**/api/data');

// Custom wait
await page.waitForFunction(() => {
  return document.querySelector('.loading') === null;
});

// Avoid: Fixed timeouts
// ❌ await page.waitForTimeout(5000);

Error Handling

try {
  await page.goto(URL, { timeout: 30000 });
  await page.waitForLoadState('networkidle');

  // Automation steps...

} catch (error) {
  console.error('Test failed:', error.message);

  // Capture failure state
  await page.screenshot({
    path: `/tmp/failure-${Date.now()}.png`,
    fullPage: true
  });

  // Capture HTML for debugging
  const html = await page.content();
  require('fs').writeFileSync('/tmp/failure-page.html', html);

} finally {
  await browser.close();
}

Multi-Server Setup

# Start multiple servers, then run test
python scripts/with_server.py \
  --server "npm run dev" --port 3000 \
  --server "npm run api" --port 5000 \
  -- node /tmp/playwright-test.js

Quick Reference

// Navigation
await page.goto(url);
await page.goBack();
await page.reload();

// Interactions
await page.click(selector);
await page.fill(selector, text);
await page.type(selector, text);  // With keystrokes
await page.press(selector, 'Enter');
await page.hover(selector);
await page.selectOption(selector, value);
await page.check(selector);  // Checkbox

// Assertions
await expect(page).toHaveTitle(/Dashboard/);
await expect(page.locator('.msg')).toHaveText('Success');
await expect(page.locator('button')).toBeEnabled();

// Information
const text = await page.textContent(selector);
const value = await page.inputValue(selector);
const visible = await page.isVisible(selector);
Compartilhar X LinkedIn