Skip to content

Commit fec4c4e

Browse files
[docs] Add comprehensive documentation for browser tests (#3942)
Co-authored-by: filtered <[email protected]>
1 parent 49d32f4 commit fec4c4e

File tree

1 file changed

+233
-8
lines changed

1 file changed

+233
-8
lines changed

browser_tests/README.md

Lines changed: 233 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Playwright Testing for ComfyUI_frontend
22

3-
This document outlines the setup and usage of Playwright for testing the ComfyUI_frontend project.
3+
This document outlines the setup, usage, and common patterns for Playwright browser tests in the ComfyUI_frontend project.
44

55
## WARNING
66

@@ -31,7 +31,7 @@ If you are running Playwright tests in parallel or running the same test multipl
3131

3232
## Running Tests
3333

34-
There are two ways to run the tests:
34+
There are multiple ways to run the tests:
3535

3636
1. **Headless mode with report generation:**
3737
```bash
@@ -47,14 +47,239 @@ There are two ways to run the tests:
4747

4848
![Playwright UI Mode](https://github.com/user-attachments/assets/6a1ebef0-90eb-4157-8694-f5ee94d03755)
4949

50+
3. **Running specific tests:**
51+
```bash
52+
npx playwright test widget.spec.ts
53+
```
54+
55+
## Test Structure
56+
57+
Browser tests in this project follow a specific organization pattern:
58+
59+
- **Fixtures**: Located in `fixtures/` - These provide test setup and utilities
60+
- `ComfyPage.ts` - The main fixture for interacting with ComfyUI
61+
- `ComfyMouse.ts` - Utility for mouse interactions with the canvas
62+
- Components fixtures in `fixtures/components/` - Page object models for UI components
63+
64+
- **Tests**: Located in `tests/` - The actual test specifications
65+
- Organized by functionality (e.g., `widget.spec.ts`, `interaction.spec.ts`)
66+
- Snapshot directories (e.g., `widget.spec.ts-snapshots/`) contain reference screenshots
67+
68+
- **Utilities**: Located in `utils/` - Common utility functions
69+
- `litegraphUtils.ts` - Utilities for working with LiteGraph nodes
70+
71+
## Writing Effective Tests
72+
73+
When writing new tests, follow these patterns:
74+
75+
### Test Structure
76+
77+
```typescript
78+
// Import the test fixture
79+
import { comfyPageFixture as test } from '../fixtures/ComfyPage';
80+
81+
test.describe('Feature Name', () => {
82+
// Set up test environment if needed
83+
test.beforeEach(async ({ comfyPage }) => {
84+
// Common setup
85+
});
86+
87+
test('should do something specific', async ({ comfyPage }) => {
88+
// Test implementation
89+
});
90+
});
91+
```
92+
93+
### Leverage Existing Fixtures and Helpers
94+
95+
Always check for existing helpers and fixtures before implementing new ones:
96+
97+
- **ComfyPage**: Main fixture with methods for canvas interaction and node management
98+
- **ComfyMouse**: Helper for precise mouse operations on the canvas
99+
- **Helpers**: Check `browser_tests/helpers/` for specialized helpers like:
100+
- `actionbar.ts`: Interact with the action bar
101+
- `manageGroupNode.ts`: Group node management operations
102+
- `templates.ts`: Template workflows operations
103+
- **Component Fixtures**: Check `browser_tests/fixtures/components/` for UI component helpers
104+
- **Utility Functions**: Check `browser_tests/utils/` and `browser_tests/fixtures/utils/` for shared utilities
105+
106+
Most common testing needs are already addressed by these helpers, which will make your tests more consistent and reliable.
107+
108+
### Key Testing Patterns
109+
110+
1. **Focus elements explicitly**:
111+
Canvas-based elements often need explicit focus before interaction:
112+
```typescript
113+
// Click the canvas first to focus it before pressing keys
114+
await comfyPage.canvas.click();
115+
await comfyPage.page.keyboard.press('a');
116+
```
117+
118+
2. **Mark canvas as dirty if needed**:
119+
Some interactions need explicit canvas updates:
120+
```typescript
121+
// After programmatically changing node state, mark canvas dirty
122+
await comfyPage.page.evaluate(() => {
123+
window['app'].graph.setDirtyCanvas(true, true);
124+
});
125+
```
126+
127+
3. **Use node references over coordinates**:
128+
Node references from `fixtures/utils/litegraphUtils.ts` provide stable ways to interact with nodes:
129+
```typescript
130+
// Prefer this:
131+
const node = await comfyPage.getNodeRefsByType('LoadImage')[0];
132+
await node.click('title');
133+
134+
// Over this:
135+
await comfyPage.canvas.click({ position: { x: 100, y: 100 } });
136+
```
137+
138+
4. **Wait for canvas to render after UI interactions**:
139+
```typescript
140+
await comfyPage.nextFrame();
141+
```
142+
143+
5. **Clean up persistent server state**:
144+
While most state is reset between tests, anything stored on the server persists:
145+
```typescript
146+
// Reset settings that affect other tests (these are stored on server)
147+
await comfyPage.setSetting('Comfy.ColorPalette', 'dark');
148+
await comfyPage.setSetting('Comfy.NodeBadge.NodeIdBadgeMode', 'None');
149+
150+
// Clean up uploaded files if needed
151+
await comfyPage.request.delete(`${comfyPage.url}/api/delete/image.png`);
152+
```
153+
154+
6. **Prefer functional assertions over screenshots**:
155+
Use screenshots only when visual verification is necessary:
156+
```typescript
157+
// Prefer this:
158+
expect(await node.isPinned()).toBe(true);
159+
expect(await node.getProperty('title')).toBe('Expected Title');
160+
161+
// Over this - only use when needed:
162+
await expect(comfyPage.canvas).toHaveScreenshot('state.png');
163+
```
164+
165+
7. **Use minimal test workflows**:
166+
When creating test workflows, keep them as minimal as possible:
167+
```typescript
168+
// Include only the components needed for the test
169+
await comfyPage.loadWorkflow('single_ksampler');
170+
```
171+
172+
## Common Patterns and Utilities
173+
174+
### Page Object Pattern
175+
176+
Tests use the Page Object pattern to create abstractions over the UI:
177+
178+
```typescript
179+
// Using the ComfyPage fixture
180+
test('Can toggle boolean widget', async ({ comfyPage }) => {
181+
await comfyPage.loadWorkflow('widgets/boolean_widget')
182+
const node = (await comfyPage.getFirstNodeRef())!
183+
const widget = await node.getWidget(0)
184+
await widget.click()
185+
});
186+
```
187+
188+
### Node References
189+
190+
The `NodeReference` class provides helpers for interacting with LiteGraph nodes:
191+
192+
```typescript
193+
// Getting node by type and interacting with it
194+
const nodes = await comfyPage.getNodeRefsByType('LoadImage')
195+
const loadImageNode = nodes[0]
196+
const widget = await loadImageNode.getWidget(0)
197+
await widget.click()
198+
```
199+
200+
### Visual Regression Testing
201+
202+
Tests use screenshot comparisons to verify UI state:
203+
204+
```typescript
205+
// Take a screenshot and compare to reference
206+
await expect(comfyPage.canvas).toHaveScreenshot('boolean_widget_toggled.png')
207+
```
208+
209+
### Waiting for Animations
210+
211+
Always call `nextFrame()` after actions that trigger animations:
212+
213+
```typescript
214+
await comfyPage.canvas.click({ position: { x: 100, y: 100 } })
215+
await comfyPage.nextFrame() // Wait for canvas to redraw
216+
```
217+
218+
### Mouse Interactions
219+
220+
Canvas operations use special helpers to ensure proper timing:
221+
222+
```typescript
223+
// Using ComfyMouse for drag and drop
224+
await comfyMouse.dragAndDrop(
225+
{ x: 100, y: 100 }, // From
226+
{ x: 200, y: 200 } // To
227+
)
228+
229+
// Standard ComfyPage helpers
230+
await comfyPage.drag({ x: 100, y: 100 }, { x: 200, y: 200 })
231+
await comfyPage.pan({ x: 200, y: 200 })
232+
await comfyPage.zoom(-100) // Zoom in
233+
```
234+
235+
### Workflow Management
236+
237+
Tests use workflows stored in `assets/` for consistent starting points:
238+
239+
```typescript
240+
// Load a test workflow
241+
await comfyPage.loadWorkflow('single_ksampler')
242+
243+
// Wait for workflow to load and stabilize
244+
await comfyPage.nextFrame()
245+
```
246+
247+
### Custom Assertions
248+
249+
The project includes custom Playwright assertions through `comfyExpect`:
250+
251+
```typescript
252+
// Check if a node is in a specific state
253+
await expect(node).toBePinned()
254+
await expect(node).toBeBypassed()
255+
await expect(node).toBeCollapsed()
256+
```
257+
258+
## Troubleshooting Common Issues
259+
260+
### Flaky Tests
261+
262+
- **Timing Issues**: Always wait for animations to complete with `nextFrame()`
263+
- **Coordinate Sensitivity**: Canvas coordinates are viewport-relative; use node references when possible
264+
- **Test Isolation**: Tests run in parallel; avoid dependencies between tests
265+
- **Screenshots vary**: Ensure your OS and browser match the reference environment (Linux)
266+
- **Async / await**: Race conditions are a very common cause of test flakiness
267+
50268
## Screenshot Expectations
51269

52270
Due to variations in system font rendering, screenshot expectations are platform-specific. Please note:
53271

54-
- We maintain Linux screenshot expectations as our GitHub Action runner operates in a Linux environment.
55-
- To set new test expectations:
56-
1. Create a pull request from a `Comfy-Org/ComfyUI_frontend` branch.
57-
2. Add the `New Browser Test Expectation` tag to your pull request.
58-
3. This will trigger a GitHub action to update the screenshot expectations automatically.
272+
- **DO NOT commit local screenshot expectations** to the repository
273+
- We maintain Linux screenshot expectations as our GitHub Action runner operates in a Linux environment
274+
- While developing, you can generate local screenshots for your tests, but these will differ from CI-generated ones
275+
276+
To set new test expectations for PR:
277+
278+
1. Write your test with screenshot assertions using `toHaveScreenshot(filename)`
279+
2. Create a pull request from a `Comfy-Org/ComfyUI_frontend` branch
280+
3. Add the `New Browser Test Expectation` tag to your pull request
281+
4. The GitHub CI will automatically generate and commit the reference screenshots
282+
283+
This approach ensures consistent screenshot expectations across all PRs and avoids issues with platform-specific rendering.
59284

60-
> **Note:** If you're making a pull request from a forked repository, the GitHub action won't be able to commit updated screenshot expectations directly to your PR branch.
285+
> **Note:** If you're making a pull request from a forked repository, the GitHub action won't be able to commit updated screenshot expectations directly to your PR branch.

0 commit comments

Comments
 (0)