creevey 0.10.0-beta.43 → 0.10.0-beta.45
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/CHANGELOG.md +282 -0
- package/dist/client/addon/controller.js +1 -1
- package/dist/client/addon/controller.js.map +1 -1
- package/dist/client/addon/withCreevey.js +1 -18
- package/dist/client/addon/withCreevey.js.map +1 -1
- package/dist/client/shared/components/PageHeader/PageHeader.js +13 -4
- package/dist/client/shared/components/PageHeader/PageHeader.js.map +1 -1
- package/dist/client/shared/creeveyClientApi.js +10 -0
- package/dist/client/shared/creeveyClientApi.js.map +1 -1
- package/dist/client/web/CreeveyApp.d.ts +1 -0
- package/dist/client/web/CreeveyApp.js +1 -0
- package/dist/client/web/CreeveyApp.js.map +1 -1
- package/dist/client/web/CreeveyContext.d.ts +1 -0
- package/dist/client/web/CreeveyContext.js +1 -0
- package/dist/client/web/CreeveyContext.js.map +1 -1
- package/dist/client/web/CreeveyView/SideBar/SideBarFooter.js +9 -8
- package/dist/client/web/CreeveyView/SideBar/SideBarFooter.js.map +1 -1
- package/dist/client/web/CreeveyView/SideBar/SideBarHeader.js +13 -3
- package/dist/client/web/CreeveyView/SideBar/SideBarHeader.js.map +1 -1
- package/dist/client/web/CreeveyView/SideBar/SuiteLink.js +2 -3
- package/dist/client/web/CreeveyView/SideBar/SuiteLink.js.map +1 -1
- package/dist/client/web/CreeveyView/SideBar/TestLink.js +2 -3
- package/dist/client/web/CreeveyView/SideBar/TestLink.js.map +1 -1
- package/dist/client/web/CreeveyView/SideBar/TestsStatus.js +1 -0
- package/dist/client/web/CreeveyView/SideBar/TestsStatus.js.map +1 -1
- package/dist/client/web/assets/{index-C47njyZV.js → index-BU4jjKVC.js} +68 -68
- package/dist/client/web/index.html +1 -1
- package/dist/client/web/index.js +8 -3
- package/dist/client/web/index.js.map +1 -1
- package/dist/creevey.d.ts +1 -1
- package/dist/creevey.js +1 -22
- package/dist/creevey.js.map +1 -1
- package/dist/playwright-reporter.d.ts +2 -0
- package/dist/playwright-reporter.js +5 -0
- package/dist/playwright-reporter.js.map +1 -0
- package/dist/playwright.d.ts +1 -1
- package/dist/server/config.js +8 -1
- package/dist/server/config.js.map +1 -1
- package/dist/server/index.js +12 -5
- package/dist/server/index.js.map +1 -1
- package/dist/server/master/api.d.ts +11 -6
- package/dist/server/master/api.js +88 -25
- package/dist/server/master/api.js.map +1 -1
- package/dist/server/master/handlers/capture-handler.d.ts +5 -0
- package/dist/server/master/handlers/capture-handler.js +25 -0
- package/dist/server/master/handlers/capture-handler.js.map +1 -0
- package/dist/server/master/handlers/index.d.ts +4 -0
- package/dist/server/master/handlers/index.js +21 -0
- package/dist/server/master/handlers/index.js.map +1 -0
- package/dist/server/master/handlers/ping-handler.d.ts +2 -0
- package/dist/server/master/handlers/ping-handler.js +8 -0
- package/dist/server/master/handlers/ping-handler.js.map +1 -0
- package/dist/server/master/handlers/static-handler.d.ts +1 -0
- package/dist/server/master/handlers/static-handler.js +22 -0
- package/dist/server/master/handlers/static-handler.js.map +1 -0
- package/dist/server/master/handlers/stories-handler.d.ts +4 -0
- package/dist/server/master/handlers/stories-handler.js +24 -0
- package/dist/server/master/handlers/stories-handler.js.map +1 -0
- package/dist/server/master/master.js +7 -24
- package/dist/server/master/master.js.map +1 -1
- package/dist/server/master/runner.d.ts +4 -6
- package/dist/server/master/runner.js +30 -127
- package/dist/server/master/runner.js.map +1 -1
- package/dist/server/master/server.js +191 -89
- package/dist/server/master/server.js.map +1 -1
- package/dist/server/master/start.d.ts +1 -2
- package/dist/server/master/start.js +11 -29
- package/dist/server/master/start.js.map +1 -1
- package/dist/server/master/testsManager.d.ts +81 -0
- package/dist/server/master/testsManager.js +281 -0
- package/dist/server/master/testsManager.js.map +1 -0
- package/dist/server/playwright/docker-file.js +2 -2
- package/dist/server/playwright/docker-file.js.map +1 -1
- package/dist/server/playwright/reporter.d.ts +87 -0
- package/dist/server/playwright/reporter.js +351 -0
- package/dist/server/playwright/reporter.js.map +1 -0
- package/dist/server/selenium/internal.js +20 -2
- package/dist/server/selenium/internal.js.map +1 -1
- package/dist/server/selenium/selenoid.js +4 -0
- package/dist/server/selenium/selenoid.js.map +1 -1
- package/dist/server/shutdown.d.ts +1 -0
- package/dist/server/shutdown.js +23 -0
- package/dist/server/shutdown.js.map +1 -0
- package/dist/server/stories.d.ts +0 -1
- package/dist/server/stories.js +0 -12
- package/dist/server/stories.js.map +1 -1
- package/dist/server/ui-update.d.ts +10 -0
- package/dist/server/ui-update.js +39 -0
- package/dist/server/ui-update.js.map +1 -0
- package/dist/server/utils.d.ts +6 -0
- package/dist/server/utils.js +39 -8
- package/dist/server/utils.js.map +1 -1
- package/dist/server/worker/start.js +1 -1
- package/dist/server/worker/start.js.map +1 -1
- package/dist/types.d.ts +14 -8
- package/dist/types.js.map +1 -1
- package/docs/examples/playwright-reporter-example.ts +202 -0
- package/docs/migration-0.9-to-0.10.md +144 -0
- package/docs/playwright-reporter.md +357 -0
- package/package.json +10 -14
- package/src/client/addon/controller.ts +1 -1
- package/src/client/addon/withCreevey.ts +2 -16
- package/src/client/shared/components/PageHeader/PageHeader.tsx +18 -4
- package/src/client/shared/creeveyClientApi.ts +10 -0
- package/src/client/web/CreeveyApp.tsx +2 -0
- package/src/client/web/CreeveyContext.tsx +2 -0
- package/src/client/web/CreeveyView/SideBar/SideBarFooter.tsx +19 -17
- package/src/client/web/CreeveyView/SideBar/SideBarHeader.tsx +18 -3
- package/src/client/web/CreeveyView/SideBar/SuiteLink.tsx +9 -7
- package/src/client/web/CreeveyView/SideBar/TestLink.tsx +8 -6
- package/src/client/web/CreeveyView/SideBar/TestsStatus.tsx +1 -0
- package/src/client/web/index.tsx +8 -3
- package/src/creevey.ts +1 -24
- package/src/playwright-reporter.ts +3 -0
- package/src/server/config.ts +9 -1
- package/src/server/index.ts +13 -6
- package/src/server/master/api.ts +94 -28
- package/src/server/master/handlers/capture-handler.ts +20 -0
- package/src/server/master/handlers/index.ts +4 -0
- package/src/server/master/handlers/ping-handler.ts +6 -0
- package/src/server/master/handlers/static-handler.ts +18 -0
- package/src/server/master/handlers/stories-handler.ts +20 -0
- package/src/server/master/master.ts +10 -27
- package/src/server/master/runner.ts +38 -132
- package/src/server/master/server.ts +210 -98
- package/src/server/master/start.ts +17 -41
- package/src/server/master/testsManager.ts +315 -0
- package/src/server/playwright/docker-file.ts +2 -2
- package/src/server/playwright/reporter.ts +386 -0
- package/src/server/selenium/internal.ts +23 -3
- package/src/server/selenium/selenoid.ts +5 -0
- package/src/server/shutdown.ts +19 -0
- package/src/server/stories.ts +1 -12
- package/src/server/ui-update.ts +46 -0
- package/src/server/utils.ts +40 -9
- package/src/server/worker/start.ts +1 -1
- package/src/types.ts +14 -8
@@ -0,0 +1,144 @@
|
|
1
|
+
# Migrating from Creevey 0.9 to 0.10
|
2
|
+
|
3
|
+
This guide outlines the key changes and steps required to update your Creevey setup from version 0.9 to 0.10. Version 0.10 introduces several significant updates, including Playwright support, a new test context API, and changes to configuration.
|
4
|
+
|
5
|
+
---
|
6
|
+
|
7
|
+
## Breaking Changes
|
8
|
+
|
9
|
+
### 1. Browser Configuration in `creevey.config.ts`
|
10
|
+
|
11
|
+
The way browsers are configured has been updated to better distinguish between Selenium and Playwright settings.
|
12
|
+
|
13
|
+
- The new `webdriver` field lets you choose your WebDriver implementation. While it defaults to Selenium for now, this may change. We recommend explicitly setting it by importing and using either `SeleniumWebdriver` or `PlaywrightWebdriver`.
|
14
|
+
- Selenium-specific capabilities (e.g., `browserVersion`, `platformName`) must now be nested under a `seleniumCapabilities` object.
|
15
|
+
- Playwright-specific options should be placed under a `playwrightOptions` object.
|
16
|
+
|
17
|
+
**Before (0.9):**
|
18
|
+
|
19
|
+
```javascript
|
20
|
+
// creevey.config.js
|
21
|
+
export default {
|
22
|
+
browsers: {
|
23
|
+
chrome: {
|
24
|
+
browserName: 'chrome',
|
25
|
+
browserVersion: '90.0',
|
26
|
+
platformName: 'linux',
|
27
|
+
},
|
28
|
+
},
|
29
|
+
};
|
30
|
+
```
|
31
|
+
|
32
|
+
**After (0.10):**
|
33
|
+
|
34
|
+
```typescript
|
35
|
+
// creevey.config.ts
|
36
|
+
import type { CreeveyConfig } from 'creevey';
|
37
|
+
import { SeleniumWebdriver } from 'creevey/selenium';
|
38
|
+
// or
|
39
|
+
// import { PlaywrightWebdriver } from 'creevey/playwright';
|
40
|
+
|
41
|
+
const config: CreeveyConfig = {
|
42
|
+
webdriver: SeleniumWebdriver, // or PlaywrightWebdriver
|
43
|
+
browsers: {
|
44
|
+
chrome: {
|
45
|
+
// For Selenium
|
46
|
+
browserName: 'chrome',
|
47
|
+
seleniumCapabilities: {
|
48
|
+
browserVersion: '90.0',
|
49
|
+
platformName: 'linux',
|
50
|
+
},
|
51
|
+
},
|
52
|
+
firefoxPlaywright: {
|
53
|
+
// For Playwright
|
54
|
+
browserName: 'firefox', // 'chromium', 'firefox', or 'webkit' for Playwright
|
55
|
+
playwrightOptions: {
|
56
|
+
headless: true,
|
57
|
+
},
|
58
|
+
},
|
59
|
+
},
|
60
|
+
};
|
61
|
+
|
62
|
+
export default config;
|
63
|
+
```
|
64
|
+
|
65
|
+
### 2. Mocha Removal and New `CreeveyTestContext` API
|
66
|
+
|
67
|
+
Creevey no longer uses the Mocha testing framework. Tests now use a `CreeveyTestContext` object passed as an argument to the test function.
|
68
|
+
|
69
|
+
- Replace `this` with the `context` parameter in your tests.
|
70
|
+
- Image matching methods (e.g., `matchImage`, `takeScreenshot`) are now called on the `context` object.
|
71
|
+
- The `context.webdriver` property gives you direct access to the configured WebDriver instance (Selenium or Playwright) for advanced browser interactions.
|
72
|
+
|
73
|
+
**Before (0.9 - Mocha style):**
|
74
|
+
|
75
|
+
```javascript
|
76
|
+
it('should match the image', async function () {
|
77
|
+
this.expect(await this.takeScreenshot()).to.matchImage('example');
|
78
|
+
});
|
79
|
+
```
|
80
|
+
|
81
|
+
**After (0.10 - New context style):**
|
82
|
+
|
83
|
+
```javascript
|
84
|
+
it('should match the image', async (context) => {
|
85
|
+
await context.matchImage(await context.takeScreenshot(), 'example');
|
86
|
+
});
|
87
|
+
|
88
|
+
// Example using context.webdriver with Selenium WebDriver API
|
89
|
+
it('should interact with an element using Selenium', async (context) => {
|
90
|
+
const seleniumWebDriver = context.webdriver; // Assuming SeleniumWebdriver is configured
|
91
|
+
const element = await seleniumWebDriver.findElement({ css: '#myElement' });
|
92
|
+
await element.click();
|
93
|
+
// ... more Selenium interactions
|
94
|
+
await context.matchImage(await context.takeScreenshot(), 'selenium-interaction');
|
95
|
+
});
|
96
|
+
|
97
|
+
// Example using context.webdriver with Playwright API
|
98
|
+
it('should interact with an element using Playwright', async (context) => {
|
99
|
+
const playwrightPage = context.webdriver; // Assuming PlaywrightWebdriver is configured
|
100
|
+
await playwrightPage.click('#myElement');
|
101
|
+
// ... more Playwright interactions
|
102
|
+
await context.matchImage(await context.takeScreenshot(), 'playwright-interaction');
|
103
|
+
});
|
104
|
+
```
|
105
|
+
|
106
|
+
### 3. Reporter Configuration
|
107
|
+
|
108
|
+
Reporter setup has moved from command-line options to the `creevey.config.ts` file.
|
109
|
+
|
110
|
+
**Example (0.10):**
|
111
|
+
|
112
|
+
```typescript
|
113
|
+
// creevey.config.ts
|
114
|
+
import type { CreeveyConfig } from 'creevey';
|
115
|
+
|
116
|
+
const config: CreeveyConfig = {
|
117
|
+
reporter: 'junit', // or 'teamcity', 'creevey'
|
118
|
+
reporterOptions: {
|
119
|
+
// For JUnit: { outputFile: 'report.xml' }
|
120
|
+
// For Creevey HTML reporter (default): { reportDir: './report' }
|
121
|
+
},
|
122
|
+
};
|
123
|
+
|
124
|
+
export default config;
|
125
|
+
```
|
126
|
+
|
127
|
+
---
|
128
|
+
|
129
|
+
## Key New Features & Updates
|
130
|
+
|
131
|
+
- **Creevey Playwright Reporter:** Integrate Creevey's visual testing into your existing Playwright test suites. See `docs/playwright-reporter.md` for details.
|
132
|
+
- **Approve Tests from Report UI (Update Mode):** Approve visual changes directly in the Creevey report UI. Run with `creevey --ui --update` (or `creevey --ui -u`).
|
133
|
+
- **ODiff Image Comparison:** Use `odiff` for image comparison with the `--odiff` flag and `odiffOptions` in config.
|
134
|
+
- **Easier Storybook Autostart:** Use `creevey -s` or `creevey --startStorybook` to automatically start Storybook. Creevey will find a free port if necessary.
|
135
|
+
|
136
|
+
---
|
137
|
+
|
138
|
+
## Other Notable Changes
|
139
|
+
|
140
|
+
- **`--noDocker` Option:** A command-line flag to disable Docker, overriding `useDocker: true` in your config.
|
141
|
+
|
142
|
+
---
|
143
|
+
|
144
|
+
We recommend reviewing the full announcement for details on all new features and improvements. After updating, test your suite thoroughly to ensure a smooth transition.
|
@@ -0,0 +1,357 @@
|
|
1
|
+
# Playwright Reporter for Creevey
|
2
|
+
|
3
|
+
Creevey provides a Playwright-compatible reporter that allows you to use Creevey's image comparison, reporting, and UI features with Playwright tests.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
The reporter is included with the Creevey package. Install Playwright and Creevey in your project:
|
8
|
+
|
9
|
+
```bash
|
10
|
+
npm install --save-dev @playwright/test creevey
|
11
|
+
```
|
12
|
+
|
13
|
+
## Configuration
|
14
|
+
|
15
|
+
Add the Creevey reporter to your Playwright configuration file:
|
16
|
+
|
17
|
+
```typescript
|
18
|
+
// playwright.config.ts
|
19
|
+
import { defineConfig } from '@playwright/test';
|
20
|
+
|
21
|
+
export default defineConfig({
|
22
|
+
reporter: [
|
23
|
+
['list'], // Standard Playwright reporter for console output
|
24
|
+
[
|
25
|
+
'creevey/playwright-reporter',
|
26
|
+
{
|
27
|
+
// Optional configuration options
|
28
|
+
reportDir: './report', // Directory for report output
|
29
|
+
screenDir: './images', // Directory for reference images
|
30
|
+
port: 3000, // Port for Creevey UI server
|
31
|
+
debug: false, // Enable debug logging
|
32
|
+
},
|
33
|
+
],
|
34
|
+
],
|
35
|
+
// Other Playwright configuration...
|
36
|
+
});
|
37
|
+
```
|
38
|
+
|
39
|
+
## Usage
|
40
|
+
|
41
|
+
### Taking Screenshots for Comparison
|
42
|
+
|
43
|
+
The reporter automatically collects screenshots taken during Playwright tests. You can use Playwright's built-in screenshot capabilities:
|
44
|
+
|
45
|
+
#### Using `page.screenshot()`
|
46
|
+
|
47
|
+
```typescript
|
48
|
+
import { test, expect } from '@playwright/test';
|
49
|
+
|
50
|
+
test('capture screenshot with page.screenshot', async ({ page }) => {
|
51
|
+
await page.goto('https://example.com');
|
52
|
+
|
53
|
+
// Take a screenshot and attach it to the test result
|
54
|
+
const screenshot = await page.screenshot();
|
55
|
+
await test.info().attach('example-screenshot', {
|
56
|
+
body: screenshot,
|
57
|
+
contentType: 'image/png',
|
58
|
+
});
|
59
|
+
});
|
60
|
+
```
|
61
|
+
|
62
|
+
#### Using Playwright's expect().toHaveScreenshot()
|
63
|
+
|
64
|
+
```typescript
|
65
|
+
import { test, expect } from '@playwright/test';
|
66
|
+
|
67
|
+
test('capture screenshot with toHaveScreenshot', async ({ page }) => {
|
68
|
+
await page.goto('https://example.com');
|
69
|
+
|
70
|
+
// This will automatically be picked up by the Creevey reporter
|
71
|
+
await expect(page).toHaveScreenshot('example-screenshot.png');
|
72
|
+
});
|
73
|
+
```
|
74
|
+
|
75
|
+
### Adding Creevey Metadata
|
76
|
+
|
77
|
+
You can add metadata to your tests to better organize them in the Creevey UI:
|
78
|
+
|
79
|
+
```typescript
|
80
|
+
import { test } from '@playwright/test';
|
81
|
+
|
82
|
+
test.describe('Homepage', () => {
|
83
|
+
test('header elements @creevey{"storyPath": ["Website", "HomePage"], "browser": "chromium"}', async ({ page }) => {
|
84
|
+
await page.goto('https://example.com');
|
85
|
+
// Test code...
|
86
|
+
await page.screenshot({ path: 'header.png' });
|
87
|
+
});
|
88
|
+
});
|
89
|
+
```
|
90
|
+
|
91
|
+
The `@creevey` annotation accepts a JSON object with the following properties:
|
92
|
+
|
93
|
+
- `storyPath`: Array of strings defining the hierarchy in the Creevey UI
|
94
|
+
- `browser`: Browser name (chromium, firefox, webkit)
|
95
|
+
- `testName`: Custom test name (defaults to the test title)
|
96
|
+
|
97
|
+
### Viewing Results
|
98
|
+
|
99
|
+
After running your tests, you can view the results in the Creevey UI:
|
100
|
+
|
101
|
+
1. Open your browser and navigate to `http://localhost:3000` (or the port you configured)
|
102
|
+
2. Browse test results, view image comparisons, and approve changes
|
103
|
+
|
104
|
+
Run your tests with Playwright:
|
105
|
+
|
106
|
+
```bash
|
107
|
+
npx playwright test
|
108
|
+
```
|
109
|
+
|
110
|
+
The Creevey server will automatically start during the test run, and you'll see a message with the URL once tests complete.
|
111
|
+
|
112
|
+
### Approving Screenshots
|
113
|
+
|
114
|
+
You can approve screenshots directly from the Creevey UI by:
|
115
|
+
|
116
|
+
1. Selecting the test with the failed comparison
|
117
|
+
2. Reviewing the differences between expected and actual images
|
118
|
+
3. Clicking the "Approve" button to update the reference image
|
119
|
+
|
120
|
+
## Advanced Usage
|
121
|
+
|
122
|
+
### Custom Screenshot Names
|
123
|
+
|
124
|
+
You can customize screenshot names to better organize your visual tests:
|
125
|
+
|
126
|
+
```typescript
|
127
|
+
test('product page layout', async ({ page }) => {
|
128
|
+
await page.goto('https://example.com/products/1');
|
129
|
+
|
130
|
+
// Take multiple screenshots in a single test
|
131
|
+
await test.info().attach('product-header', {
|
132
|
+
body: await page.locator('.product-header').screenshot(),
|
133
|
+
contentType: 'image/png',
|
134
|
+
});
|
135
|
+
|
136
|
+
await test.info().attach('product-details', {
|
137
|
+
body: await page.locator('.product-details').screenshot(),
|
138
|
+
contentType: 'image/png',
|
139
|
+
});
|
140
|
+
});
|
141
|
+
```
|
142
|
+
|
143
|
+
### Multiple Screenshots in One Test
|
144
|
+
|
145
|
+
You can capture multiple screenshots in a single test:
|
146
|
+
|
147
|
+
```typescript
|
148
|
+
test('responsive design checks', async ({ page }) => {
|
149
|
+
await page.goto('https://example.com');
|
150
|
+
|
151
|
+
// Mobile view
|
152
|
+
await page.setViewportSize({ width: 375, height: 667 });
|
153
|
+
await test.info().attach('mobile-view', {
|
154
|
+
body: await page.screenshot(),
|
155
|
+
contentType: 'image/png',
|
156
|
+
});
|
157
|
+
|
158
|
+
// Tablet view
|
159
|
+
await page.setViewportSize({ width: 768, height: 1024 });
|
160
|
+
await test.info().attach('tablet-view', {
|
161
|
+
body: await page.screenshot(),
|
162
|
+
contentType: 'image/png',
|
163
|
+
});
|
164
|
+
|
165
|
+
// Desktop view
|
166
|
+
await page.setViewportSize({ width: 1280, height: 800 });
|
167
|
+
await test.info().attach('desktop-view', {
|
168
|
+
body: await page.screenshot(),
|
169
|
+
contentType: 'image/png',
|
170
|
+
});
|
171
|
+
});
|
172
|
+
```
|
173
|
+
|
174
|
+
### Custom Test Names
|
175
|
+
|
176
|
+
By default, the reporter will use the Playwright test title as the test name. You can customize how tests are named by setting meta data:
|
177
|
+
|
178
|
+
```typescript
|
179
|
+
test('home page visual test', async ({ page }) => {
|
180
|
+
test.info().annotations.push({
|
181
|
+
type: 'creevey',
|
182
|
+
description: JSON.stringify({
|
183
|
+
testName: 'custom-test-name',
|
184
|
+
browser: 'chrome', // Optional, to override browser name
|
185
|
+
}),
|
186
|
+
});
|
187
|
+
|
188
|
+
// Test implementation...
|
189
|
+
});
|
190
|
+
```
|
191
|
+
|
192
|
+
### Integration with Existing Creevey Configuration
|
193
|
+
|
194
|
+
If you're already using Creevey for other tests, you can share configuration:
|
195
|
+
|
196
|
+
```typescript
|
197
|
+
import { defineConfig } from '@playwright/test';
|
198
|
+
import creeveyConfig from './creevey.config.js';
|
199
|
+
|
200
|
+
export default defineConfig({
|
201
|
+
reporter: [
|
202
|
+
['list'],
|
203
|
+
[
|
204
|
+
'creevey/playwright-reporter',
|
205
|
+
{
|
206
|
+
reportDir: creeveyConfig.reportDir,
|
207
|
+
screenDir: creeveyConfig.screenDir,
|
208
|
+
port: 3001, // Use a different port to avoid conflicts
|
209
|
+
},
|
210
|
+
],
|
211
|
+
],
|
212
|
+
});
|
213
|
+
```
|
214
|
+
|
215
|
+
### Test Steps Integration
|
216
|
+
|
217
|
+
The reporter supports Playwright's test steps, capturing screenshots at each step:
|
218
|
+
|
219
|
+
```typescript
|
220
|
+
test('multi-step test', async ({ page }) => {
|
221
|
+
await test.step('Step 1: Navigate to home', async () => {
|
222
|
+
await page.goto('/');
|
223
|
+
// Screenshot captured from this step will be associated with "Step 1"
|
224
|
+
await test.info().attach('step1', {
|
225
|
+
body: await page.screenshot(),
|
226
|
+
contentType: 'image/png',
|
227
|
+
});
|
228
|
+
});
|
229
|
+
|
230
|
+
await test.step('Step 2: Click button', async () => {
|
231
|
+
await page.click('.button');
|
232
|
+
// This screenshot will be associated with "Step 2"
|
233
|
+
await test.info().attach('step2', {
|
234
|
+
body: await page.screenshot(),
|
235
|
+
contentType: 'image/png',
|
236
|
+
});
|
237
|
+
});
|
238
|
+
});
|
239
|
+
```
|
240
|
+
|
241
|
+
### Integration with Existing Creevey Server
|
242
|
+
|
243
|
+
If you're already running a Creevey server, you can configure the reporter to use it:
|
244
|
+
|
245
|
+
```typescript
|
246
|
+
[
|
247
|
+
CreeveyPlaywrightReporter,
|
248
|
+
{
|
249
|
+
useExistingServer: true, // Don't start a new server
|
250
|
+
port: 3000, // Port of the existing server
|
251
|
+
},
|
252
|
+
];
|
253
|
+
```
|
254
|
+
|
255
|
+
### Performance Optimization
|
256
|
+
|
257
|
+
For large test suites with many screenshots, you can enable performance optimizations:
|
258
|
+
|
259
|
+
```typescript
|
260
|
+
[
|
261
|
+
CreeveyPlaywrightReporter,
|
262
|
+
{
|
263
|
+
batchProcessing: true, // Process screenshots in batches
|
264
|
+
maxConcurrency: 4, // Maximum concurrent screenshot processing
|
265
|
+
lazyInit: true, // Initialize components on demand
|
266
|
+
},
|
267
|
+
];
|
268
|
+
```
|
269
|
+
|
270
|
+
## API Reference
|
271
|
+
|
272
|
+
### Reporter Options
|
273
|
+
|
274
|
+
| Option | Type | Default | Description |
|
275
|
+
| ------------------------- | ------- | ------------ | ----------------------------------------------------- |
|
276
|
+
| `reportDir` | string | `'./report'` | Directory where Creevey will store reports |
|
277
|
+
| `screenDir` | string | `'./images'` | Directory where reference images are stored |
|
278
|
+
| `port` | number | `3000` | Port number for the Creevey UI server |
|
279
|
+
| `debug` | boolean | `false` | Enable debug logging |
|
280
|
+
| `uiEnabled` | boolean | `true` | Enable or disable the UI server |
|
281
|
+
| `useExistingServer` | boolean | `false` | Use an existing Creevey server instance |
|
282
|
+
| `batchProcessing` | boolean | `false` | Process screenshots in batches for better performance |
|
283
|
+
| `maxConcurrency` | number | `2` | Maximum concurrent screenshot processing operations |
|
284
|
+
| `lazyInit` | boolean | `false` | Initialize components on demand for faster startup |
|
285
|
+
| `retainOrphanedImages` | boolean | `false` | Keep images not associated with current tests |
|
286
|
+
| `customComparisonOptions` | object | `undefined` | Custom options for image comparison |
|
287
|
+
|
288
|
+
## Troubleshooting
|
289
|
+
|
290
|
+
### Common Issues
|
291
|
+
|
292
|
+
- **Port conflicts**: If the Creevey server fails to start, it might be due to port conflicts. Change the port in the configuration.
|
293
|
+
- **Missing screenshots**: Ensure your tests are attaching screenshots with unique names or using `toHaveScreenshot()`.
|
294
|
+
- **Path issues**: If reference images aren't found, check that the `screenDir` path is correct and accessible.
|
295
|
+
|
296
|
+
If screenshots are not appearing in the Creevey UI:
|
297
|
+
|
298
|
+
1. Ensure your screenshots are being properly attached to test results
|
299
|
+
2. Check that the content type is set to 'image/png' when attaching
|
300
|
+
3. Enable debug mode in the reporter configuration to see detailed logs
|
301
|
+
|
302
|
+
### Server Issues
|
303
|
+
|
304
|
+
If the Creevey server fails to start:
|
305
|
+
|
306
|
+
1. Check if the configured port is already in use
|
307
|
+
2. Ensure the report directory is writable
|
308
|
+
3. Look for error messages in the console output
|
309
|
+
|
310
|
+
### Debug Mode
|
311
|
+
|
312
|
+
Enable debug logging for more detailed information:
|
313
|
+
|
314
|
+
```typescript
|
315
|
+
[
|
316
|
+
CreeveyPlaywrightReporter,
|
317
|
+
{
|
318
|
+
debug: true,
|
319
|
+
// Other options...
|
320
|
+
},
|
321
|
+
];
|
322
|
+
```
|
323
|
+
|
324
|
+
## Error Handling
|
325
|
+
|
326
|
+
The reporter is designed to handle errors gracefully:
|
327
|
+
|
328
|
+
- If the reporter fails to initialize, tests will still run and screenshots will be captured when possible
|
329
|
+
- If the server can't start, the reporter will continue to capture screenshots but the UI won't be available
|
330
|
+
- All errors are logged with appropriate severity levels and won't cause your tests to fail
|
331
|
+
|
332
|
+
### Debugging Reporter Issues
|
333
|
+
|
334
|
+
For detailed debugging information, enable debug mode and check the logs:
|
335
|
+
|
336
|
+
```typescript
|
337
|
+
[
|
338
|
+
CreeveyPlaywrightReporter,
|
339
|
+
{
|
340
|
+
debug: true,
|
341
|
+
},
|
342
|
+
];
|
343
|
+
```
|
344
|
+
|
345
|
+
You can also specify a custom log file for the reporter:
|
346
|
+
|
347
|
+
```typescript
|
348
|
+
[
|
349
|
+
CreeveyPlaywrightReporter,
|
350
|
+
{
|
351
|
+
debug: true,
|
352
|
+
logFile: './creevey-reporter.log',
|
353
|
+
},
|
354
|
+
];
|
355
|
+
```
|
356
|
+
|
357
|
+
For more help, please check the main Creevey documentation or open an issue on GitHub.
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "creevey",
|
3
3
|
"description": "Cross-browser screenshot testing tool for Storybook with fancy UI Runner",
|
4
|
-
"version": "0.10.0-beta.
|
4
|
+
"version": "0.10.0-beta.45",
|
5
5
|
"type": "commonjs",
|
6
6
|
"bin": "dist/cli.js",
|
7
7
|
"main": "./dist/index.js",
|
@@ -12,6 +12,10 @@
|
|
12
12
|
"types": "./dist/playwright.d.ts",
|
13
13
|
"default": "./dist/playwright.js"
|
14
14
|
},
|
15
|
+
"./playwright-reporter": {
|
16
|
+
"types": "./dist/playwright-reporter.d.ts",
|
17
|
+
"default": "./dist/playwright-reporter.js"
|
18
|
+
},
|
15
19
|
"./selenium": {
|
16
20
|
"types": "./dist/selenium.d.ts",
|
17
21
|
"default": "./dist/selenium.js"
|
@@ -48,7 +52,8 @@
|
|
48
52
|
"lint:tsc": "tsc --noEmit",
|
49
53
|
"lint:eslint": "eslint",
|
50
54
|
"lint:prettier": "prettier --check .",
|
51
|
-
"test": "vitest",
|
55
|
+
"test": "vitest run",
|
56
|
+
"test:watch": "vitest",
|
52
57
|
"start": "concurrently \"yarn start:client\" \"yarn start:storybook\" \"yarn start:creevey\"",
|
53
58
|
"start:client": "vite",
|
54
59
|
"start:storybook": "storybook dev --ci -p 6006",
|
@@ -86,16 +91,10 @@
|
|
86
91
|
}
|
87
92
|
},
|
88
93
|
"dependencies": {
|
89
|
-
"@koa/cors": "^5.0.0",
|
90
94
|
"@octokit/core": "^6.1.4",
|
91
95
|
"@storybook/icons": "^1.4.0",
|
92
96
|
"@types/chai": "^4.3.20",
|
93
97
|
"@types/dockerode": "^3.3.37",
|
94
|
-
"@types/koa": "^2.15.0",
|
95
|
-
"@types/koa-bodyparser": "^4.3.12",
|
96
|
-
"@types/koa-mount": "^4.0.5",
|
97
|
-
"@types/koa-static": "^4.0.4",
|
98
|
-
"@types/koa__cors": "^5.0.0",
|
99
98
|
"@types/lodash": "^4.17.16",
|
100
99
|
"@types/micromatch": "^4.0.9",
|
101
100
|
"@types/minimist": "^1.2.5",
|
@@ -113,10 +112,6 @@
|
|
113
112
|
"dockerode": "^4.0.5",
|
114
113
|
"find-cache-dir": "^5.0.0",
|
115
114
|
"get-port": "^7.1.0",
|
116
|
-
"koa": "^2.16.0",
|
117
|
-
"koa-bodyparser": "^4.4.1",
|
118
|
-
"koa-mount": "^4.0.0",
|
119
|
-
"koa-static": "^5.0.0",
|
120
115
|
"lodash": "^4.17.21",
|
121
116
|
"loglevel": "^1.9.2",
|
122
117
|
"loglevel-plugin-prefix": "^0.8.4",
|
@@ -140,6 +135,7 @@
|
|
140
135
|
"devDependencies": {
|
141
136
|
"@chromatic-com/storybook": "^3.2.6",
|
142
137
|
"@eslint/js": "^9.23.0",
|
138
|
+
"@playwright/test": "^1.52.0",
|
143
139
|
"@storybook/addon-essentials": "^8.6.12",
|
144
140
|
"@storybook/addon-interactions": "^8.6.12",
|
145
141
|
"@storybook/blocks": "^8.6.12",
|
@@ -208,7 +204,7 @@
|
|
208
204
|
"displayName": "Creevey"
|
209
205
|
},
|
210
206
|
"volta": {
|
211
|
-
"node": "
|
212
|
-
"yarn": "4.
|
207
|
+
"node": "22.15.0",
|
208
|
+
"yarn": "4.9.1"
|
213
209
|
}
|
214
210
|
}
|
@@ -22,7 +22,7 @@ export class CreeveyController {
|
|
22
22
|
storyId = '';
|
23
23
|
activeBrowser = '';
|
24
24
|
selectedTestId = '';
|
25
|
-
status: CreeveyStatus = { isRunning: false, tests: {}, browsers: [] };
|
25
|
+
status: CreeveyStatus = { isRunning: false, tests: {}, browsers: [], isUpdateMode: false };
|
26
26
|
creeveyApi: CreeveyClientApi | null = null;
|
27
27
|
stories: StoriesRaw = {};
|
28
28
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import type { Renderer
|
1
|
+
import type { Renderer } from '@storybook/types';
|
2
2
|
import type { PreviewWeb, StoryStore } from '@storybook/preview-api';
|
3
3
|
import { Channel } from '@storybook/channels';
|
4
4
|
import {
|
@@ -121,7 +121,6 @@ function initCreeveyState(): void {
|
|
121
121
|
|
122
122
|
if (prevState.creeveyHost) window.__CREEVEY_SERVER_HOST__ = prevState.creeveyHost;
|
123
123
|
if (prevState.creeveyPort) window.__CREEVEY_SERVER_PORT__ = prevState.creeveyPort;
|
124
|
-
if (prevState.setStoriesCounter) setStoriesCounter = prevState.setStoriesCounter;
|
125
124
|
if (prevState.isTestBrowser) isTestBrowser = prevState.isTestBrowser;
|
126
125
|
|
127
126
|
window.addEventListener('beforeunload', () => {
|
@@ -130,7 +129,6 @@ function initCreeveyState(): void {
|
|
130
129
|
JSON.stringify({
|
131
130
|
creeveyHost: window.__CREEVEY_SERVER_HOST__,
|
132
131
|
creeveyPort: window.__CREEVEY_SERVER_PORT__,
|
133
|
-
setStoriesCounter,
|
134
132
|
isTestBrowser,
|
135
133
|
} as CreeveyTestsState),
|
136
134
|
);
|
@@ -141,7 +139,6 @@ let isTestBrowser = false;
|
|
141
139
|
let captureResolver: () => void;
|
142
140
|
let waitForCreevey: Promise<void>;
|
143
141
|
let creeveyReady: () => void;
|
144
|
-
let setStoriesCounter = 0;
|
145
142
|
let globals = {};
|
146
143
|
|
147
144
|
export function withCreevey(): ReturnType<typeof makeDecorator> {
|
@@ -160,20 +157,9 @@ export function withCreevey(): ReturnType<typeof makeDecorator> {
|
|
160
157
|
document.head.appendChild(style);
|
161
158
|
}
|
162
159
|
|
160
|
+
// TODO Find a way to send stories updates to the server
|
163
161
|
async function getStories(): Promise<StoriesRaw | undefined> {
|
164
162
|
const stories = serializeRawStories(await window.__STORYBOOK_PREVIEW__.extract());
|
165
|
-
const storiesByFiles = new Map<string, StoryContextForEnhancers[]>();
|
166
|
-
Object.values(stories).forEach((story) => {
|
167
|
-
const fileName = story.parameters.fileName as string;
|
168
|
-
const storiesFromFile = storiesByFiles.get(fileName);
|
169
|
-
if (storiesFromFile) storiesFromFile.push(story);
|
170
|
-
else storiesByFiles.set(fileName, [story]);
|
171
|
-
});
|
172
|
-
void fetch(`http://${getConnectionUrl()}/stories`, {
|
173
|
-
method: 'POST',
|
174
|
-
headers: { 'Content-Type': 'application/json' },
|
175
|
-
body: JSON.stringify({ setStoriesCounter, stories: [...storiesByFiles.entries()] }),
|
176
|
-
});
|
177
163
|
return stories;
|
178
164
|
}
|
179
165
|
|
@@ -21,14 +21,14 @@ interface PageHeaderProps {
|
|
21
21
|
}
|
22
22
|
|
23
23
|
const Container = styled.div({
|
24
|
-
|
24
|
+
marginTop: '24px',
|
25
25
|
});
|
26
26
|
|
27
27
|
const ErrorContainer = withTheme(
|
28
28
|
styled.div<{ theme: Theme }>(({ theme }) => ({
|
29
29
|
marginTop: '8px',
|
30
30
|
padding: '8px',
|
31
|
-
background: theme.background.negative
|
31
|
+
background: `${theme.background.negative}20`,
|
32
32
|
color: theme.color.negative,
|
33
33
|
borderRadius: '2px',
|
34
34
|
display: 'flex',
|
@@ -48,8 +48,19 @@ const ErrorContainer = withTheme(
|
|
48
48
|
})),
|
49
49
|
);
|
50
50
|
|
51
|
+
const UpdateModeBanner = withTheme(
|
52
|
+
styled.div(({ theme }) => ({
|
53
|
+
padding: '8px 32px',
|
54
|
+
backgroundColor: `${theme.color.positive}20`,
|
55
|
+
color: theme.color.positive,
|
56
|
+
fontSize: '12px',
|
57
|
+
textAlign: 'center',
|
58
|
+
fontWeight: 'bold',
|
59
|
+
})),
|
60
|
+
);
|
61
|
+
|
51
62
|
const H1 = styled.h1({
|
52
|
-
|
63
|
+
marginLeft: '44px',
|
53
64
|
marginBottom: '8px',
|
54
65
|
});
|
55
66
|
|
@@ -77,7 +88,7 @@ export function PageHeader({
|
|
77
88
|
onImageChange,
|
78
89
|
onViewModeChange,
|
79
90
|
}: PageHeaderProps): JSX.Element | null {
|
80
|
-
const { isReport } = useContext(CreeveyContext);
|
91
|
+
const { isReport, isUpdateMode } = useContext(CreeveyContext);
|
81
92
|
const imageEntires = Object.entries(images) as [string, Images][];
|
82
93
|
|
83
94
|
const handleViewModeChange = (mode: string): void => {
|
@@ -120,6 +131,9 @@ export function PageHeader({
|
|
120
131
|
))}
|
121
132
|
</ImagesEntriesContainer>
|
122
133
|
) : null}
|
134
|
+
{isUpdateMode && (
|
135
|
+
<UpdateModeBanner>Update Mode: Review and approve screenshots from previous test runs</UpdateModeBanner>
|
136
|
+
)}
|
123
137
|
{showViewModes && (
|
124
138
|
<Tabs selected={viewMode} actions={{ onSelect: handleViewModeChange }}>
|
125
139
|
{viewModes.map((x) => (
|