@relipa/ai-flow-kit 0.1.0 → 0.1.1

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.
@@ -119,6 +119,39 @@ See: [Figma workflow guide](../../docs/common/workflows/figma.md)
119
119
 
120
120
  ---
121
121
 
122
+ ### Playwright (`playwright.json`)
123
+
124
+ Drive a real browser to explore selectors, verify flows, and capture evidence. Powers the `automation-testing` skill (Phase 3 — Explore).
125
+
126
+ **When to use:** Generating E2E UI tests. The skill uses MCP to read the live DOM (real selectors, not guessed) and screenshot each step, then emits durable `.spec.ts` files for CI.
127
+
128
+ **Setup:**
129
+ ```bash
130
+ aiflow init --adapter playwright
131
+ ```
132
+
133
+ **Requirements:**
134
+ - The web app under test must be running and reachable at `baseUrl`
135
+ - No API token needed
136
+ - First run downloads browsers via `npx playwright install` (one-time)
137
+
138
+ **Tools provided by `@playwright/mcp`:**
139
+ - `browser_navigate(url)` — open a page
140
+ - `browser_snapshot()` — accessibility tree (source of real selectors)
141
+ - `browser_click` / `browser_type` / `browser_fill` — interact with elements
142
+ - `browser_take_screenshot(path)` — capture evidence
143
+
144
+ **Usage:**
145
+ ```
146
+ /automation-testing baseUrl: http://localhost:3000 explore: true
147
+ ```
148
+
149
+ > **Hybrid principle:** MCP is for *exploration + evidence* only. It does not replace test files — the skill always emits committable `.spec.ts` so CI can re-run.
150
+
151
+ See: [automation-testing design](../../requirements/autotest/AutomationTestWorkflow.md)
152
+
153
+ ---
154
+
122
155
  ### Google Sheets (`google-sheets.json`)
123
156
 
124
157
  Connect to Google Sheets for loading task context.
@@ -0,0 +1,11 @@
1
+ {
2
+ "mcpServers": {
3
+ "playwright": {
4
+ "command": "npx",
5
+ "args": [
6
+ "-y",
7
+ "@playwright/mcp@latest"
8
+ ]
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,105 @@
1
+ # E2E Test Patterns (Playwright)
2
+
3
+ Reusable patterns the `automation-testing` skill applies when generating Page Objects and specs. Selector priority is always: **`getByRole` → `getByLabel` → `getByTestId`** → (CSS/XPath only as last resort).
4
+
5
+ ---
6
+
7
+ ## 1. Login / Authentication
8
+
9
+ **Test cases to cover:**
10
+ - Valid credentials → redirect to landing page
11
+ - Wrong password → error message visible
12
+ - Empty required field → validation message
13
+ - (optional) Locked/disabled account → blocked
14
+
15
+ ```typescript
16
+ test('TC01 - Login success', async ({ page }) => {
17
+ const login = new LoginPage(page);
18
+ await login.navigate('/login');
19
+ await login.login('user@example.com', 'Password123');
20
+ await expect(page).toHaveURL(/\/dashboard/);
21
+ });
22
+ ```
23
+
24
+ ---
25
+
26
+ ## 2. CRUD (Create / Read / Update / Delete)
27
+
28
+ **Cover:** create → appears in list → edit → reflects change → delete → removed. Always assert on the list/detail after each mutation, not just the success toast.
29
+
30
+ ```typescript
31
+ test('Create item appears in list', async ({ page }) => {
32
+ const list = new ItemListPage(page);
33
+ await list.navigate('/items');
34
+ await list.openCreate();
35
+ await list.fillForm({ name: 'Sample' });
36
+ await list.submit();
37
+ await expect(list.rowByName('Sample')).toBeVisible();
38
+ });
39
+ ```
40
+
41
+ > **Test data:** prefer a unique suffix (e.g. timestamp passed in via fixture) so reruns don't collide. Clean up created data in `afterEach` when possible.
42
+
43
+ ---
44
+
45
+ ## 3. Form validation
46
+
47
+ - Submit empty → each required field shows its message
48
+ - Invalid format (email, phone) → format message
49
+ - Boundary (min/max length) → length message
50
+ - Valid input → no error, submit succeeds
51
+
52
+ ```typescript
53
+ test('Email format validation', async ({ page }) => {
54
+ const form = new SignupPage(page);
55
+ await form.navigate('/signup');
56
+ await form.emailInput.fill('not-an-email');
57
+ await form.submit();
58
+ await expect(page.getByText(/invalid email/i)).toBeVisible();
59
+ });
60
+ ```
61
+
62
+ ---
63
+
64
+ ## 4. Modal / Dialog
65
+
66
+ - Open trigger → modal visible
67
+ - Confirm → action runs + modal closes
68
+ - Cancel / backdrop / Esc → modal closes, no action
69
+
70
+ ```typescript
71
+ await page.getByRole('button', { name: 'Delete' }).click();
72
+ const dialog = page.getByRole('dialog');
73
+ await expect(dialog).toBeVisible();
74
+ await dialog.getByRole('button', { name: 'Confirm' }).click();
75
+ await expect(dialog).toBeHidden();
76
+ ```
77
+
78
+ ---
79
+
80
+ ## 5. Pagination / Table
81
+
82
+ - Default page loads expected count
83
+ - Next/Prev changes rows
84
+ - Page size change updates count
85
+ - Sort by column reorders rows
86
+
87
+ ```typescript
88
+ await expect(page.getByRole('row')).toHaveCount(11); // header + 10 rows
89
+ await page.getByRole('button', { name: 'Next' }).click();
90
+ await expect(page.getByText('Page 2')).toBeVisible();
91
+ ```
92
+
93
+ ---
94
+
95
+ ## 6. General assertions & waits
96
+
97
+ - Prefer **web-first assertions** (`await expect(locator).toBeVisible()`) — they auto-retry. Never `waitForTimeout` to "wait for UI".
98
+ - Assert on **user-visible outcome** (URL, text, element state), not internal state.
99
+ - For async data, assert the loaded element, not a spinner disappearing.
100
+
101
+ ---
102
+
103
+ ## 7. Evidence (MCP explore phase)
104
+
105
+ When exploring via Playwright MCP, capture a screenshot per significant step into `<evidenceDir>/[ticket-id]/TC<NN>-step<N>.png`. Name files so the reviewer can map evidence → test case at a glance.
@@ -0,0 +1,168 @@
1
+ ---
2
+ name: automation-testing
3
+ description: Generate runnable Playwright E2E tests for a web UI from requirement/business-logic docs or a tester's free-form draft. Uses Playwright MCP to explore real selectors and capture evidence on a live browser, then emits durable .spec.ts files plus an HTML report. Tester does not need to know TypeScript.
4
+ keywords: automation, testing, playwright, e2e, mcp, testcase, browser, evidence, report, qa, tester
5
+ ---
6
+
7
+ # Automation Testing (Hybrid MCP)
8
+
9
+ Generate **runnable** Playwright E2E tests for a web UI. Works in a **multi-repo workspace** (a parent folder containing backend + frontend repos).
10
+
11
+ ## Core principle — HYBRID
12
+
13
+ > Playwright MCP does **not** replace test files. It **improves** them.
14
+ > Use the live browser to *learn* the app's real selectors and capture evidence, but the deliverable is always committable `.spec.ts` so CI can re-run.
15
+
16
+ ## When to use
17
+
18
+ - Tester/Dev wants E2E UI tests but doesn't write TypeScript
19
+ - A requirement (`requirement.md`) or business-logic doc exists and test cases should be derived from it
20
+ - A finished feature needs regression coverage with evidence
21
+
22
+ ## How to invoke
23
+
24
+ ```
25
+ /automation-testing baseUrl: <url> [explore: true|false] [autoRun: true|false] [headed: true|false] [ticketId: <id>]
26
+ ---
27
+ (optional) tester's free-form test case draft
28
+ ```
29
+
30
+ **Example:**
31
+ ```
32
+ /automation-testing baseUrl: http://localhost:3000 explore: true autoRun: true
33
+ ---
34
+ 1. Vào /login, nhập đúng email/password → vào dashboard
35
+ 2. Nhập sai password → hiện thông báo lỗi
36
+ 3. Để trống email → hiện validation lỗi
37
+ ```
38
+
39
+ ## Params
40
+
41
+ | Param | Type | Default | Description |
42
+ |-------|------|---------|-------------|
43
+ | `baseUrl` | string | — | URL of the running web app **(required)** |
44
+ | `explore` | boolean | `true` | Use Playwright MCP to explore real selectors + capture evidence before generating |
45
+ | `autoRun` | boolean | `true` | Run `npx playwright test` after generating |
46
+ | `headed` | boolean | `false` | Show browser window during `autoRun` (CI should keep `false`) |
47
+ | `ticketId` | string | — | Ticket id; if omitted, read from `.aiflow/context/current.json` |
48
+
49
+ ---
50
+
51
+ ## Phase 1 — Collect
52
+
53
+ 1. **Resolve workspace.** Read `.aiflow/repos.json`.
54
+ - If it does NOT exist: copy the template at `.claude/skills/automation-testing/templates/repos.json`, ask the user to confirm the paths (`backend`, `frontend`, `e2e`, `planDir`, `evidenceDir`), then write `.aiflow/repos.json`. **Do not guess** the folder layout.
55
+ 2. **Resolve ticket.** Use `ticketId` param, else read `.aiflow/context/current.json`. If none, use a descriptive slug for `[ticket-id]`.
56
+ 3. **Read inputs** (any that exist):
57
+ - `<planDir>/[ticket-id]/requirement.md` (Gate 1)
58
+ - `<planDir>/[ticket-id]/plan.md` (Gate 2)
59
+ - business-logic doc (path provided by user or pasted)
60
+ - tester's draft (text after `---`)
61
+ - `custom/rules/test-patterns.md`
62
+ 4. **Require `baseUrl`.** If missing, ask before continuing.
63
+ 5. If NO testcase draft is provided, that's fine — derive test cases from the requirement + business-logic docs (this is the primary value).
64
+
65
+ ---
66
+
67
+ ## Phase 2 — Analyze (GATE 1)
68
+
69
+ Produce a structured test case list:
70
+
71
+ ```
72
+ ## Test Cases — [Feature Name]
73
+
74
+ | ID | Test case | Steps | Expected Result |
75
+ |------|--------------------------------|------------------------------------------------|----------------------------------|
76
+ | TC01 | Đăng nhập thành công | 1. /login 2. Nhập email+pass hợp lệ 3. Submit | Redirect /dashboard |
77
+ | TC02 | Sai mật khẩu | 1. /login 2. Sai password 3. Submit | Hiện error message |
78
+ | TC03 | Validation email trống | 1. /login 2. Submit ngay | "Email là bắt buộc" |
79
+ ```
80
+
81
+ > ⚠️ **GATE — STOP HERE.** Show the list and ask:
82
+ > "Danh sách test cases trên có đúng không? Thêm/sửa/xóa gì không? Xác nhận để tôi khám phá app và sinh code."
83
+ >
84
+ > **Wait for confirmation before Phase 3.** Do not explore or generate code until confirmed.
85
+
86
+ ---
87
+
88
+ ## Phase 3 — Explore (Playwright MCP, live browser)
89
+
90
+ Only if `explore: true` AND the Playwright MCP server is available AND the app is reachable.
91
+
92
+ For each test case, drive the real app:
93
+ 1. `browser_navigate(baseUrl + path)` — open the page
94
+ 2. `browser_snapshot()` — read the accessibility tree; **extract real selectors** (prefer `getByRole` → `getByLabel` → `getByTestId`)
95
+ 3. Walk the flow (type, click) to confirm it behaves as the test case expects
96
+ 4. `browser_take_screenshot()` → save to `<evidenceDir>/[ticket-id]/TC<NN>-step<N>.png`
97
+ 5. Record the verified selectors for Phase 4
98
+
99
+ **Output of this phase:** a selector map (element → verified locator) + evidence screenshots.
100
+
101
+ > Do NOT commit the MCP session. The committable artifact is produced in Phase 4.
102
+
103
+ ### Fallback
104
+ If `explore: false`, MCP unavailable, or the app is unreachable:
105
+ - Generate from inference (v1 behavior)
106
+ - **Warn clearly** that selectors are unverified and a developer must check them
107
+ - Skip evidence capture
108
+
109
+ ---
110
+
111
+ ## Phase 4 — Generate (durable scripts)
112
+
113
+ Write files under the `e2e` path from `repos.json`:
114
+
115
+ ```
116
+ <e2e>/
117
+ ├── pages/
118
+ │ ├── BasePage.ts ← only if missing (template below)
119
+ │ └── [Feature]Page.ts ← Page Object; selectors from Phase 3
120
+ ├── specs/[ticket-id]/[feature].spec.ts
121
+ ├── fixtures/test.ts ← only if missing
122
+ └── playwright.config.ts ← only if missing (template below)
123
+ ```
124
+
125
+ **Rules:**
126
+ - `BasePage.ts` / `playwright.config.ts` / `fixtures/test.ts` — create only if absent. Templates at `.claude/skills/automation-testing/templates/`.
127
+ - **Page Object** — declare locators using verified selectors from Phase 3 (`getByRole` > `getByLabel` > `getByTestId`; avoid CSS/XPath unless unavoidable). One async method per action.
128
+ - **Spec** — one `test()` per case; group with `test.describe`; test ids MUST match Phase 2 (TC01, TC02…); explicit `expect` assertions.
129
+ - Apply patterns from `custom/rules/test-patterns.md` where relevant.
130
+
131
+ ---
132
+
133
+ ## Phase 5 — Run & Report
134
+
135
+ ### If `autoRun: true`
136
+ 1. Determine the target repo for E2E (per §Git below) and `cd` there.
137
+ 2. Run `npx playwright test <e2e>/specs/[ticket-id]/` (add `--headed` if `headed: true`).
138
+ 3. On completion: `npx playwright show-report` (or report the HTML path).
139
+ 4. Summarize: pass/fail count, failed-test screenshots, plus the Phase 3 exploration evidence folder.
140
+
141
+ ### If `autoRun: false`
142
+ Print manual instructions:
143
+ ```
144
+ ✅ Scripts generated.
145
+ npx playwright test # all
146
+ npx playwright test <e2e>/specs/[ticket-id]/ # this ticket
147
+ npx playwright test --headed # show browser
148
+ npx playwright show-report # HTML report
149
+ ```
150
+
151
+ ---
152
+
153
+ ## Git & Gate 5 (multi-repo)
154
+
155
+ The parent workspace is usually NOT a git repo. Commit to the **repo that owns the code under test**:
156
+
157
+ | Artifact | Commit target |
158
+ |----------|---------------|
159
+ | E2E tests for UI | the **frontend** repo (`<frontend>/e2e/`) — unless a dedicated `e2e` repo exists |
160
+ | requirement.md / plan.md | `<planDir>` at parent level (shared; not committed into a sub-repo) |
161
+
162
+ > When creating a PR (aiflow Gate 5 / `requesting-code-review`), `cd` into the correct sub-repo first — `git`/PR commands must run inside that repo, not the parent cwd.
163
+
164
+ ---
165
+
166
+ ## Two mandatory gates
167
+ 1. After Phase 2 — confirm the test case list before exploring/generating.
168
+ 2. After Phase 5 — hand off (evidence + report) and ask the developer to review before commit/PR.
@@ -0,0 +1,30 @@
1
+ import { Page, expect } from '@playwright/test';
2
+
3
+ /**
4
+ * BasePage — shared helpers for all Page Objects.
5
+ * Generated by the aiflow `automation-testing` skill. Create once; extend per feature.
6
+ */
7
+ export abstract class BasePage {
8
+ constructor(protected readonly page: Page) {}
9
+
10
+ /** Navigate to a path relative to playwright.config `baseURL`. */
11
+ async navigate(path = '/'): Promise<void> {
12
+ await this.page.goto(path);
13
+ await this.waitForLoad();
14
+ }
15
+
16
+ /** Wait until network is idle (page settled). */
17
+ async waitForLoad(): Promise<void> {
18
+ await this.page.waitForLoadState('networkidle');
19
+ }
20
+
21
+ /** Capture a full-page screenshot as evidence. */
22
+ async screenshot(name: string): Promise<void> {
23
+ await this.page.screenshot({ path: `evidence/${name}.png`, fullPage: true });
24
+ }
25
+
26
+ /** Assert the current URL matches (string or RegExp). */
27
+ async expectUrl(url: string | RegExp): Promise<void> {
28
+ await expect(this.page).toHaveURL(url);
29
+ }
30
+ }
@@ -0,0 +1,21 @@
1
+ import { defineConfig, devices } from '@playwright/test';
2
+
3
+ /**
4
+ * Playwright config generated by the aiflow `automation-testing` skill.
5
+ * Create once per target repo; edit to fit your environment.
6
+ */
7
+ export default defineConfig({
8
+ testDir: './specs',
9
+ fullyParallel: false,
10
+ retries: process.env.CI ? 1 : 0,
11
+ reporter: [['html', { open: 'never' }], ['list']],
12
+ use: {
13
+ baseURL: process.env.BASE_URL || 'http://localhost:3000',
14
+ trace: 'on-first-retry',
15
+ screenshot: 'only-on-failure',
16
+ video: 'retain-on-failure',
17
+ },
18
+ projects: [
19
+ { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
20
+ ],
21
+ });
@@ -0,0 +1,8 @@
1
+ {
2
+ "_comment": "Workspace map for the automation-testing skill. Copied to .aiflow/repos.json. Paths are relative to the parent workspace folder (aiflow cwd). Adjust to match your layout.",
3
+ "backend": "./backend",
4
+ "frontend": "./frontend",
5
+ "e2e": "./frontend/e2e",
6
+ "planDir": "./plan",
7
+ "evidenceDir": "./frontend/e2e/evidence"
8
+ }