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.
Files changed (137) hide show
  1. package/CHANGELOG.md +282 -0
  2. package/dist/client/addon/controller.js +1 -1
  3. package/dist/client/addon/controller.js.map +1 -1
  4. package/dist/client/addon/withCreevey.js +1 -18
  5. package/dist/client/addon/withCreevey.js.map +1 -1
  6. package/dist/client/shared/components/PageHeader/PageHeader.js +13 -4
  7. package/dist/client/shared/components/PageHeader/PageHeader.js.map +1 -1
  8. package/dist/client/shared/creeveyClientApi.js +10 -0
  9. package/dist/client/shared/creeveyClientApi.js.map +1 -1
  10. package/dist/client/web/CreeveyApp.d.ts +1 -0
  11. package/dist/client/web/CreeveyApp.js +1 -0
  12. package/dist/client/web/CreeveyApp.js.map +1 -1
  13. package/dist/client/web/CreeveyContext.d.ts +1 -0
  14. package/dist/client/web/CreeveyContext.js +1 -0
  15. package/dist/client/web/CreeveyContext.js.map +1 -1
  16. package/dist/client/web/CreeveyView/SideBar/SideBarFooter.js +9 -8
  17. package/dist/client/web/CreeveyView/SideBar/SideBarFooter.js.map +1 -1
  18. package/dist/client/web/CreeveyView/SideBar/SideBarHeader.js +13 -3
  19. package/dist/client/web/CreeveyView/SideBar/SideBarHeader.js.map +1 -1
  20. package/dist/client/web/CreeveyView/SideBar/SuiteLink.js +2 -3
  21. package/dist/client/web/CreeveyView/SideBar/SuiteLink.js.map +1 -1
  22. package/dist/client/web/CreeveyView/SideBar/TestLink.js +2 -3
  23. package/dist/client/web/CreeveyView/SideBar/TestLink.js.map +1 -1
  24. package/dist/client/web/CreeveyView/SideBar/TestsStatus.js +1 -0
  25. package/dist/client/web/CreeveyView/SideBar/TestsStatus.js.map +1 -1
  26. package/dist/client/web/assets/{index-C47njyZV.js → index-BU4jjKVC.js} +68 -68
  27. package/dist/client/web/index.html +1 -1
  28. package/dist/client/web/index.js +8 -3
  29. package/dist/client/web/index.js.map +1 -1
  30. package/dist/creevey.d.ts +1 -1
  31. package/dist/creevey.js +1 -22
  32. package/dist/creevey.js.map +1 -1
  33. package/dist/playwright-reporter.d.ts +2 -0
  34. package/dist/playwright-reporter.js +5 -0
  35. package/dist/playwright-reporter.js.map +1 -0
  36. package/dist/playwright.d.ts +1 -1
  37. package/dist/server/config.js +8 -1
  38. package/dist/server/config.js.map +1 -1
  39. package/dist/server/index.js +12 -5
  40. package/dist/server/index.js.map +1 -1
  41. package/dist/server/master/api.d.ts +11 -6
  42. package/dist/server/master/api.js +88 -25
  43. package/dist/server/master/api.js.map +1 -1
  44. package/dist/server/master/handlers/capture-handler.d.ts +5 -0
  45. package/dist/server/master/handlers/capture-handler.js +25 -0
  46. package/dist/server/master/handlers/capture-handler.js.map +1 -0
  47. package/dist/server/master/handlers/index.d.ts +4 -0
  48. package/dist/server/master/handlers/index.js +21 -0
  49. package/dist/server/master/handlers/index.js.map +1 -0
  50. package/dist/server/master/handlers/ping-handler.d.ts +2 -0
  51. package/dist/server/master/handlers/ping-handler.js +8 -0
  52. package/dist/server/master/handlers/ping-handler.js.map +1 -0
  53. package/dist/server/master/handlers/static-handler.d.ts +1 -0
  54. package/dist/server/master/handlers/static-handler.js +22 -0
  55. package/dist/server/master/handlers/static-handler.js.map +1 -0
  56. package/dist/server/master/handlers/stories-handler.d.ts +4 -0
  57. package/dist/server/master/handlers/stories-handler.js +24 -0
  58. package/dist/server/master/handlers/stories-handler.js.map +1 -0
  59. package/dist/server/master/master.js +7 -24
  60. package/dist/server/master/master.js.map +1 -1
  61. package/dist/server/master/runner.d.ts +4 -6
  62. package/dist/server/master/runner.js +30 -127
  63. package/dist/server/master/runner.js.map +1 -1
  64. package/dist/server/master/server.js +191 -89
  65. package/dist/server/master/server.js.map +1 -1
  66. package/dist/server/master/start.d.ts +1 -2
  67. package/dist/server/master/start.js +11 -29
  68. package/dist/server/master/start.js.map +1 -1
  69. package/dist/server/master/testsManager.d.ts +81 -0
  70. package/dist/server/master/testsManager.js +281 -0
  71. package/dist/server/master/testsManager.js.map +1 -0
  72. package/dist/server/playwright/docker-file.js +2 -2
  73. package/dist/server/playwright/docker-file.js.map +1 -1
  74. package/dist/server/playwright/reporter.d.ts +87 -0
  75. package/dist/server/playwright/reporter.js +351 -0
  76. package/dist/server/playwright/reporter.js.map +1 -0
  77. package/dist/server/selenium/internal.js +20 -2
  78. package/dist/server/selenium/internal.js.map +1 -1
  79. package/dist/server/selenium/selenoid.js +4 -0
  80. package/dist/server/selenium/selenoid.js.map +1 -1
  81. package/dist/server/shutdown.d.ts +1 -0
  82. package/dist/server/shutdown.js +23 -0
  83. package/dist/server/shutdown.js.map +1 -0
  84. package/dist/server/stories.d.ts +0 -1
  85. package/dist/server/stories.js +0 -12
  86. package/dist/server/stories.js.map +1 -1
  87. package/dist/server/ui-update.d.ts +10 -0
  88. package/dist/server/ui-update.js +39 -0
  89. package/dist/server/ui-update.js.map +1 -0
  90. package/dist/server/utils.d.ts +6 -0
  91. package/dist/server/utils.js +39 -8
  92. package/dist/server/utils.js.map +1 -1
  93. package/dist/server/worker/start.js +1 -1
  94. package/dist/server/worker/start.js.map +1 -1
  95. package/dist/types.d.ts +14 -8
  96. package/dist/types.js.map +1 -1
  97. package/docs/examples/playwright-reporter-example.ts +202 -0
  98. package/docs/migration-0.9-to-0.10.md +144 -0
  99. package/docs/playwright-reporter.md +357 -0
  100. package/package.json +10 -14
  101. package/src/client/addon/controller.ts +1 -1
  102. package/src/client/addon/withCreevey.ts +2 -16
  103. package/src/client/shared/components/PageHeader/PageHeader.tsx +18 -4
  104. package/src/client/shared/creeveyClientApi.ts +10 -0
  105. package/src/client/web/CreeveyApp.tsx +2 -0
  106. package/src/client/web/CreeveyContext.tsx +2 -0
  107. package/src/client/web/CreeveyView/SideBar/SideBarFooter.tsx +19 -17
  108. package/src/client/web/CreeveyView/SideBar/SideBarHeader.tsx +18 -3
  109. package/src/client/web/CreeveyView/SideBar/SuiteLink.tsx +9 -7
  110. package/src/client/web/CreeveyView/SideBar/TestLink.tsx +8 -6
  111. package/src/client/web/CreeveyView/SideBar/TestsStatus.tsx +1 -0
  112. package/src/client/web/index.tsx +8 -3
  113. package/src/creevey.ts +1 -24
  114. package/src/playwright-reporter.ts +3 -0
  115. package/src/server/config.ts +9 -1
  116. package/src/server/index.ts +13 -6
  117. package/src/server/master/api.ts +94 -28
  118. package/src/server/master/handlers/capture-handler.ts +20 -0
  119. package/src/server/master/handlers/index.ts +4 -0
  120. package/src/server/master/handlers/ping-handler.ts +6 -0
  121. package/src/server/master/handlers/static-handler.ts +18 -0
  122. package/src/server/master/handlers/stories-handler.ts +20 -0
  123. package/src/server/master/master.ts +10 -27
  124. package/src/server/master/runner.ts +38 -132
  125. package/src/server/master/server.ts +210 -98
  126. package/src/server/master/start.ts +17 -41
  127. package/src/server/master/testsManager.ts +315 -0
  128. package/src/server/playwright/docker-file.ts +2 -2
  129. package/src/server/playwright/reporter.ts +386 -0
  130. package/src/server/selenium/internal.ts +23 -3
  131. package/src/server/selenium/selenoid.ts +5 -0
  132. package/src/server/shutdown.ts +19 -0
  133. package/src/server/stories.ts +1 -12
  134. package/src/server/ui-update.ts +46 -0
  135. package/src/server/utils.ts +40 -9
  136. package/src/server/worker/start.ts +1 -1
  137. 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.43",
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": "20.16.0",
212
- "yarn": "4.4.0"
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, StoryContextForEnhancers } from '@storybook/types';
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
- margin: '24px 44px 0',
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
- margin: 0,
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) => (