Files
claude-skills-reference/engineering-team/playwright-pro/templates/notifications/toast-messages.md
Alireza Rezvani d33d03da50 feat: add playwright-pro plugin — production-grade Playwright testing toolkit (#254)
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>
2026-03-05 13:50:05 +01:00

140 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Toast Messages Template
Tests success, error, and warning toasts with auto-dismiss and manual close.
## Prerequisites
- Authenticated session via `{{authStorageStatePath}}`
- App running at `{{baseUrl}}`
---
## TypeScript
```typescript
import { test, expect } from '@playwright/test';
test.describe('Toast Messages', () => {
test.use({ storageState: '{{authStorageStatePath}}' });
// Happy path: success toast on action
test('shows success toast after save action', async ({ page }) => {
await page.goto('{{baseUrl}}/{{formPath}}');
await page.getByRole('textbox', { name: /{{fieldLabel}}/i }).fill('{{validValue}}');
await page.getByRole('button', { name: /save/i }).click();
const toast = page.getByRole('alert').filter({ hasText: /saved|success/i });
await expect(toast).toBeVisible();
});
// Happy path: error toast on failure
test('shows error toast when action fails', async ({ page }) => {
await page.route('{{baseUrl}}/api/{{endpoint}}*', route =>
route.fulfill({ status: 500, body: '{}' })
);
await page.goto('{{baseUrl}}/{{formPath}}');
await page.getByRole('button', { name: /save/i }).click();
const toast = page.getByRole('alert').filter({ hasText: /error|failed/i });
await expect(toast).toBeVisible();
});
// Happy path: warning toast shown
test('shows warning toast', async ({ page }) => {
await page.goto('{{baseUrl}}/{{warningTriggerPath}}');
await page.getByRole('button', { name: /{{warningAction}}/i }).click();
const toast = page.getByRole('alert').filter({ hasText: /warning|attention/i });
await expect(toast).toBeVisible();
});
// Happy path: toast auto-dismisses
test('toast auto-dismisses after timeout', async ({ page }) => {
await page.goto('{{baseUrl}}/{{formPath}}');
await page.clock.install();
await page.getByRole('textbox', { name: /{{fieldLabel}}/i }).fill('{{validValue}}');
await page.getByRole('button', { name: /save/i }).click();
const toast = page.getByRole('alert').filter({ hasText: /saved/i });
await expect(toast).toBeVisible();
await page.clock.fastForward({{toastDurationMs}});
await expect(toast).toBeHidden();
});
// Happy path: toast manually dismissed
test('dismisses toast via close button', async ({ page }) => {
await page.goto('{{baseUrl}}/{{formPath}}');
await page.getByRole('button', { name: /save/i }).click();
const toast = page.getByRole('alert').filter({ hasText: /saved/i });
await expect(toast).toBeVisible();
await toast.getByRole('button', { name: /close|dismiss|×/i }).click();
await expect(toast).toBeHidden();
});
// Happy path: multiple toasts stack
test('stacks multiple toasts', async ({ page }) => {
await page.goto('{{baseUrl}}/{{formPath}}');
// Trigger two saves quickly
await page.getByRole('button', { name: /save/i }).click();
await page.getByRole('button', { name: /save/i }).click();
const toasts = page.getByRole('alert');
const count = await toasts.count();
expect(count).toBeGreaterThanOrEqual(2);
});
// Edge case: toast announces to screen readers
test('toast has live region role for accessibility', async ({ page }) => {
await page.goto('{{baseUrl}}/{{formPath}}');
await page.getByRole('button', { name: /save/i }).click();
const toast = page.getByRole('alert').first();
await expect(toast).toBeVisible();
// role="alert" implies aria-live="assertive"
const role = await toast.getAttribute('role');
expect(role).toMatch(/alert|status/);
});
});
```
---
## JavaScript
```javascript
const { test, expect } = require('@playwright/test');
test.describe('Toast Messages', () => {
test.use({ storageState: '{{authStorageStatePath}}' });
test('shows success toast after save', async ({ page }) => {
await page.goto('{{baseUrl}}/{{formPath}}');
await page.getByRole('textbox', { name: /{{fieldLabel}}/i }).fill('{{validValue}}');
await page.getByRole('button', { name: /save/i }).click();
await expect(page.getByRole('alert').filter({ hasText: /saved|success/i })).toBeVisible();
});
test('toast auto-dismisses after timeout', async ({ page }) => {
await page.goto('{{baseUrl}}/{{formPath}}');
await page.clock.install();
await page.getByRole('button', { name: /save/i }).click();
const toast = page.getByRole('alert').filter({ hasText: /saved/i });
await expect(toast).toBeVisible();
await page.clock.fastForward({{toastDurationMs}});
await expect(toast).toBeHidden();
});
test('dismisses toast via close button', async ({ page }) => {
await page.goto('{{baseUrl}}/{{formPath}}');
await page.getByRole('button', { name: /save/i }).click();
const toast = page.getByRole('alert').filter({ hasText: /saved/i });
await toast.getByRole('button', { name: /close|×/i }).click();
await expect(toast).toBeHidden();
});
});
```
## Variants
| Variant | Description |
|---------|-------------|
| Success toast | Save → green/success alert visible |
| Error toast | 500 → red/error alert visible |
| Warning toast | Trigger action → warning alert |
| Auto-dismiss | Toast hidden after N ms (clock-controlled) |
| Manual dismiss | Close button hides toast |
| Stacked toasts | Multiple alerts visible simultaneously |
| Accessible | role=alert or role=status present |