Complete Claude Code plugin with: - 9 skills (/pw:init, generate, review, fix, migrate, coverage, testrail, browserstack, report) - 3 specialized agents (test-architect, test-debugger, migration-planner) - 55 test case templates across 11 categories (auth, CRUD, checkout, search, forms, dashboard, settings, onboarding, notifications, API, accessibility) - TestRail MCP server (TypeScript) — 8 tools for bidirectional sync - BrowserStack MCP server (TypeScript) — 7 tools for cross-browser testing - Smart hooks (auto-validate tests, auto-detect Playwright projects) - 6 curated reference docs (golden rules, locators, assertions, fixtures, pitfalls, flaky tests) - Leverages Claude Code built-ins (/batch, /debug, Explore subagent) - Zero-config for core features; TestRail/BrowserStack via env vars - Both TypeScript and JavaScript support throughout Co-authored-by: Leo <leo@openclaw.ai>
5.7 KiB
5.7 KiB
Registration Template
Tests signup form submission, validation, and post-registration flow.
Prerequisites
- Unique test email for each run:
{{newUserEmail}} - App running at
{{baseUrl}}
TypeScript
import { test, expect } from '@playwright/test';
const uniqueEmail = `test+${Date.now()}@example.com`;
test.describe('Registration', () => {
test.beforeEach(async ({ page }) => {
await page.goto('{{baseUrl}}/register');
});
// Happy path: successful registration
test('registers new user with valid data', async ({ page }) => {
await page.getByRole('textbox', { name: /first name/i }).fill('{{firstName}}');
await page.getByRole('textbox', { name: /last name/i }).fill('{{lastName}}');
await page.getByRole('textbox', { name: /email/i }).fill(uniqueEmail);
await page.getByRole('textbox', { name: /^password$/i }).fill('{{newPassword}}');
await page.getByRole('textbox', { name: /confirm.*password/i }).fill('{{newPassword}}');
await page.getByRole('checkbox', { name: /terms/i }).check();
await page.getByRole('button', { name: /sign up|register|create account/i }).click();
await expect(page).toHaveURL(/\/verify-email|\/dashboard|\/onboarding/);
});
// Happy path: success message or redirect
test('shows confirmation after registration', async ({ page }) => {
await page.getByRole('textbox', { name: /email/i }).fill(uniqueEmail);
await page.getByRole('textbox', { name: /^password$/i }).fill('{{newPassword}}');
await page.getByRole('checkbox', { name: /terms/i }).check();
await page.getByRole('button', { name: /sign up|register/i }).click();
await expect(page.getByText(/check your email|account created|welcome/i)).toBeVisible();
});
// Error case: email already registered
test('shows error for already registered email', async ({ page }) => {
await page.getByRole('textbox', { name: /email/i }).fill('{{existingUserEmail}}');
await page.getByRole('textbox', { name: /^password$/i }).fill('{{newPassword}}');
await page.getByRole('checkbox', { name: /terms/i }).check();
await page.getByRole('button', { name: /sign up|register/i }).click();
await expect(page.getByRole('alert')).toContainText(/already.*registered|email.*taken/i);
});
// Error case: terms not accepted
test('blocks registration if terms not accepted', async ({ page }) => {
await page.getByRole('textbox', { name: /email/i }).fill(uniqueEmail);
await page.getByRole('textbox', { name: /^password$/i }).fill('{{newPassword}}');
await page.getByRole('button', { name: /sign up|register/i }).click();
await expect(page.getByText(/accept.*terms|terms.*required/i)).toBeVisible();
});
// Error case: weak password
test('shows error for weak password', async ({ page }) => {
await page.getByRole('textbox', { name: /^password$/i }).fill('123');
await page.getByRole('textbox', { name: /^password$/i }).blur();
await expect(page.getByText(/at least \d+ characters|too weak/i)).toBeVisible();
});
// Error case: passwords mismatch
test('shows error when passwords do not match', async ({ page }) => {
await page.getByRole('textbox', { name: /^password$/i }).fill('{{newPassword}}');
await page.getByRole('textbox', { name: /confirm.*password/i }).fill('different');
await page.getByRole('textbox', { name: /confirm.*password/i }).blur();
await expect(page.getByText(/do not match/i)).toBeVisible();
});
// Edge case: already logged-in user redirected
test('redirects to dashboard when already authenticated', async ({ page, context }) => {
await context.addCookies([{ name: '{{sessionCookieName}}', value: '{{validSession}}', domain: '{{cookieDomain}}', path: '/' }]);
await page.goto('{{baseUrl}}/register');
await expect(page).toHaveURL('{{baseUrl}}/dashboard');
});
});
JavaScript
const { test, expect } = require('@playwright/test');
test.describe('Registration', () => {
test('registers with valid data', async ({ page }) => {
const email = `test+${Date.now()}@example.com`;
await page.goto('{{baseUrl}}/register');
await page.getByRole('textbox', { name: /email/i }).fill(email);
await page.getByRole('textbox', { name: /^password$/i }).fill('{{newPassword}}');
await page.getByRole('checkbox', { name: /terms/i }).check();
await page.getByRole('button', { name: /sign up|register/i }).click();
await expect(page).toHaveURL(/\/verify-email|\/dashboard|\/onboarding/);
});
test('shows error for existing email', async ({ page }) => {
await page.goto('{{baseUrl}}/register');
await page.getByRole('textbox', { name: /email/i }).fill('{{existingUserEmail}}');
await page.getByRole('textbox', { name: /^password$/i }).fill('{{newPassword}}');
await page.getByRole('checkbox', { name: /terms/i }).check();
await page.getByRole('button', { name: /sign up|register/i }).click();
await expect(page.getByRole('alert')).toContainText(/already.*registered/i);
});
test('requires terms acceptance', async ({ page }) => {
await page.goto('{{baseUrl}}/register');
await page.getByRole('textbox', { name: /email/i }).fill(`t${Date.now()}@example.com`);
await page.getByRole('textbox', { name: /^password$/i }).fill('{{newPassword}}');
await page.getByRole('button', { name: /sign up|register/i }).click();
await expect(page.getByText(/accept.*terms/i)).toBeVisible();
});
});
Variants
| Variant | Description |
|---|---|
| Valid registration | All fields → redirect or success message |
| Confirmation | Email check or welcome shown |
| Existing email | Error alert |
| Terms not accepted | Validation error |
| Weak password | Strength error on blur |
| Password mismatch | Confirm error |
| Already authed | Redirected to dashboard |