[automated] Apply ESLint and Oxfmt fixes

This commit is contained in:
GitHub Action
2026-03-29 02:04:04 +00:00
committed by bymyself
parent a1c9fc38be
commit da86590eeb
8 changed files with 128 additions and 97 deletions

View File

@@ -11,6 +11,7 @@ Your specialty is creating robust, reliable Playwright tests that accurately sim
application behavior.
# For each test you generate
- Obtain the test plan with all the steps and verification specification
- Run the `generator_setup_page` tool to set up page for the scenario
- For each step and verification in the scenario, do the following:
@@ -29,38 +30,44 @@ application behavior.
<example-generation>
For following plan:
```markdown file=specs/plan.md
### 1. Adding New Todos
**Seed:** `tests/seed.spec.ts`
```markdown file=specs/plan.md
### 1. Adding New Todos
#### 1.1 Add Valid Todo
**Steps:**
1. Click in the "What needs to be done?" input field
**Seed:** `tests/seed.spec.ts`
#### 1.2 Add Multiple Todos
...
```
#### 1.1 Add Valid Todo
Following file is generated:
**Steps:**
```ts file=add-valid-todo.spec.ts
// spec: specs/plan.md
// seed: tests/seed.spec.ts
1. Click in the "What needs to be done?" input field
test.describe('Adding New Todos', () => {
test('Add Valid Todo', async { page } => {
// 1. Click in the "What needs to be done?" input field
await page.click(...);
#### 1.2 Add Multiple Todos
...
```
Following file is generated:
```ts file=add-valid-todo.spec.ts
// spec: specs/plan.md
// seed: tests/seed.spec.ts
test.describe('Adding New Todos', () => {
test('Add Valid Todo', async { page } => {
// 1. Click in the "What needs to be done?" input field
await page.click(...);
...
});
});
```
...
});
});
```
</example-generation>
## ComfyUI Project Context
### Required Import Pattern
Generated tests MUST use ComfyUI fixtures, not generic `@playwright/test`:
```typescript
@@ -71,6 +78,7 @@ import {
```
### Fixture Object
Tests receive `comfyPage` (not `page`) as their fixture:
```typescript
@@ -80,32 +88,38 @@ test('my test', async ({ comfyPage }) => {
```
### Key APIs
| Need | Use | Notes |
|------|-----|-------|
| Canvas element | `comfyPage.canvas` | Pre-configured Locator |
| Wait for render | `comfyPage.nextFrame()` | After canvas mutations |
| Load workflow | `comfyPage.workflow.loadWorkflow('name')` | Assets in `browser_tests/assets/` |
| Get node by type | `comfyPage.nodeOps.getNodeRefsByType('KSampler')` | Returns NodeReference[] |
| Search box | `comfyPage.searchBox.fillAndSelectFirstNode('name')` | Opens on canvas dblclick |
| Settings | `comfyPage.settings.setSetting(key, value)` | Clean up in afterEach |
| Keyboard | `comfyPage.keyboard.press('Delete')` | Focus canvas first |
| Context menu | `comfyPage.contextMenu` | Right-click interactions |
| Need | Use | Notes |
| ---------------- | ---------------------------------------------------- | --------------------------------- |
| Canvas element | `comfyPage.canvas` | Pre-configured Locator |
| Wait for render | `comfyPage.nextFrame()` | After canvas mutations |
| Load workflow | `comfyPage.workflow.loadWorkflow('name')` | Assets in `browser_tests/assets/` |
| Get node by type | `comfyPage.nodeOps.getNodeRefsByType('KSampler')` | Returns NodeReference[] |
| Search box | `comfyPage.searchBox.fillAndSelectFirstNode('name')` | Opens on canvas dblclick |
| Settings | `comfyPage.settings.setSetting(key, value)` | Clean up in afterEach |
| Keyboard | `comfyPage.keyboard.press('Delete')` | Focus canvas first |
| Context menu | `comfyPage.contextMenu` | Right-click interactions |
### Mandatory Test Structure
Every generated test must:
1. Be wrapped in `test.describe('Name', { tag: ['@canvas'] }, () => { ... })`
2. Include `test.afterEach(async ({ comfyPage }) => { await comfyPage.canvasOps.resetView() })`
3. Use descriptive test names (not "test" or "test1")
### Anti-Patterns — NEVER Use
- ❌ `page.goto()` — fixture handles navigation
- ❌ `page.waitForTimeout()` — use `comfyPage.nextFrame()` or retrying assertions
- ❌ `import from '@playwright/test'` — use `from '../fixtures/ComfyPage'`
- ❌ Bare `page.` references — use `comfyPage.page.` if you need raw page access
### Reference
Read the fixture code for full API surface:
- `browser_tests/fixtures/ComfyPage.ts` — main fixture
- `browser_tests/fixtures/helpers/` — helper classes
- `browser_tests/fixtures/components/` — page object components
- See also: `.claude/skills/codegen-transform/SKILL.md` for transform rules
- See also: `.claude/skills/codegen-transform/SKILL.md` for transform rules

View File

@@ -11,6 +11,7 @@ resolving Playwright test failures. Your mission is to systematically identify,
broken Playwright tests using a methodical approach.
Your workflow:
1. **Initial Execution**: Run all tests using `test_run` tool to identify failing tests
2. **Debug failed tests**: For each failing test run `test_debug`.
3. **Error Investigation**: When the test pauses on errors, use available Playwright MCP tools to:
@@ -31,6 +32,7 @@ Your workflow:
7. **Iteration**: Repeat the investigation and fixing process until the test passes cleanly
Key principles:
- Be systematic and thorough in your debugging approach
- Document your findings and reasoning for each fix
- Prefer robust, maintainable solutions over quick hacks
@@ -48,7 +50,9 @@ Key principles:
## ComfyUI Project Context
### Custom Fixtures
Tests in this project use `comfyPage` fixture, not bare `page`. When healing:
- Replace any `page.` references with `comfyPage.page.` if adding new code
- Use `comfyPage.nextFrame()` instead of adding `waitForTimeout()`
- Use fixture helpers (`comfyPage.nodeOps`, `comfyPage.canvas`, etc.) over raw locators
@@ -60,6 +64,7 @@ Tests in this project use `comfyPage` fixture, not bare `page`. When healing:
2. **Canvas focus required**: Keyboard shortcuts won't work unless `await comfyPage.canvas.click()` is called first.
3. **Node position drift**: Pixel coordinates can shift between environments. When possible, replace with node references:
```typescript
// Instead of: canvas.click({ position: { x: 423, y: 267 } })
const node = (await comfyPage.nodeOps.getNodeRefsByType('KSampler'))[0]
@@ -71,6 +76,7 @@ Tests in this project use `comfyPage` fixture, not bare `page`. When healing:
5. **Drag animation timing**: Use `{ steps: 10 }` option for drag operations, not `{ steps: 1 }`.
### Healing Safety Rules
- ❌ NEVER add `waitForTimeout()` — always use retrying assertions or `nextFrame()`
- ❌ NEVER "fix" a test by weakening assertions (e.g., removing an assertion that fails)
- ❌ NEVER modify the application code — only modify test code
@@ -78,7 +84,8 @@ Tests in this project use `comfyPage` fixture, not bare `page`. When healing:
- ⚠️ If a test fails only in CI but passes locally, likely missing `nextFrame()` — don't mask with timeouts
### Reference
- `browser_tests/fixtures/ComfyPage.ts` — full fixture API
- `browser_tests/fixtures/helpers/` — available helper classes
- `.claude/skills/writing-playwright-tests/SKILL.md` — testing conventions
- `.claude/skills/codegen-transform/SKILL.md` — transform rules
- `.claude/skills/codegen-transform/SKILL.md` — transform rules

View File

@@ -44,6 +44,7 @@ You will:
Submit your test plan using `planner_save_plan` tool.
**Quality Standards**:
- Write steps that are specific enough for any tester to follow
- Include negative testing scenarios
- Ensure scenarios are independent and can be run in any order
@@ -54,7 +55,9 @@ professional formatting suitable for sharing with development and QA teams.
## ComfyUI Project Context
### Application Overview
ComfyUI is a **canvas-based node graph editor** for AI image generation. It is a complex SPA with:
- A **LiteGraph canvas** where users create workflows by connecting nodes
- A **Vue 3 sidebar** with node library, workflows panel, and settings
- A **topbar** with queue/run buttons and workspace controls
@@ -62,6 +65,7 @@ ComfyUI is a **canvas-based node graph editor** for AI image generation. It is a
- WebSocket-based real-time communication with a Python backend
### Exploration Tips
- Start by loading a workflow: the app is most useful with nodes on the canvas
- Key UI areas to explore: canvas interactions, sidebar panels, topbar buttons, search box, context menus, settings dialog
- Double-click the canvas to open the node search box
@@ -69,6 +73,7 @@ ComfyUI is a **canvas-based node graph editor** for AI image generation. It is a
- The bottom panel shows job queue and execution logs
### Test Environment
- The seed test uses `comfyPageFixture` which provides a `comfyPage` object with extensive helpers
- Workflows (JSON files) are loaded via `comfyPage.workflow.loadWorkflow('name')`
- Available workflow assets are in `browser_tests/assets/`
@@ -76,8 +81,9 @@ ComfyUI is a **canvas-based node graph editor** for AI image generation. It is a
- A Vite dev server runs on `:5173`
### When Creating Test Plans
- Reference specific workflow assets when a scenario needs a starting state
- Note that canvas interactions use pixel coordinates — these may vary across environments
- Distinguish between "canvas tests" (LiteGraph) and "UI tests" (Vue components)
- Include tags in your plans: `@canvas`, `@widget`, `@sidebar`, `@smoke`, `@screenshot`
- Reference `browser_tests/fixtures/ComfyPage.ts` for available test helpers
- Reference `browser_tests/fixtures/ComfyPage.ts` for available test helpers

View File

@@ -18,39 +18,39 @@ Transform raw Playwright codegen output into tests that follow ComfyUI conventio
Apply these replacements in order:
| Raw codegen | Convention replacement | Why |
|---|---|---|
| Raw codegen | Convention replacement | Why |
| ------------------------------------------------- | ----------------------------------------------------------------------------------------- | ---------------------------------------- |
| `import { test, expect } from '@playwright/test'` | `import { comfyPageFixture as test, comfyExpect as expect } from '../fixtures/ComfyPage'` | Use custom fixtures with ComfyUI helpers |
| `test('test', async ({ page }) =>` | `test('descriptive-name', async ({ comfyPage }) =>` | Use comfyPage fixture, descriptive names |
| `await page.goto('http://...')` | **Remove entirely** | Fixture handles navigation automatically |
| `page.locator('canvas')` | `comfyPage.canvas` | Pre-configured canvas locator |
| `page.waitForTimeout(N)` | `comfyPage.nextFrame()` | Never use arbitrary waits |
| `page.getByPlaceholder('Search Nodes...')` | `comfyPage.searchBox.input` | Use search box page object |
| `page` (bare reference) | `comfyPage.page` | Access raw page through fixture |
| Bare `test(...)` | `test.describe('Feature', { tag: ['@canvas'] }, () => { test(...) })` | All tests need describe + tags |
| No cleanup | Add `test.afterEach(async ({ comfyPage }) => { await comfyPage.canvasOps.resetView() })` | Canvas tests need cleanup |
| `test('test', async ({ page }) =>` | `test('descriptive-name', async ({ comfyPage }) =>` | Use comfyPage fixture, descriptive names |
| `await page.goto('http://...')` | **Remove entirely** | Fixture handles navigation automatically |
| `page.locator('canvas')` | `comfyPage.canvas` | Pre-configured canvas locator |
| `page.waitForTimeout(N)` | `comfyPage.nextFrame()` | Never use arbitrary waits |
| `page.getByPlaceholder('Search Nodes...')` | `comfyPage.searchBox.input` | Use search box page object |
| `page` (bare reference) | `comfyPage.page` | Access raw page through fixture |
| Bare `test(...)` | `test.describe('Feature', { tag: ['@canvas'] }, () => { test(...) })` | All tests need describe + tags |
| No cleanup | Add `test.afterEach(async ({ comfyPage }) => { await comfyPage.canvasOps.resetView() })` | Canvas tests need cleanup |
## Fixture API Quick Reference
| Need | Use | Notes |
|------|-----|-------|
| Canvas element | `comfyPage.canvas` | Pre-configured Locator |
| Wait for render | `comfyPage.nextFrame()` | After canvas mutations. NOT needed after `loadWorkflow()` |
| Load workflow | `comfyPage.workflow.loadWorkflow('name')` | Assets in `browser_tests/assets/` |
| Get node by type | `comfyPage.nodeOps.getNodeRefsByType('KSampler')` | Returns array of NodeReference |
| Get node by title | `comfyPage.nodeOps.getNodeRefsByTitle('My Node')` | Returns array of NodeReference |
| Search box | `comfyPage.searchBox` | Has `.input`, `.fillAndSelectFirstNode()` |
| Settings | `comfyPage.settings.setSetting(key, value)` | Persistent — clean up in afterEach |
| Keyboard | `comfyPage.keyboard.press('Delete')` | Focus canvas first |
| Drag & drop | `comfyPage.dragDrop.*` | Use `{ steps: 10 }` for reliability |
| Context menu | `comfyPage.contextMenu.*` | Right-click interactions |
| Toast messages | `comfyPage.toast.*` | Notification assertions |
| Subgraph | `comfyPage.subgraph.*` | Subgraph/group node operations |
| Vue Nodes | `comfyPage.vueNodes.*` | Requires opt-in: `setSetting('Comfy.VueNodes.Enabled', true)` |
| Mouse ops | `comfyPage.page` + `ComfyMouse` | For precise canvas mouse interactions |
| Bottom panel | `comfyPage.bottomPanel.*` | Job queue, logs panel |
| Commands | `comfyPage.command.*` | Command palette interactions |
| Clipboard | `comfyPage.clipboard.*` | Copy/paste operations |
| Need | Use | Notes |
| ----------------- | ------------------------------------------------- | ------------------------------------------------------------- |
| Canvas element | `comfyPage.canvas` | Pre-configured Locator |
| Wait for render | `comfyPage.nextFrame()` | After canvas mutations. NOT needed after `loadWorkflow()` |
| Load workflow | `comfyPage.workflow.loadWorkflow('name')` | Assets in `browser_tests/assets/` |
| Get node by type | `comfyPage.nodeOps.getNodeRefsByType('KSampler')` | Returns array of NodeReference |
| Get node by title | `comfyPage.nodeOps.getNodeRefsByTitle('My Node')` | Returns array of NodeReference |
| Search box | `comfyPage.searchBox` | Has `.input`, `.fillAndSelectFirstNode()` |
| Settings | `comfyPage.settings.setSetting(key, value)` | Persistent — clean up in afterEach |
| Keyboard | `comfyPage.keyboard.press('Delete')` | Focus canvas first |
| Drag & drop | `comfyPage.dragDrop.*` | Use `{ steps: 10 }` for reliability |
| Context menu | `comfyPage.contextMenu.*` | Right-click interactions |
| Toast messages | `comfyPage.toast.*` | Notification assertions |
| Subgraph | `comfyPage.subgraph.*` | Subgraph/group node operations |
| Vue Nodes | `comfyPage.vueNodes.*` | Requires opt-in: `setSetting('Comfy.VueNodes.Enabled', true)` |
| Mouse ops | `comfyPage.page` + `ComfyMouse` | For precise canvas mouse interactions |
| Bottom panel | `comfyPage.bottomPanel.*` | Job queue, logs panel |
| Commands | `comfyPage.command.*` | Command palette interactions |
| Clipboard | `comfyPage.clipboard.*` | Copy/paste operations |
## Canvas Coordinates → Node References
@@ -127,28 +127,28 @@ test.describe('Queue workflow with KSampler', { tag: ['@canvas'] }, () => {
## Decision Guide
| Question | Answer |
|----------|--------|
| Canvas or DOM interaction? | Canvas: `comfyPage.nodeOps.*`. DOM: `comfyPage.vueNodes.*` (needs opt-in) |
| Need `nextFrame()`? | Yes after canvas mutations. No after `loadWorkflow()`, no after DOM clicks |
| Which tag? | `@canvas` for canvas tests, `@widget` for widget tests, `@screenshot` for visual regression |
| Need cleanup? | Yes for canvas tests (`resetView`), yes if changing settings (`setSetting` back) |
| Keep pixel coords? | Only for empty canvas clicks. Replace with node refs for node interactions |
| Use `page` directly? | Only via `comfyPage.page` for Playwright APIs not wrapped by fixtures |
| Question | Answer |
| -------------------------- | ------------------------------------------------------------------------------------------- |
| Canvas or DOM interaction? | Canvas: `comfyPage.nodeOps.*`. DOM: `comfyPage.vueNodes.*` (needs opt-in) |
| Need `nextFrame()`? | Yes after canvas mutations. No after `loadWorkflow()`, no after DOM clicks |
| Which tag? | `@canvas` for canvas tests, `@widget` for widget tests, `@screenshot` for visual regression |
| Need cleanup? | Yes for canvas tests (`resetView`), yes if changing settings (`setSetting` back) |
| Keep pixel coords? | Only for empty canvas clicks. Replace with node refs for node interactions |
| Use `page` directly? | Only via `comfyPage.page` for Playwright APIs not wrapped by fixtures |
## Tags Reference
| Tag | When to use |
|-----|-------------|
| `@canvas` | Any test interacting with the canvas |
| `@widget` | Testing widget inputs |
| `@smoke` | Quick essential tests |
| `@screenshot` | Visual regression (Linux CI only) |
| `@mobile` | Mobile viewport (runs on Pixel 5) |
| `@2x` | HiDPI tests (2x scale) |
| `@0.5x` | Low-DPI tests (0.5x scale) |
| `@slow` | Tests taking >10 seconds |
| `@perf` | Performance measurement tests |
| Tag | When to use |
| ------------- | ------------------------------------ |
| `@canvas` | Any test interacting with the canvas |
| `@widget` | Testing widget inputs |
| `@smoke` | Quick essential tests |
| `@screenshot` | Visual regression (Linux CI only) |
| `@mobile` | Mobile viewport (runs on Pixel 5) |
| `@2x` | HiDPI tests (2x scale) |
| `@0.5x` | Low-DPI tests (0.5x scale) |
| `@slow` | Tests taking >10 seconds |
| `@perf` | Performance measurement tests |
## Anti-Patterns
@@ -163,12 +163,12 @@ test.describe('Queue workflow with KSampler', { tag: ['@canvas'] }, () => {
Read fixture code directly — it's the source of truth:
| Purpose | Path |
|---------|------|
| Main fixture | `browser_tests/fixtures/ComfyPage.ts` |
| Helper classes | `browser_tests/fixtures/helpers/` |
| Component objects | `browser_tests/fixtures/components/` |
| Test selectors | `browser_tests/fixtures/selectors.ts` |
| Vue Node helpers | `browser_tests/fixtures/VueNodeHelpers.ts` |
| Existing tests | `browser_tests/tests/` |
| Test assets | `browser_tests/assets/` |
| Purpose | Path |
| ----------------- | ------------------------------------------ |
| Main fixture | `browser_tests/fixtures/ComfyPage.ts` |
| Helper classes | `browser_tests/fixtures/helpers/` |
| Component objects | `browser_tests/fixtures/components/` |
| Test selectors | `browser_tests/fixtures/selectors.ts` |
| Vue Node helpers | `browser_tests/fixtures/VueNodeHelpers.ts` |
| Existing tests | `browser_tests/tests/` |
| Test assets | `browser_tests/assets/` |

View File

@@ -56,11 +56,11 @@ This project uses **pnpm**. Always prefer scripts defined in `package.json` (e.g
### Playwright Test Agents (`.claude/agents/`)
| Agent | Responsibility |
|-------|---------------|
| `playwright-test-planner.md` | Explores the app, identifies testable scenarios, creates structured test plans |
| `playwright-test-generator.md` | Generates Playwright test code from plans using ComfyUI fixtures and conventions |
| `playwright-test-healer.md` | Diagnoses and fixes failing tests; escalates regressions rather than auto-skipping |
| Agent | Responsibility |
| ------------------------------ | ---------------------------------------------------------------------------------- |
| `playwright-test-planner.md` | Explores the app, identifies testable scenarios, creates structured test plans |
| `playwright-test-generator.md` | Generates Playwright test code from plans using ComfyUI fixtures and conventions |
| `playwright-test-healer.md` | Diagnoses and fixes failing tests; escalates regressions rather than auto-skipping |
Guardrails: agents must use `comfyPage` fixture (not bare `page`), never add `waitForTimeout()`, never weaken assertions, and reference `.claude/skills/codegen-transform/SKILL.md` for transform rules.

View File

@@ -133,6 +133,7 @@ Source: `tools/test-recorder/`
For AI agents transforming raw Playwright codegen output. See `.claude/skills/codegen-transform/SKILL.md`.
Key transforms:
- `@playwright/test``../fixtures/ComfyPage` imports
- `page` destructure → `comfyPage` fixture
- `page.goto()` → removed (fixture handles navigation)
@@ -153,6 +154,7 @@ To regenerate after Playwright updates: `bash scripts/update-playwright-agents.s
### MCP Server
The `.mcp.json` configures `playwright-test` MCP server for agent browser interaction:
```bash
pnpm exec playwright run-test-mcp-server
```

View File

@@ -79,6 +79,7 @@ pnpm comfy-test record
```
This guides you through a 7-step flow:
1. **Environment check** — verifies all tools are installed (with install instructions if not)
2. **Project setup** — installs dependencies
3. **Backend check** — ensures ComfyUI is running
@@ -88,6 +89,7 @@ This guides you through a 7-step flow:
7. **PR creation** — creates a PR via `gh` CLI or gives manual instructions
Other commands:
```bash
pnpm comfy-test check # Just run environment checks
pnpm comfy-test transform <file> # Transform a raw codegen file

View File

@@ -3,10 +3,10 @@
"version": "0.1.0",
"private": true,
"description": "Interactive CLI for recording and transforming Playwright browser tests",
"type": "module",
"bin": {
"comfy-test": "./dist/index.js"
},
"type": "module",
"scripts": {
"build": "tsc",
"dev": "tsc --watch",