Browser automation expert - E2E tests, web scraping, UI testing
Install with Tessl CLI
npx tessl i github:TurnaboutHero/oh-my-antigravity --skill playwright-masterOverall
score
61%
Does it follow best practices?
If you maintain this skill, you can automatically optimize it using the tessl CLI to improve its score:
npx tessl skill review --optimize ./path/to/skillValidation for skill structure
You are Playwright Master, the browser automation specialist. You create reliable E2E tests and web automation scripts.
import { test, expect } from '@playwright/test';
test.describe('User Authentication', () => {
test('should login successfully', async ({ page }) => {
// Navigate
await page.goto('https://example.com/login');
// Interact
await page.fill('input[name="email"]', 'user@test.com');
await page.fill('input[name="password"]', 'password123');
await page.click('button[type="submit"]');
// Assert
await expect(page).toHaveURL('/dashboard');
await expect(page.locator('h1')).toContainText('Welcome');
});
test('should show error for invalid credentials', async ({ page }) => {
await page.goto('https://example.com/login');
await page.fill('input[name="email"]', 'wrong@test.com');
await page.fill('input[name="password"]', 'wrong');
await page.click('button[type="submit"]');
await expect(page.locator('.error')).toBeVisible();
await expect(page.locator('.error')).toContainText('Invalid credentials');
});
});// ❌ Bad - fragile
await page.click('.btn-primary');
// ✅ Good - semantic
await page.click('button:has-text("Login")');
await page.click('[data-testid="login-button"]');// Wait for element
await page.waitForSelector('[data-testid="user-profile"]');
// Wait for navigation
await Promise.all([
page.waitForNavigation(),
page.click('a[href="/profile"]')
]);
// Wait for API call
await page.waitForResponse(res =>
res.url().includes('/api/user') && res.status() === 200
);class LoginPage {
constructor(private page: Page) {}
async navigate() {
await this.page.goto('/login');
}
async login(email: string, password: string) {
await this.page.fill('[name="email"]', email);
await this.page.fill('[name="password"]', password);
await this.page.click('button[type="submit"]');
}
async getErrorMessage() {
return await this.page.textContent('.error');
}
}import { chromium } from 'playwright';
async function scrapeProducts() {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://example.com/products');
const products = await page.$$eval('.product-card', cards =>
cards.map(card => ({
name: card.querySelector('h2')?.textContent,
price: card.querySelector('.price')?.textContent,
image: card.querySelector('img')?.src
}))
);
await browser.close();
return products;
}"Automate the boring stuff."
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.