
Generate
Emit Playwright TypeScript tests for login flows and CRUD screens so you can ship UI changes with repeatable browser checks.
Overview
Generate is an agent skill for the Ship phase that provides Playwright TypeScript templates for authentication and CRUD end-to-end tests.
Install
npx skills add https://github.com/alirezarezvani/claude-skills --skill generateWhat is this skill?
- Playwright test.describe blocks with TypeScript examples
- Authentication pattern: valid login, invalid credentials, URL and heading assertions
- CRUD pattern: create item, edit row, save and visibility checks
- Uses accessible selectors: getByLabel, getByRole, getByText
- 2 documented pattern groups: Authentication and CRUD Operations
Adoption & trust: 1.6k installs on skills.sh; 17.5k GitHub stars; 2/3 security scanners passed (skills.sh audits).
What problem does it solve?
You are shipping UI features but keep rewriting the same Playwright login and CRUD test scaffolding by hand.
Who is it for?
Solo builders on TypeScript web apps who use Playwright and want consistent E2E patterns from the agent during test suite expansion.
Skip if: Projects on non-browser test stacks only (pure unit tests, mobile native harnesses) with no Playwright setup.
When should I use this skill?
When you need Playwright TypeScript test examples for authentication flows or CRUD UI operations during test authoring.
What do I get? / Deliverables
You get ready-to-adapt test.describe blocks with role-based selectors and assertion patterns for auth success, auth errors, create, and edit flows.
- TypeScript test.describe blocks for auth
- TypeScript test.describe blocks for CRUD flows
Recommended Skills
Journey fit
Canonical shelf is Ship because the skill outputs executable test code meant to run before or during release, not during initial product discovery. Testing is the right subphase: patterns are auth and item CRUD specs with assertions on URLs, headings, and alerts.
How it compares
Pattern library for browser E2E snippets, not a full test runner or CI orchestration skill.
Common Questions / FAQ
Who is generate for?
Developers shipping SaaS or web UIs who run Playwright and want agent-generated TypeScript tests for auth and CRUD instead of blank files.
When should I use generate?
In Ship/testing when you add or harden login, dashboard redirects, validation alerts, or item create/edit flows before release.
Is generate safe to install?
Check this page’s Security Audits panel for license and file integrity; the skill is documentation patterns only and does not execute tests by itself.
SKILL.md
READMESKILL.md - Generate
# Test Generation Patterns ## Pattern: Authentication Flow ```typescript test.describe('Authentication', () => { test('should login with valid credentials', async ({ page }) => { await page.goto('/login'); await page.getByLabel('Email').fill('user@example.com'); await page.getByLabel('Password').fill('password123'); await page.getByRole('button', { name: 'Sign in' }).click(); await expect(page).toHaveURL('/dashboard'); await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible(); }); test('should show error for invalid credentials', async ({ page }) => { await page.goto('/login'); await page.getByLabel('Email').fill('wrong@example.com'); await page.getByLabel('Password').fill('wrong'); await page.getByRole('button', { name: 'Sign in' }).click(); await expect(page.getByRole('alert')).toHaveText(/invalid/i); await expect(page).toHaveURL('/login'); }); }); ``` ## Pattern: CRUD Operations ```typescript test.describe('Items', () => { test('should create a new item', async ({ page }) => { await page.goto('/items'); await page.getByRole('button', { name: 'Add item' }).click(); await page.getByLabel('Name').fill('Test Item'); await page.getByRole('button', { name: 'Save' }).click(); await expect(page.getByText('Test Item')).toBeVisible(); }); test('should edit an existing item', async ({ page }) => { await page.goto('/items'); await page.getByRole('row', { name: /Test Item/ }) .getByRole('button', { name: 'Edit' }).click(); await page.getByLabel('Name').clear(); await page.getByLabel('Name').fill('Updated Item'); await page.getByRole('button', { name: 'Save' }).click(); await expect(page.getByText('Updated Item')).toBeVisible(); }); test('should delete an item with confirmation', async ({ page }) => { await page.goto('/items'); await page.getByRole('row', { name: /Test Item/ }) .getByRole('button', { name: 'Delete' }).click(); await page.getByRole('button', { name: 'Confirm' }).click(); await expect(page.getByText('Test Item')).not.toBeVisible(); }); }); ``` ## Pattern: Form with Validation ```typescript test.describe('Contact Form', () => { test.beforeEach(async ({ page }) => { await page.goto('/contact'); }); test('should submit valid form', async ({ page }) => { await page.getByLabel('Name').fill('Jane Doe'); await page.getByLabel('Email').fill('jane@example.com'); await page.getByLabel('Message').fill('Hello, this is a test message.'); await page.getByRole('button', { name: 'Send' }).click(); await expect(page.getByText('Message sent')).toBeVisible(); }); test('should show validation errors for empty required fields', async ({ page }) => { await page.getByRole('button', { name: 'Send' }).click(); await expect(page.getByText('Name is required')).toBeVisible(); await expect(page.getByText('Email is required')).toBeVisible(); }); test('should validate email format', async ({ page }) => { await page.getByLabel('Email').fill('not-an-email'); await page.getByRole('button', { name: 'Send' }).click(); await expect(page.getByText('Invalid email')).toBeVisible(); }); }); ``` ## Pattern: Search and Filter ```typescript test.describe('Product Search', () => { test('should return results for valid query', async ({ page }) => { await page.goto('/products'); await page.getByPlaceholder('Search products').fill('laptop'); await page.getByRole('button', { name: 'Search' }).click(); await expect(page.getByRole('list')).toBeVisible(); const results = page.getByRole('listitem'); await expect(results).not.toHaveCount(0); }); test('should show empty state for no results', async ({ page }) => { await page.goto('/products'); await page.getByPlaceholder('Search products').fill('xyznonexistent'); await page.getByRole('button', { name: 'Search' }).click(); await expect(page.getByTex