| name | chrome |
| description | Browser automation using Puppeteer or Playwright. Use for web testing, screenshots, form filling, and automated browser interactions. |
Chrome Automation
Automate browser interactions using Puppeteer or Playwright.
Prerequisites
# Puppeteer
npm install puppeteer
# Or Playwright
npm install playwright
npx playwright install chromium
Puppeteer Quick Start
Basic Script
// script.js
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({ path: 'screenshot.png' });
await browser.close();
})();
Run: node script.js
With Visible Browser
const browser = await puppeteer.launch({
headless: false,
slowMo: 50, // Slow down operations
});
Playwright Quick Start
Basic Script
// script.js
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({ path: 'screenshot.png' });
await browser.close();
})();
Common Operations
Navigation
// Go to URL
await page.goto('https://example.com');
// Wait for navigation
await page.goto('https://example.com', { waitUntil: 'networkidle0' });
// Go back/forward
await page.goBack();
await page.goForward();
// Reload
await page.reload();
Screenshots
// Full page
await page.screenshot({ path: 'full.png', fullPage: true });
// Specific element
const element = await page.$('#header');
await element.screenshot({ path: 'header.png' });
// With options
await page.screenshot({
path: 'screenshot.png',
type: 'png',
quality: 90, // For jpeg
clip: { x: 0, y: 0, width: 800, height: 600 }
});
Click Actions
// Click element
await page.click('#button');
await page.click('button.submit');
// Double click
await page.dblclick('#item');
// Right click
await page.click('#element', { button: 'right' });
// Click and wait for navigation
await Promise.all([
page.waitForNavigation(),
page.click('a.link')
]);
Form Filling
// Type text
await page.type('#email', 'user@example.com');
// Clear and type
await page.fill('#email', 'user@example.com'); // Playwright
await page.$eval('#email', el => el.value = ''); // Puppeteer clear
await page.type('#email', 'user@example.com');
// Select dropdown
await page.select('#country', 'US');
// Checkbox
await page.check('#agree'); // Playwright
await page.click('#agree'); // Puppeteer
// File upload
await page.setInputFiles('#file', '/path/to/file.pdf'); // Playwright
const input = await page.$('#file');
await input.uploadFile('/path/to/file.pdf'); // Puppeteer
Waiting
// Wait for selector
await page.waitForSelector('#loaded');
// Wait for text
await page.waitForFunction(() =>
document.body.textContent.includes('Success')
);
// Wait for navigation
await page.waitForNavigation();
// Wait for network idle
await page.waitForLoadState('networkidle'); // Playwright
// Explicit wait
await page.waitForTimeout(1000); // Not recommended for production
Extract Data
// Get text content
const text = await page.textContent('#element');
const text = await page.$eval('#element', el => el.textContent);
// Get attribute
const href = await page.getAttribute('a', 'href');
const href = await page.$eval('a', el => el.href);
// Get multiple elements
const items = await page.$$eval('.item', els =>
els.map(el => el.textContent)
);
// Get page content
const html = await page.content();
Evaluate JavaScript
// Run in browser context
const result = await page.evaluate(() => {
return document.title;
});
// With arguments
const text = await page.evaluate((selector) => {
return document.querySelector(selector).textContent;
}, '#element');
Testing Patterns
Login Flow
async function login(page, username, password) {
await page.goto('https://app.example.com/login');
await page.fill('#username', username);
await page.fill('#password', password);
await page.click('button[type="submit"]');
await page.waitForSelector('#dashboard');
}
Form Submission Test
async function testForm(page) {
await page.goto('https://example.com/form');
// Fill form
await page.fill('#name', 'Test User');
await page.fill('#email', 'test@example.com');
await page.select('#country', 'US');
await page.check('#agree');
// Submit
await page.click('button[type="submit"]');
// Verify success
await page.waitForSelector('.success-message');
const message = await page.textContent('.success-message');
console.assert(message.includes('Thank you'));
}
Visual Regression
// Take baseline
await page.screenshot({ path: 'baseline.png', fullPage: true });
// Later, compare
await page.screenshot({ path: 'current.png', fullPage: true });
// Use image comparison tool
Device Emulation
// Puppeteer
const iPhone = puppeteer.devices['iPhone 12'];
await page.emulate(iPhone);
// Playwright
const iPhone = playwright.devices['iPhone 12'];
const context = await browser.newContext({ ...iPhone });
// Manual viewport
await page.setViewportSize({ width: 375, height: 812 });
Network
// Intercept requests (Playwright)
await page.route('**/api/*', route => {
route.fulfill({ status: 200, body: JSON.stringify({ mocked: true }) });
});
// Block resources
await page.route('**/*.{png,jpg,jpeg}', route => route.abort());
// Monitor requests
page.on('request', req => console.log(req.url()));
page.on('response', res => console.log(res.status(), res.url()));
Best Practices
- Use explicit waits - Not timeouts
- Handle errors - try/catch important
- Close browsers - Always clean up
- Use headless for CI - Faster, no display needed
- Test selectors - Prefer data-testid
- Screenshot on failure - Debug easier
- Reuse contexts - Faster than new browsers