e2e-tests
Skill2 starsChanged 8 months agoUnlicenseView on GitHub
Generate Playwright E2E tests for a user flow. Framework-agnostic (tests run in the browser, not against framework internals). Focus on critical user journeys. Do not use for component-level unit tests — use /component-tests instead.
- Reads credentials
12 other projects use a version of this.
Adopted by
Most recently taken up by
- oberemokis/skillstheir own version, first seen Nov 15, 2026
- piskelapp/piskeltheir own version, first seen Nov 9, 2026
- microsoft/physical-ai-toolchaintheir own version, first seen Nov 1, 2026
- pablopetr/claude-skillstheir own version, first seen Oct 25, 2026
- rterakedis/leanwheel-skillstheir own version, first seen Oct 17, 2026
- vstorm-co/agenticostheir own version, first seen Oct 16, 2026
Other versions12 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 12
- vitessio/vitess★ 21ksame name
- piskelapp/piskel★ 13ksame name
- borgbase/vykar★ 722same name
- vstorm-co/agenticos★ 241same name
- microsoft/physical-ai-toolchain★ 139same name
- braintrustdata/braintrust-sdk★ 30same name
- issue-orchestrator/issue-orchestrator★ 10same name
- Joomla-Bible-Study/joomla-skills★ 8same name
- GlamgarOnDiscord/claude-saas-blueprint★ 2same name
- oberemokis/skills★ 2same name
2 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository70 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- .cursor/rules/00-project-context.mdcCursor rule
- .cursor/rules/01b-component-gen-next.mdcCursor rule
- .cursor/rules/01-component-gen.mdcCursor rule
- .cursor/rules/02-component-tests.mdcCursor rule
- .cursor/rules/03b-vue-doctor.mdcCursor rule
- .cursor/rules/03-react-doctor.mdcCursor rule
- .cursor/rules/04-ui-tweak.mdcCursor rule
- .cursor/rules/05-refactor.mdcCursor rule
- .cursor/rules/06-frontend-code-review.mdcCursor rule
- .cursor/rules/07-fe-repo-scout.mdcCursor rule
- .cursor/rules/08-be-repo-scout.mdcCursor rule
- .cursor/rules/09-web-vitals.mdcCursor rule
- .cursor/rules/10-browser-check.mdcCursor rule
- .cursor/rules/11-api-bind.mdcCursor rule
- .cursor/rules/12-e2e-tests.mdcCursor rule
- .cursor/rules/13-api-mocks.mdcCursor rule
- agents-checkerSkill
- api-bindSkill
- api-mocksSkill
- be-repo-scoutSkill
- browser-checkSkill
- component-gen-nextSkill
- component-genSkill
- component-testsSkill
- curate-lessonsSkill
- e2e-testsSkill
- fe-repo-scoutSkill
- fix-markdownSkill
- frontend-code-reviewSkill
- init-agentSkill
- init-projectSkill
- init-skillSkill
- prSkill
- react-doctorSkill
- refactorSkill
- setup-configsSkill
- skill-auditSkill
- spec-auditSkill
- ui-tweakSkill
- update-ai-setupSkill
- vue-doctorSkill
- web-vitalsSkill
- agents-checkerSkill
- api-bindSkill
- api-mocksSkill
- be-repo-scoutSkill
- browser-checkSkill
- component-gen-nextSkill
- component-genSkill
- component-testsSkill
- curate-lessonsSkill
- fe-repo-scoutSkill
- fix-markdownSkill
- frontend-code-reviewSkill
- init-agentSkill
- init-projectSkill
- init-skillSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
7 rules. 0 are common, 1 is distinctive, and 6 are very specific to this project.
0
Common
Most of the 10 edited versions we read keep these.
1
Distinctive
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 12
Before execution the agent MUST load: .claude/protocols/gardener.md
- Very specific: line 27
Default base URL: http://localhost:5173 (Vite dev server).
- Very specific: line 75
Every Page Object MUST extend BasePage:
- Very specific: line 167
When --auth is passed, generate global setup to avoid re-authenticating per test:
- Very specific: line 200
When --mock is passed and the flow depends on external API calls:
- Distinctive: line 213
Add mocks only for APIs identified as unstable or external in the described flow.
- Very specific: line 236
Gardener Protocol: Call .claude/protocols/gardener.md before SKILL COMPLETE.
“Common” is measured: kept by at least 6 in 10 of the 10 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
SYSTEM REQUIREMENTS
Before execution the agent MUST load: .claude/protocols/gardener.md
E2E Tests Generator — Playwright
Generates Playwright E2E tests for critical user flows. Tests run in a real browser (Chromium by default). Focus: user-visible behavior, not implementation details. Produces stable, maintainable, accessible tests.
Input
Usage: /e2e-tests [flow-description] [base-url?] [--auth] [--mock] [--visual]
Example: /e2e-tests "User logs in and views dashboard" http://localhost:5173 --authDefault base URL: http://localhost:5173 (Vite dev server).
| Flag | Effect |
--auth | Generate e2e/auth/setup.ts + storageState session reuse |
--mock | Generate page.route() stubs for unstable backend APIs |
--visual | Add toHaveScreenshot() for critical UI components (opt-in) |
Protocol
BANNED
- Hardcoded waits:
page.waitForTimeout(2000)— FORBIDDEN (usewaitForURL,waitForSelector,expect(locator).toBeVisible()) - Hardcoded credentials:
'user@example.com'/'password123'— FORBIDDEN; useprocess.env.TEST_USER/process.env.TEST_PASSor a data factory page.locator('.css-class')— BANNED except as absolute Last Resort with comment// LAST RESORT: no role/label/testid available- Testing internal state (localStorage, Vuex/Pinia internals) — test what user SEES
- Duplicate selectors defined inline in each test — use Page Object Model
Selector Hierarchy
The agent MUST follow this priority order strictly:
1. getByRole — semantic, most stable
2. getByLabel — form fields
3. getByPlaceholder — inputs without visible label
4. getByTestId — data-testid attribute
5. getByText — visible text (avoid for dynamic content)
6. locator(css) — LAST RESORT only; requires commentTest Structure
e2e/
├── {flow-name}.spec.ts
├── auth/
│ └── setup.ts # storageState generation (--auth flag)
├── fixtures/
│ └── data.ts # data factories (unique strings / faker)
├── components/
│ └── {Name}.component.ts # shared component objects (nav, table, modal)
└── pages/
└── {Name}.page.ts # page objects (extend BasePage)BasePage Template
Every Page Object MUST extend BasePage:
// e2e/pages/BasePage.ts
import type { Page } from '@playwright/test';
import { expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
export abstract class BasePage {
constructor(protected page: Page) {}
async waitForReady() {
await this.page.waitForLoadState('networkidle');
}
async checkA11y() {
const results = await new AxeBuilder({ page: this.page }).analyze();
expect(results.violations).toEqual([]);
}
}checkA11y() is called explicitly in tests — not auto-injected. Keeps simple tests simple.
Page Object Model Template
// e2e/pages/LoginPage.ts
import type { Page } from '@playwright/test';
import { BasePage } from './BasePage';
export class LoginPage extends BasePage {
constructor(page: Page) {
super(page);
}
async goto() {
await this.page.goto('/login');
await this.waitForReady();
}
async login(email: string, password: string) {
await this.page.getByLabel('Email').fill(email);
await this.page.getByLabel('Password').fill(password);
await this.page.getByRole('button', { name: 'Sign in' }).click();
}
}Data Factories
// e2e/fixtures/data.ts
export const testUser = () => ({
email: `test-${Date.now()}@example.com`,
password: process.env.TEST_PASS ?? 'Secure123!',
});Replace ALL hardcoded credential strings with testUser() calls.
Test Template
// e2e/user-login.spec.ts
import { test, expect } from '@playwright/test';
import { LoginPage } from './pages/LoginPage';
import { testUser } from './fixtures/data';
test.describe('User login flow', () => {
test('successful login redirects to dashboard', async ({ page }) => {
const loginPage = new LoginPage(page);
const user = testUser();
await loginPage.goto();
await loginPage.login(user.email, user.password);
await expect(page).toHaveURL('/dashboard');
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
});
test('invalid credentials shows error message', async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login('bad@invalid.test', 'wrongpass');
await expect(
page.getByRole('alert', { name: /invalid/i })
).toBeVisible();
});
});Auth Storage State (--auth flag)
When --auth is passed, generate global setup to avoid re-authenticating per test:
// e2e/auth/setup.ts
import { chromium } from '@playwright/test';
async function globalSetup() {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('/login');
await page.getByLabel('Email').fill(process.env.TEST_USER!);
await page.getByLabel('Password').fill(process.env.TEST_PASS!);
await page.getByRole('button', { name: 'Sign in' }).click();
await page.waitForURL('/dashboard');
await page.context().storageState({ path: 'e2e/auth/auth.json' });
await browser.close();
}
export default globalSetup;Add to playwright.config.ts:
use: {
storageState: 'e2e/auth/auth.json',
},
globalSetup: './e2e/auth/setup.ts',auth.json MUST be in .gitignore.
Network Mocking (--mock flag)
When --mock is passed and the flow depends on external API calls:
// Intercept unstable API — add inside test or Page Object method
await page.route('**/api/orders', route =>
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ orders: [{ id: '1', status: 'delivered' }] }),
})
);Add mocks only for APIs identified as unstable or external in the described flow.
Workflow
- Discover — read
playwright.config.ts; check ife2e/auth/auth.jsonexists - Plan — identify 3-5 critical paths; decide if
--auth/--mockare needed based on flow - Generate — test file + Page Objects + fixtures + BasePage
- Run —
npx playwright test {file} --reporter=list 2>&1 | tail -30 - Fix — on failure: read trace screenshot via
cat→ update selector (max 3 iterations). After 3 failed fix attempts → output🛑 LOOP_GUARD_TRIGGERED: [selector/assertion]and PAUSE for user input - A11y — if page has forms or interactive elements: add
checkA11y()assertions - Gardener → SKILL COMPLETE
Quality Gates
- No hardcoded
waitForTimeout - No hardcoded credentials (use env vars or data factory)
- Selectors follow hierarchy (role → label → placeholder → testid → text → css last resort)
- Page Objects extend
BasePage testUser()factory used for all credential stringsauth.jsonadded to.gitignore(if--auth)- A11y check added for pages with forms or interactive widgets
- Tests pass
npx playwright test(against running dev server)
Gardener Protocol: Call .claude/protocols/gardener.md before SKILL COMPLETE.
Completion Contract
✅ SKILL COMPLETE: /e2e-tests
├─ Artifacts: [e2e/{flow}.spec.ts + Page Objects + fixtures?]
├─ Flow: [description]
├─ Tests: [N total]
├─ A11y: [violations: 0 | skipped]
└─ Run: [PASS | FAIL | SKIPPED (dev server not running)]Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

