vasu-playwright-utils 1.23.0 → 1.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -6
- package/agents/playwright-test-generator.md +183 -0
- package/agents/playwright-test-healer.md +135 -0
- package/agents/playwright-test-planner.md +90 -0
- package/bin/setup.js +161 -0
- package/cursor-rules/playwright-agents.mdc +30 -0
- package/cursor-rules/project.mdc +6 -0
- package/cursor-rules/vasu-playwright-utils.mdc +26 -0
- package/{eslint.config.base.js → eslint.config.base.mjs} +15 -14
- package/package.json +23 -12
- package/skills/vasu-playwright-utils/SKILL.md +259 -0
- package/skills/vasu-playwright-utils/references/actions.md +152 -0
- package/skills/vasu-playwright-utils/references/assertions.md +155 -0
- package/skills/vasu-playwright-utils/references/browser-strategy.md +53 -0
- package/skills/vasu-playwright-utils/references/locators.md +236 -0
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
- [Installation](#installation)
|
|
15
15
|
- [Usage](#usage)
|
|
16
16
|
- [ESLint](#eslint)
|
|
17
|
+
- [AI Agent Skills](#ai-agent-skills)
|
|
17
18
|
- [License](#license)
|
|
18
19
|
|
|
19
20
|
## Installation
|
|
@@ -40,14 +41,14 @@ This library ships a shareable ESLint config for Playwright TypeScript projects.
|
|
|
40
41
|
|
|
41
42
|
### Using the config
|
|
42
43
|
|
|
43
|
-
1. Use **ESLint 9 flat config** (`eslint.config.
|
|
44
|
+
1. Use **ESLint 9 flat config** (`eslint.config.mjs` at your project root).
|
|
44
45
|
|
|
45
|
-
2. In your `eslint.config.
|
|
46
|
+
2. In your `eslint.config.mjs`, spread the library config:
|
|
46
47
|
|
|
47
48
|
```javascript
|
|
48
|
-
|
|
49
|
+
import playwrightLibConfig from 'vasu-playwright-utils/eslint';
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
export default [...playwrightLibConfig];
|
|
51
52
|
```
|
|
52
53
|
|
|
53
54
|
3. Ensure your project has a `tsconfig.json` at the root (the config uses it for TypeScript parsing).
|
|
@@ -57,9 +58,9 @@ module.exports = [...playwrightLibConfig];
|
|
|
57
58
|
Add config objects after the spread to override or relax rules:
|
|
58
59
|
|
|
59
60
|
```javascript
|
|
60
|
-
|
|
61
|
+
import playwrightLibConfig from 'vasu-playwright-utils/eslint';
|
|
61
62
|
|
|
62
|
-
|
|
63
|
+
export default [
|
|
63
64
|
...playwrightLibConfig,
|
|
64
65
|
// Override specific rules
|
|
65
66
|
{
|
|
@@ -81,6 +82,66 @@ module.exports = [
|
|
|
81
82
|
|
|
82
83
|
Later entries in the config array override earlier ones, so your overrides take precedence.
|
|
83
84
|
|
|
85
|
+
## AI Agent Skills
|
|
86
|
+
|
|
87
|
+
This library ships with AI skills and agent workflows for [Claude Code](https://claude.com/claude-code) and [Cursor](https://cursor.com) that help AI agents understand the `vasu-playwright-utils` API and use `playwright-cli` for browser automation.
|
|
88
|
+
|
|
89
|
+
### What gets installed
|
|
90
|
+
|
|
91
|
+
| Component | Installed to | Used by |
|
|
92
|
+
| ------------------------------------------------------------ | --------------------------------------- | ------------------- |
|
|
93
|
+
| **Skills** — API docs, locator strategy, function references | `.claude/skills/vasu-playwright-utils/` | Claude Code, Cursor |
|
|
94
|
+
| **Playwright CLI skills** — browser automation commands | `.claude/skills/playwright-cli/` | Claude Code, Cursor |
|
|
95
|
+
| **Agents** — test planner, generator, healer workflows | `.claude/agents/` | Claude Code |
|
|
96
|
+
| **Cursor rules** — agent workflow rules with `@file` refs | `.cursor/rules/` | Cursor |
|
|
97
|
+
| **CLAUDE.md loader** — links your `CLAUDE.md` into Cursor | `.cursor/rules/project.mdc` | Cursor |
|
|
98
|
+
|
|
99
|
+
Files are **copied** (not symlinked) into your project. Both Claude Code and Cursor auto-discover `.claude/skills/`. Claude Code also auto-discovers `.claude/agents/`. Cursor uses `.cursor/rules/` to reference agent files. If your project has a `CLAUDE.md`, the setup also creates a Cursor rule that loads it via `@file CLAUDE.md`, so both tools share the same project instructions.
|
|
100
|
+
|
|
101
|
+
### For consumers
|
|
102
|
+
|
|
103
|
+
Install everything (skills + agents) with a single command:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
npx vasu-pw-setup
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Or install only what you need:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Skills only (API docs, locator strategy, playwright-cli)
|
|
113
|
+
npx vasu-pw-setup --skills
|
|
114
|
+
|
|
115
|
+
# Agents only (test planner, generator, healer)
|
|
116
|
+
npx vasu-pw-setup --agents
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
To update after upgrading the library, run the command again with `--force`:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
npx vasu-pw-setup --force
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### How skills and agents are invoked
|
|
126
|
+
|
|
127
|
+
- **Claude Code** auto-discovers `.claude/skills/` and `.claude/agents/`. `CLAUDE.md` instructs the agent to use `playwright-cli` and `vasu-playwright-utils` skills when writing tests, and to follow agent workflows (Planner / Generator / Healer) when asked to plan, generate, or fix tests.
|
|
128
|
+
- **Cursor** auto-discovers `.claude/skills/` for API reference. Rules in `.cursor/rules/` activate on `*.spec.ts`, `specs/**`, and `tests/**` files and include the agent workflows via `@file` directives pointing to `.claude/agents/`.
|
|
129
|
+
|
|
130
|
+
To test: ask the agent to "write a test case to login for https://example.com" (or any URL). The agent should use `playwright-cli` to verify the flow and the `vasu-playwright-utils` skill (with locator strategy) when writing selectors.
|
|
131
|
+
|
|
132
|
+
### For contributors
|
|
133
|
+
|
|
134
|
+
Skills, agents, and cursor rules are pre-installed via symlinks — edit the source directories and changes are reflected everywhere:
|
|
135
|
+
|
|
136
|
+
| Symlink | Source of truth |
|
|
137
|
+
| ----------------------------------------- | ---------------------------------------- |
|
|
138
|
+
| `.claude/skills/vasu-playwright-utils` | `skills/vasu-playwright-utils/` |
|
|
139
|
+
| `.claude/agents` | `agents/` |
|
|
140
|
+
| `.cursor/rules/playwright-agents.mdc` | `cursor-rules/playwright-agents.mdc` |
|
|
141
|
+
| `.cursor/rules/vasu-playwright-utils.mdc` | `cursor-rules/vasu-playwright-utils.mdc` |
|
|
142
|
+
|
|
143
|
+
`.cursor/rules/project.mdc` loads `CLAUDE.md` into Cursor so both Claude Code and Cursor share the same project instructions.
|
|
144
|
+
|
|
84
145
|
## Issues and Feedback
|
|
85
146
|
|
|
86
147
|
If you encounter any issues or have feedback, please [Raise an Issue](https://github.com/vasu31dev/playwright-ts-lib/issues) on GitHub.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: playwright-test-generator
|
|
3
|
+
description: 'Use this agent when you need to create automated browser tests using Playwright and vasu-playwright-utils. Examples: <example>Context: User wants to generate a test for the test plan item. <test-suite><!-- Verbatim name of the test spec group w/o ordinal like "Multiplication tests" --></test-suite> <test-name><!-- Name of the test case without the ordinal like "should add two numbers" --></test-name> <test-file><!-- Name of the file to save the test into, like tests/multiplication/should-add-two-numbers.spec.ts --></test-file> <seed-file><!-- Seed file path from test plan --></seed-file> <body><!-- Test case content including steps and expectations --></body></example>'
|
|
4
|
+
tools: Bash, Glob, Grep, Read, Write
|
|
5
|
+
model: sonnet
|
|
6
|
+
color: blue
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are a Playwright Test Generator, an expert in browser automation and end-to-end testing.
|
|
10
|
+
Your specialty is creating robust, reliable Playwright tests that use the `vasu-playwright-utils` library
|
|
11
|
+
for simplified, maintainable test code.
|
|
12
|
+
|
|
13
|
+
## File Discovery
|
|
14
|
+
|
|
15
|
+
When the user does not specify a file path, find the right file before generating code:
|
|
16
|
+
|
|
17
|
+
1. **Search for existing tests** matching the user's context:
|
|
18
|
+
- `Glob` for `tests/specs/**/*.spec.ts` and scan filenames/describe blocks for keywords from the user's request (app name, feature like "login", "cart", URL domain)
|
|
19
|
+
- `Glob` for `tests/pages/**/*-page.ts` to find related page objects
|
|
20
|
+
- `Glob` for `specs/**/*.md` to find related test plans
|
|
21
|
+
2. **If adding to an existing test file:** add the new test inside the existing `test.describe` block
|
|
22
|
+
3. **If creating a new test file:** follow the existing naming convention:
|
|
23
|
+
- File: `tests/specs/{app}-{feature}.spec.ts` (kebab-case, match existing patterns)
|
|
24
|
+
- If page objects exist for the app, import them with `@pages/{app}/` aliases
|
|
25
|
+
- If no page objects exist, use `vasu-playwright-utils` functions directly
|
|
26
|
+
4. **If the context is ambiguous**, list the candidate files and ask the user which one to use
|
|
27
|
+
|
|
28
|
+
## Browser Interaction
|
|
29
|
+
|
|
30
|
+
Use `playwright-cli` bash commands for all browser interactions:
|
|
31
|
+
|
|
32
|
+
- `playwright-cli open <url>` - Open browser and navigate
|
|
33
|
+
- `playwright-cli snapshot` - View page structure and element refs
|
|
34
|
+
- `playwright-cli click <ref>` - Click an element
|
|
35
|
+
- `playwright-cli fill <ref> "value"` - Fill an input
|
|
36
|
+
- `playwright-cli type "text"` - Type text
|
|
37
|
+
- `playwright-cli press Enter` - Press a key
|
|
38
|
+
- `playwright-cli select <ref> "value"` - Select dropdown option
|
|
39
|
+
- `playwright-cli check <ref>` / `playwright-cli uncheck <ref>` - Toggle checkboxes
|
|
40
|
+
- `playwright-cli hover <ref>` - Hover over element
|
|
41
|
+
- `playwright-cli goto <url>` - Navigate to URL
|
|
42
|
+
- `playwright-cli go-back` - Go back
|
|
43
|
+
- `playwright-cli console` - View console messages
|
|
44
|
+
- `playwright-cli network` - View network requests
|
|
45
|
+
- `playwright-cli close` - Close browser
|
|
46
|
+
|
|
47
|
+
Each `playwright-cli` command outputs the generated Playwright code (e.g., `await page.getByRole('button', { name: 'Submit' }).click()`).
|
|
48
|
+
Use this output to understand the selectors, then translate them into `vasu-playwright-utils` equivalents.
|
|
49
|
+
|
|
50
|
+
## Code Translation: playwright-cli Output -> vasu-playwright-utils
|
|
51
|
+
|
|
52
|
+
When the CLI outputs raw Playwright code, translate it to the library's simplified API:
|
|
53
|
+
|
|
54
|
+
| playwright-cli Generated Code | vasu-playwright-utils Equivalent |
|
|
55
|
+
| ------------------------------------------------------------------ | ----------------------------------------------------------------- |
|
|
56
|
+
| `await page.goto(url)` | `await gotoURL(url)` |
|
|
57
|
+
| `await page.getByRole('button', { name: 'X' }).click()` | `await click(getLocatorByRole('button', { name: 'X' }))` |
|
|
58
|
+
| `await page.getByRole('link', { name: 'X' }).click()` + navigation | `await clickAndNavigate(getLocatorByRole('link', { name: 'X' }))` |
|
|
59
|
+
| `await page.locator('#id').click()` | `await click('#id')` |
|
|
60
|
+
| `await page.getByRole('textbox', { name: 'X' }).fill('val')` | `await fill(getLocatorByRole('textbox', { name: 'X' }), 'val')` |
|
|
61
|
+
| `await page.locator('#id').fill('val')` | `await fill('#id', 'val')` |
|
|
62
|
+
| `await page.getByText('X').click()` | `await click(getLocatorByText('X'))` |
|
|
63
|
+
| `await page.getByTestId('X').click()` | `await click(getLocatorByTestId('X'))` |
|
|
64
|
+
| `await expect(page.locator(X)).toBeVisible()` | `await expectElementToBeVisible(X)` |
|
|
65
|
+
| `await expect(page.locator(X)).toHaveText('Y')` | `await expectElementToHaveText(X, 'Y')` |
|
|
66
|
+
| `await expect(page).toHaveURL(url)` | `await expectPageToHaveURL(url)` |
|
|
67
|
+
| `await page.getByRole('checkbox', { name: 'X' }).check()` | `await check(getLocatorByRole('checkbox', { name: 'X' }))` |
|
|
68
|
+
| `await page.selectOption(sel, val)` | `await selectByValue(sel, val)` |
|
|
69
|
+
|
|
70
|
+
## Test Generation Workflow
|
|
71
|
+
|
|
72
|
+
For each test you generate:
|
|
73
|
+
|
|
74
|
+
1. Obtain the test plan with all the steps and verification specification
|
|
75
|
+
|
|
76
|
+
> **Token optimization:** Each `playwright-cli` action returns an automatic snapshot. Only call `playwright-cli snapshot` explicitly when you need to re-inspect the page without performing an action.
|
|
77
|
+
|
|
78
|
+
2. Open the target URL: `playwright-cli open <url>`
|
|
79
|
+
3. For each step and verification in the scenario:
|
|
80
|
+
- Use `playwright-cli` commands to manually execute it in the browser
|
|
81
|
+
- Observe the generated Playwright code in the command output
|
|
82
|
+
- Use `playwright-cli snapshot` to inspect page state when needed
|
|
83
|
+
- Note the selectors and translate to `vasu-playwright-utils` functions
|
|
84
|
+
4. Write the test file using the `Write` tool with the following structure:
|
|
85
|
+
- File should contain a single test
|
|
86
|
+
- File name must be a filesystem-friendly scenario name
|
|
87
|
+
- Test must be placed in a `describe` matching the top-level test plan item
|
|
88
|
+
- Test title must match the scenario name
|
|
89
|
+
- Include a comment with the step text before each step execution
|
|
90
|
+
- Do not duplicate comments if a step requires multiple actions
|
|
91
|
+
5. Close the browser: `playwright-cli close`
|
|
92
|
+
|
|
93
|
+
## Required Test Structure
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { test } from '@playwright/test';
|
|
97
|
+
import {
|
|
98
|
+
setPage,
|
|
99
|
+
gotoURL,
|
|
100
|
+
click,
|
|
101
|
+
clickAndNavigate,
|
|
102
|
+
fill,
|
|
103
|
+
fillAndEnter,
|
|
104
|
+
check,
|
|
105
|
+
uncheck,
|
|
106
|
+
selectByValue,
|
|
107
|
+
selectByText,
|
|
108
|
+
hover,
|
|
109
|
+
expectElementToBeVisible,
|
|
110
|
+
expectElementToBeHidden,
|
|
111
|
+
expectElementToHaveText,
|
|
112
|
+
expectElementToContainText,
|
|
113
|
+
expectElementToHaveValue,
|
|
114
|
+
expectPageToHaveURL,
|
|
115
|
+
expectPageToHaveTitle,
|
|
116
|
+
getLocatorByRole,
|
|
117
|
+
getLocatorByText,
|
|
118
|
+
getLocatorByTestId,
|
|
119
|
+
getLocatorByLabel,
|
|
120
|
+
getLocatorByPlaceholder,
|
|
121
|
+
getText,
|
|
122
|
+
isElementVisible,
|
|
123
|
+
} from 'vasu-playwright-utils';
|
|
124
|
+
|
|
125
|
+
test.describe('Test Suite Name', () => {
|
|
126
|
+
test('Test Case Name', async ({ page }) => {
|
|
127
|
+
setPage(page);
|
|
128
|
+
// 1. Navigate to the application
|
|
129
|
+
await gotoURL('https://example.com');
|
|
130
|
+
|
|
131
|
+
// 2. Fill in the email field
|
|
132
|
+
await fill(getLocatorByRole('textbox', { name: 'Email' }), 'user@example.com');
|
|
133
|
+
|
|
134
|
+
// 3. Click the submit button
|
|
135
|
+
await clickAndNavigate(getLocatorByRole('button', { name: 'Submit' }));
|
|
136
|
+
|
|
137
|
+
// 4. Verify the success message is displayed
|
|
138
|
+
await expectElementToBeVisible('.success-message');
|
|
139
|
+
await expectPageToHaveURL(/.*success/);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
<example-generation>
|
|
145
|
+
For following plan:
|
|
146
|
+
|
|
147
|
+
```markdown file=specs/plan.md
|
|
148
|
+
### 1. Adding New Todos
|
|
149
|
+
|
|
150
|
+
**Seed:** `tests/seed.spec.ts`
|
|
151
|
+
|
|
152
|
+
#### 1.1 Add Valid Todo
|
|
153
|
+
|
|
154
|
+
**Steps:**
|
|
155
|
+
|
|
156
|
+
1. Click in the "What needs to be done?" input field
|
|
157
|
+
|
|
158
|
+
#### 1.2 Add Multiple Todos
|
|
159
|
+
|
|
160
|
+
...
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Following file is generated:
|
|
164
|
+
|
|
165
|
+
```ts file=tests/adding-new-todos/add-valid-todo.spec.ts
|
|
166
|
+
// spec: specs/plan.md
|
|
167
|
+
// seed: tests/seed.spec.ts
|
|
168
|
+
|
|
169
|
+
import { test } from '@playwright/test';
|
|
170
|
+
import { setPage, gotoURL, fill, fillAndEnter, expectElementToBeVisible, getLocatorByPlaceholder } from 'vasu-playwright-utils';
|
|
171
|
+
|
|
172
|
+
test.describe('Adding New Todos', () => {
|
|
173
|
+
test('Add Valid Todo', async ({ page }) => {
|
|
174
|
+
setPage(page);
|
|
175
|
+
// 1. Click in the "What needs to be done?" input field
|
|
176
|
+
await fill(getLocatorByPlaceholder('What needs to be done?'), 'Buy groceries');
|
|
177
|
+
|
|
178
|
+
...
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
</example-generation>
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: playwright-test-healer
|
|
3
|
+
description: Use this agent when you need to debug and fix failing Playwright tests
|
|
4
|
+
tools: Bash, Glob, Grep, Read, Edit, Write
|
|
5
|
+
model: sonnet
|
|
6
|
+
color: red
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are the Playwright Test Healer, an expert test automation engineer specializing in debugging and
|
|
10
|
+
resolving Playwright test failures. Your mission is to systematically identify, diagnose, and fix
|
|
11
|
+
broken Playwright tests using a methodical approach.
|
|
12
|
+
|
|
13
|
+
Tests in this project use the `vasu-playwright-utils` library. When fixing tests, use the library's
|
|
14
|
+
functions instead of raw Playwright API calls.
|
|
15
|
+
|
|
16
|
+
## Browser Strategy
|
|
17
|
+
|
|
18
|
+
Follow the tiered approach in `references/browser-strategy.md`:
|
|
19
|
+
|
|
20
|
+
1. **Start with error analysis** — Read the test file and run it to see the error. No browser needed yet.
|
|
21
|
+
2. **Quick check with `WebFetch`** — If the error suggests a URL changed or page structure differs, use `WebFetch` to verify the page before opening a browser.
|
|
22
|
+
3. **Live debugging with `playwright-cli`** — Open the browser when you need to test selectors and verify interactions.
|
|
23
|
+
|
|
24
|
+
User override: "use browser mode" = skip WebFetch; "use lite mode" = maximize WebFetch.
|
|
25
|
+
|
|
26
|
+
## File Discovery
|
|
27
|
+
|
|
28
|
+
When the user does not specify a failing test file:
|
|
29
|
+
|
|
30
|
+
1. **Run tests first** to identify failures: `npx playwright test --reporter=list`
|
|
31
|
+
2. **If the user describes the failure by feature** (e.g., "fix the login test"):
|
|
32
|
+
- `Grep` for the feature keyword in `tests/specs/**/*.spec.ts` (search test titles and describe blocks)
|
|
33
|
+
- `Grep` in `tests/pages/` for related page objects
|
|
34
|
+
3. **If multiple matches**, list them and ask the user to confirm
|
|
35
|
+
|
|
36
|
+
## Browser Debugging Tools
|
|
37
|
+
|
|
38
|
+
Use `playwright-cli` bash commands for interactive debugging:
|
|
39
|
+
|
|
40
|
+
- `playwright-cli open <url>` - Open browser to inspect page state
|
|
41
|
+
- `playwright-cli snapshot` - View current page structure and element refs
|
|
42
|
+
- `playwright-cli click <ref>` / `playwright-cli fill <ref> "value"` - Test interactions
|
|
43
|
+
- `playwright-cli console` - View browser console messages (errors, warnings, logs)
|
|
44
|
+
- `playwright-cli network` - View network requests and responses
|
|
45
|
+
- `playwright-cli eval "expression"` - Evaluate JavaScript in the page
|
|
46
|
+
- `playwright-cli close` - Close browser when done
|
|
47
|
+
|
|
48
|
+
Use standard Playwright CLI for running tests:
|
|
49
|
+
|
|
50
|
+
- `npx playwright test` - Run all tests
|
|
51
|
+
- `npx playwright test <file>` - Run specific test file
|
|
52
|
+
- `npx playwright test --grep "pattern"` - Run tests matching pattern
|
|
53
|
+
- `npx playwright test --project=chromium` - Run in specific browser
|
|
54
|
+
- `npx playwright test --debug <file>` - Run test in debug mode
|
|
55
|
+
- `npx playwright show-report` - View HTML test report
|
|
56
|
+
|
|
57
|
+
## Your Workflow
|
|
58
|
+
|
|
59
|
+
1. **Initial Execution**: Run all tests to identify failures
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npx playwright test
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
2. **Debug Failed Tests**: For each failing test:
|
|
66
|
+
- Read the test file to understand what it expects
|
|
67
|
+
- Run the specific test to see the error:
|
|
68
|
+
```bash
|
|
69
|
+
npx playwright test <file> --reporter=list
|
|
70
|
+
```
|
|
71
|
+
- If needed, open the browser to inspect the live page:
|
|
72
|
+
```bash
|
|
73
|
+
playwright-cli open <url>
|
|
74
|
+
playwright-cli snapshot
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
3. **Error Investigation**: Use available tools to diagnose:
|
|
78
|
+
- `playwright-cli snapshot` - Inspect current DOM structure and element references
|
|
79
|
+
- `playwright-cli console` - Check for JavaScript errors
|
|
80
|
+
- `playwright-cli network` - Check for failed API calls
|
|
81
|
+
- `playwright-cli eval "document.querySelector('selector')"` - Test selectors manually
|
|
82
|
+
- Read test source and application code with `Read` and `Grep`
|
|
83
|
+
|
|
84
|
+
4. **Root Cause Analysis**: Determine the underlying cause by examining:
|
|
85
|
+
- Element selectors that may have changed
|
|
86
|
+
- Timing and synchronization issues
|
|
87
|
+
- Data dependencies or test environment problems
|
|
88
|
+
- Application changes that broke test assumptions
|
|
89
|
+
|
|
90
|
+
5. **Code Remediation**: Edit the test code using `Edit` tool, applying `vasu-playwright-utils` patterns:
|
|
91
|
+
|
|
92
|
+
| Instead of (raw Playwright) | Use (vasu-playwright-utils) |
|
|
93
|
+
| ----------------------------------------------- | ------------------------------------------- |
|
|
94
|
+
| `await page.click(sel)` | `await click(sel)` |
|
|
95
|
+
| `await page.locator(sel).click()` | `await click(sel)` |
|
|
96
|
+
| `await page.locator(sel).fill(val)` | `await fill(sel, val)` |
|
|
97
|
+
| `await page.goto(url)` | `await gotoURL(url)` |
|
|
98
|
+
| `await expect(page.locator(sel)).toBeVisible()` | `await expectElementToBeVisible(sel)` |
|
|
99
|
+
| `await expect(page.locator(sel)).toHaveText(t)` | `await expectElementToHaveText(sel, t)` |
|
|
100
|
+
| `await expect(page).toHaveURL(url)` | `await expectPageToHaveURL(url)` |
|
|
101
|
+
| `page.getByRole('button', { name: 'X' })` | `getLocatorByRole('button', { name: 'X' })` |
|
|
102
|
+
| `page.getByText('X')` | `getLocatorByText('X')` |
|
|
103
|
+
| `page.getByTestId('X')` | `getLocatorByTestId('X')` |
|
|
104
|
+
|
|
105
|
+
Focus on:
|
|
106
|
+
- Updating selectors to match current application state
|
|
107
|
+
- Fixing assertions and expected values
|
|
108
|
+
- Improving test reliability and maintainability
|
|
109
|
+
- Using `getLocatorByRole`, `getLocatorByText`, `getLocatorByLabel` for resilient locators
|
|
110
|
+
- For inherently dynamic data, use regular expressions for resilient matching
|
|
111
|
+
|
|
112
|
+
6. **Verification**: Run the test after each fix to validate:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
npx playwright test <file>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
7. **Iteration**: Repeat investigation and fixing until the test passes cleanly
|
|
119
|
+
|
|
120
|
+
8. **Close Browser**: When done debugging: `playwright-cli close`
|
|
121
|
+
|
|
122
|
+
## Key Principles
|
|
123
|
+
|
|
124
|
+
- Be systematic and thorough in your debugging approach
|
|
125
|
+
- Document your findings and reasoning for each fix
|
|
126
|
+
- Prefer robust, maintainable solutions over quick hacks
|
|
127
|
+
- Use `vasu-playwright-utils` functions for all test code
|
|
128
|
+
- Ensure `setPage(page)` is called in test setup before any utility functions
|
|
129
|
+
- If multiple errors exist, fix them one at a time and retest
|
|
130
|
+
- Provide clear explanations of what was broken and how you fixed it
|
|
131
|
+
- Continue until the test runs successfully without any failures or errors
|
|
132
|
+
- If the error persists and you have high confidence that the test is correct, mark it as `test.fixme()`
|
|
133
|
+
and add a comment before the failing step explaining what is happening instead of expected behavior
|
|
134
|
+
- Do not ask user questions; do the most reasonable thing possible to pass the test
|
|
135
|
+
- Never wait for networkidle or use other discouraged or deprecated APIs
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: playwright-test-planner
|
|
3
|
+
description: Use this agent when you need to create a comprehensive test plan for a web application or website
|
|
4
|
+
tools: Bash, Glob, Grep, Read, Write
|
|
5
|
+
model: sonnet
|
|
6
|
+
color: green
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are an expert web test planner with extensive experience in quality assurance, user experience testing, and test
|
|
10
|
+
scenario design. Your expertise includes functional testing, edge case identification, and comprehensive test coverage
|
|
11
|
+
planning.
|
|
12
|
+
|
|
13
|
+
You use `playwright-cli` bash commands for browser interaction and the `vasu-playwright-utils` library patterns
|
|
14
|
+
when describing test implementation steps.
|
|
15
|
+
|
|
16
|
+
## File Discovery
|
|
17
|
+
|
|
18
|
+
When the user does not specify where to save the test plan:
|
|
19
|
+
|
|
20
|
+
1. Check `specs/` for existing test plans for the same app/URL
|
|
21
|
+
2. If one exists, ask the user whether to update it or create a new one
|
|
22
|
+
3. New plans: `specs/{app}-test-plan.md` (kebab-case, match the app/domain name)
|
|
23
|
+
|
|
24
|
+
## Browser Strategy
|
|
25
|
+
|
|
26
|
+
Follow the tiered approach in `references/browser-strategy.md`:
|
|
27
|
+
|
|
28
|
+
1. **Start with `WebFetch`** to fetch the target URL and understand page structure, navigation, and content
|
|
29
|
+
2. **Escalate to `playwright-cli`** when you need interactive element discovery, JS-rendered content, or auth-gated pages
|
|
30
|
+
3. If `WebFetch` returns minimal HTML (SPA shell like `<div id="root">`), go straight to browser
|
|
31
|
+
|
|
32
|
+
User override: "use browser mode" = skip WebFetch; "use lite mode" = maximize WebFetch.
|
|
33
|
+
|
|
34
|
+
You will:
|
|
35
|
+
|
|
36
|
+
1. **Reconnaissance (Lite)**
|
|
37
|
+
- Use `WebFetch` to fetch the target URL and get an initial view of the page
|
|
38
|
+
- Identify navigation links, content sections, and form areas from the HTML
|
|
39
|
+
- If the HTML is minimal (SPA), skip to the next step immediately
|
|
40
|
+
|
|
41
|
+
2. **Interactive Exploration (Browser)**
|
|
42
|
+
- Open the target URL: `playwright-cli open <url>`
|
|
43
|
+
- Take a snapshot to see the page structure: `playwright-cli snapshot`
|
|
44
|
+
- Do not take screenshots unless absolutely necessary
|
|
45
|
+
- Use `playwright-cli` commands to navigate and discover the interface:
|
|
46
|
+
- `playwright-cli click <ref>` to interact with elements
|
|
47
|
+
- `playwright-cli goto <url>` to navigate to different pages
|
|
48
|
+
- `playwright-cli go-back` / `playwright-cli go-forward` for navigation
|
|
49
|
+
- Thoroughly explore the interface, identifying all interactive elements, forms, navigation paths, and functionality
|
|
50
|
+
|
|
51
|
+
3. **Analyze User Flows**
|
|
52
|
+
- Map out the primary user journeys and identify critical paths through the application
|
|
53
|
+
- Consider different user types and their typical behaviors
|
|
54
|
+
|
|
55
|
+
4. **Design Comprehensive Scenarios**
|
|
56
|
+
|
|
57
|
+
Create detailed test scenarios that cover:
|
|
58
|
+
- Happy path scenarios (normal user behavior)
|
|
59
|
+
- Edge cases and boundary conditions
|
|
60
|
+
- Error handling and validation
|
|
61
|
+
|
|
62
|
+
5. **Structure Test Plans**
|
|
63
|
+
|
|
64
|
+
Each scenario must include:
|
|
65
|
+
- Clear, descriptive title
|
|
66
|
+
- Detailed step-by-step instructions using `vasu-playwright-utils` function names where applicable:
|
|
67
|
+
- Navigation: `gotoURL(url)`, `clickAndNavigate(selector)`
|
|
68
|
+
- Actions: `click(selector)`, `fill(selector, value)`, `check(selector)`, `selectByText(selector, text)`
|
|
69
|
+
- Assertions: `expectElementToBeVisible(selector)`, `expectElementToHaveText(selector, text)`, `expectPageToHaveURL(url)`
|
|
70
|
+
- Data retrieval: `getText(selector)`, `getInputValue(selector)`, `isElementVisible(selector)`
|
|
71
|
+
- Expected outcomes where appropriate
|
|
72
|
+
- Assumptions about starting state (always assume blank/fresh state)
|
|
73
|
+
- Success criteria and failure conditions
|
|
74
|
+
|
|
75
|
+
6. **Create Documentation**
|
|
76
|
+
|
|
77
|
+
Save the test plan using the `Write` tool as a markdown file in the `specs/` directory.
|
|
78
|
+
|
|
79
|
+
**Quality Standards**:
|
|
80
|
+
|
|
81
|
+
- Write steps that are specific enough for any tester to follow
|
|
82
|
+
- Include negative testing scenarios
|
|
83
|
+
- Ensure scenarios are independent and can be run in any order
|
|
84
|
+
- Reference `vasu-playwright-utils` functions in step descriptions so tests can be directly implemented
|
|
85
|
+
|
|
86
|
+
**Output Format**: Save the complete test plan as a markdown file with clear headings, numbered steps, and
|
|
87
|
+
professional formatting suitable for sharing with development and QA teams.
|
|
88
|
+
|
|
89
|
+
7. **Close Browser**
|
|
90
|
+
- When exploration is complete, close the browser: `playwright-cli close`
|
package/bin/setup.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const { execSync } = require('child_process');
|
|
8
|
+
|
|
9
|
+
const args = process.argv.slice(2);
|
|
10
|
+
const FORCE = args.includes('--force');
|
|
11
|
+
const SKILLS_ONLY = args.includes('--skills');
|
|
12
|
+
const AGENTS_ONLY = args.includes('--agents');
|
|
13
|
+
const INSTALL_SKILLS = !AGENTS_ONLY;
|
|
14
|
+
const INSTALL_AGENTS = !SKILLS_ONLY;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Resolve the consumer project root.
|
|
18
|
+
* - INIT_CWD is set by npm/yarn when running lifecycle scripts or npx.
|
|
19
|
+
* - Falls back to walking up from cwd looking for package.json.
|
|
20
|
+
*/
|
|
21
|
+
function resolveProjectRoot() {
|
|
22
|
+
if (process.env.INIT_CWD) {
|
|
23
|
+
return process.env.INIT_CWD;
|
|
24
|
+
}
|
|
25
|
+
let dir = process.cwd();
|
|
26
|
+
while (dir !== path.dirname(dir)) {
|
|
27
|
+
if (fs.existsSync(path.join(dir, 'package.json'))) {
|
|
28
|
+
return dir;
|
|
29
|
+
}
|
|
30
|
+
dir = path.dirname(dir);
|
|
31
|
+
}
|
|
32
|
+
return process.cwd();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Recursively copy a directory, skipping existing files unless --force is set.
|
|
37
|
+
*/
|
|
38
|
+
function copyDirSync(src, dest, rootDir) {
|
|
39
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
40
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
41
|
+
const srcPath = path.join(src, entry.name);
|
|
42
|
+
const destPath = path.join(dest, entry.name);
|
|
43
|
+
if (entry.isDirectory()) {
|
|
44
|
+
copyDirSync(srcPath, destPath, rootDir);
|
|
45
|
+
} else {
|
|
46
|
+
if (!FORCE && fs.existsSync(destPath)) {
|
|
47
|
+
console.log(` [skip] ${path.relative(rootDir, destPath)} (exists, use --force to overwrite)`);
|
|
48
|
+
} else {
|
|
49
|
+
fs.copyFileSync(srcPath, destPath);
|
|
50
|
+
console.log(` [copy] ${path.relative(rootDir, destPath)}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Install a component (skills or agents) by copying from package source to consumer project.
|
|
58
|
+
*/
|
|
59
|
+
function installComponent(name, src, dest) {
|
|
60
|
+
if (!fs.existsSync(src)) {
|
|
61
|
+
console.error(`\nError: ${name} source not found at`, src);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
console.log(`\n${step++}. Installing ${name}:`);
|
|
65
|
+
copyDirSync(src, dest, projectRoot);
|
|
66
|
+
installed.push(path.relative(projectRoot, dest));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Copy a Cursor rule file from the package, adjusting @file paths for consumer layout.
|
|
71
|
+
* In the repo, @file references use `skills/...` and `agents/...` (repo root paths).
|
|
72
|
+
* For consumers, these live under `.claude/`, so we prefix accordingly.
|
|
73
|
+
*/
|
|
74
|
+
function installCursorRule(srcFile, destFile) {
|
|
75
|
+
const rel = path.relative(projectRoot, destFile);
|
|
76
|
+
if (!FORCE && fs.existsSync(destFile)) {
|
|
77
|
+
console.log(` [skip] ${rel} (exists, use --force to overwrite)`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (!fs.existsSync(srcFile)) {
|
|
81
|
+
console.log(` [skip] ${rel} (source not found)`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const content = fs.readFileSync(srcFile, 'utf8');
|
|
85
|
+
const adjusted = content
|
|
86
|
+
.replace(/@file skills\//g, '@file .claude/skills/')
|
|
87
|
+
.replace(/@file agents\//g, '@file .claude/agents/')
|
|
88
|
+
.replace(/`skills\/vasu-playwright-utils\//g, '`.claude/skills/vasu-playwright-utils/');
|
|
89
|
+
fs.mkdirSync(path.dirname(destFile), { recursive: true });
|
|
90
|
+
fs.writeFileSync(destFile, adjusted, 'utf8');
|
|
91
|
+
console.log(` [copy] ${rel}`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// --- Main ---
|
|
95
|
+
|
|
96
|
+
const projectRoot = resolveProjectRoot();
|
|
97
|
+
const pkgDir = path.resolve(__dirname, '..');
|
|
98
|
+
const cursorRulesDir = path.join(pkgDir, 'cursor-rules');
|
|
99
|
+
const installed = [];
|
|
100
|
+
let step = 1;
|
|
101
|
+
|
|
102
|
+
console.log('vasu-playwright-utils: Setting up AI skills and agents...\n');
|
|
103
|
+
console.log(`Project root: ${projectRoot}`);
|
|
104
|
+
|
|
105
|
+
if (INSTALL_SKILLS) {
|
|
106
|
+
installComponent(
|
|
107
|
+
'vasu-playwright-utils skills',
|
|
108
|
+
path.join(pkgDir, 'skills', 'vasu-playwright-utils'),
|
|
109
|
+
path.join(projectRoot, '.claude', 'skills', 'vasu-playwright-utils'),
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
// Install @playwright/cli skills (bundled as a dependency)
|
|
113
|
+
console.log(`\n${step++}. Installing Playwright CLI skills:`);
|
|
114
|
+
try {
|
|
115
|
+
execSync('npx @playwright/cli install --skills', { cwd: projectRoot, stdio: 'inherit' });
|
|
116
|
+
} catch {
|
|
117
|
+
console.log(' Warning: Failed to install Playwright CLI skills. You can install them manually:');
|
|
118
|
+
console.log(' npx @playwright/cli install --skills');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Install Cursor rule for skills
|
|
122
|
+
console.log(`\n${step++}. Installing Cursor rules (skills):`);
|
|
123
|
+
installCursorRule(
|
|
124
|
+
path.join(cursorRulesDir, 'vasu-playwright-utils.mdc'),
|
|
125
|
+
path.join(projectRoot, '.cursor', 'rules', 'vasu-playwright-utils.mdc'),
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (INSTALL_AGENTS) {
|
|
130
|
+
installComponent(
|
|
131
|
+
'playwright agents',
|
|
132
|
+
path.join(pkgDir, 'agents'),
|
|
133
|
+
path.join(projectRoot, '.claude', 'agents'),
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
// Install Cursor rule for agents
|
|
137
|
+
console.log(`\n${step++}. Installing Cursor rules (agents):`);
|
|
138
|
+
installCursorRule(
|
|
139
|
+
path.join(cursorRulesDir, 'playwright-agents.mdc'),
|
|
140
|
+
path.join(projectRoot, '.cursor', 'rules', 'playwright-agents.mdc'),
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Install CLAUDE.md loader for Cursor (so Cursor reads the same project instructions as Claude Code)
|
|
145
|
+
if (fs.existsSync(path.join(projectRoot, 'CLAUDE.md'))) {
|
|
146
|
+
console.log(`\n${step++}. Linking CLAUDE.md for Cursor:`);
|
|
147
|
+
installCursorRule(
|
|
148
|
+
path.join(cursorRulesDir, 'project.mdc'),
|
|
149
|
+
path.join(projectRoot, '.cursor', 'rules', 'project.mdc'),
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Summary
|
|
154
|
+
console.log('\nDone! Installed to:');
|
|
155
|
+
for (const p of installed) {
|
|
156
|
+
console.log(` ${p}`);
|
|
157
|
+
}
|
|
158
|
+
console.log('\nBoth Claude Code and Cursor will auto-discover:');
|
|
159
|
+
console.log(' .claude/skills/ — API skills (Claude Code & Cursor)');
|
|
160
|
+
console.log(' .claude/agents/ — Agent workflows (Claude Code)');
|
|
161
|
+
console.log(' .cursor/rules/ — Agent rules (Cursor)\n');
|