creevey 0.10.0-beta.4 → 0.10.0-beta.41

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 (227) hide show
  1. package/README.md +19 -41
  2. package/dist/client/addon/components/Addon.js +17 -7
  3. package/dist/client/addon/components/Addon.js.map +1 -1
  4. package/dist/client/addon/components/Panel.js +2 -2
  5. package/dist/client/addon/components/Panel.js.map +1 -1
  6. package/dist/client/addon/components/Tools.js +17 -7
  7. package/dist/client/addon/components/Tools.js.map +1 -1
  8. package/dist/client/addon/withCreevey.d.ts +2 -1
  9. package/dist/client/addon/withCreevey.js +11 -1
  10. package/dist/client/addon/withCreevey.js.map +1 -1
  11. package/dist/client/shared/components/ImagesView/BlendView.d.ts +1 -1
  12. package/dist/client/shared/components/ImagesView/BlendView.js +17 -7
  13. package/dist/client/shared/components/ImagesView/BlendView.js.map +1 -1
  14. package/dist/client/shared/components/ImagesView/SideBySideView.d.ts +1 -1
  15. package/dist/client/shared/components/ImagesView/SideBySideView.js +17 -7
  16. package/dist/client/shared/components/ImagesView/SideBySideView.js.map +1 -1
  17. package/dist/client/shared/components/ImagesView/SlideView.d.ts +1 -1
  18. package/dist/client/shared/components/ImagesView/SlideView.js +17 -7
  19. package/dist/client/shared/components/ImagesView/SlideView.js.map +1 -1
  20. package/dist/client/shared/components/ImagesView/SwapView.d.ts +1 -1
  21. package/dist/client/shared/components/ImagesView/SwapView.js +29 -7
  22. package/dist/client/shared/components/ImagesView/SwapView.js.map +1 -1
  23. package/dist/client/shared/components/PageHeader/ImagePreview.d.ts +1 -1
  24. package/dist/client/shared/components/PageHeader/ImagePreview.js +1 -0
  25. package/dist/client/shared/components/PageHeader/ImagePreview.js.map +1 -1
  26. package/dist/client/shared/components/PageHeader/PageHeader.js +20 -8
  27. package/dist/client/shared/components/PageHeader/PageHeader.js.map +1 -1
  28. package/dist/client/shared/components/ResultsPage.d.ts +1 -1
  29. package/dist/client/shared/components/ResultsPage.js +43 -13
  30. package/dist/client/shared/components/ResultsPage.js.map +1 -1
  31. package/dist/client/shared/creeveyClientApi.js +8 -1
  32. package/dist/client/shared/creeveyClientApi.js.map +1 -1
  33. package/dist/client/shared/helpers.d.ts +1 -3
  34. package/dist/client/shared/helpers.js +4 -19
  35. package/dist/client/shared/helpers.js.map +1 -1
  36. package/dist/client/web/CreeveyApp.js +42 -14
  37. package/dist/client/web/CreeveyApp.js.map +1 -1
  38. package/dist/client/web/CreeveyContext.d.ts +5 -0
  39. package/dist/client/web/CreeveyContext.js +20 -7
  40. package/dist/client/web/CreeveyContext.js.map +1 -1
  41. package/dist/client/web/CreeveyLoader.js +2 -2
  42. package/dist/client/web/CreeveyLoader.js.map +1 -1
  43. package/dist/client/web/CreeveyView/SideBar/Search.js +19 -9
  44. package/dist/client/web/CreeveyView/SideBar/Search.js.map +1 -1
  45. package/dist/client/web/CreeveyView/SideBar/SideBar.js +18 -7
  46. package/dist/client/web/CreeveyView/SideBar/SideBar.js.map +1 -1
  47. package/dist/client/web/CreeveyView/SideBar/SideBarFooter.js +60 -7
  48. package/dist/client/web/CreeveyView/SideBar/SideBarFooter.js.map +1 -1
  49. package/dist/client/web/CreeveyView/SideBar/SideBarHeader.js +17 -7
  50. package/dist/client/web/CreeveyView/SideBar/SideBarHeader.js.map +1 -1
  51. package/dist/client/web/CreeveyView/SideBar/SuiteLink.d.ts +2 -2
  52. package/dist/client/web/CreeveyView/SideBar/SuiteLink.js +18 -10
  53. package/dist/client/web/CreeveyView/SideBar/SuiteLink.js.map +1 -1
  54. package/dist/client/web/CreeveyView/SideBar/TestLink.js +18 -10
  55. package/dist/client/web/CreeveyView/SideBar/TestLink.js.map +1 -1
  56. package/dist/client/web/CreeveyView/SideBar/TestStatusIcon.d.ts +1 -1
  57. package/dist/client/web/CreeveyView/SideBar/TestsStatus.d.ts +1 -1
  58. package/dist/client/web/KeyboardEventsContext.d.ts +1 -8
  59. package/dist/client/web/KeyboardEventsContext.js +79 -64
  60. package/dist/client/web/KeyboardEventsContext.js.map +1 -1
  61. package/dist/client/web/assets/index-C47njyZV.js +802 -0
  62. package/dist/client/web/index.html +1 -1
  63. package/dist/client/web/index.js +17 -7
  64. package/dist/client/web/index.js.map +1 -1
  65. package/dist/client/web/themes.d.ts +2 -0
  66. package/dist/client/web/themes.js +22 -0
  67. package/dist/client/web/themes.js.map +1 -0
  68. package/dist/creevey.js +16 -9
  69. package/dist/creevey.js.map +1 -1
  70. package/dist/index.d.ts +1 -0
  71. package/dist/server/config.d.ts +1 -1
  72. package/dist/server/config.js +30 -7
  73. package/dist/server/config.js.map +1 -1
  74. package/dist/server/connection.d.ts +3 -0
  75. package/dist/server/connection.js +28 -0
  76. package/dist/server/connection.js.map +1 -0
  77. package/dist/server/docker.d.ts +1 -1
  78. package/dist/server/docker.js +56 -32
  79. package/dist/server/docker.js.map +1 -1
  80. package/dist/server/index.js +64 -11
  81. package/dist/server/index.js.map +1 -1
  82. package/dist/server/logger.d.ts +2 -1
  83. package/dist/server/logger.js +7 -3
  84. package/dist/server/logger.js.map +1 -1
  85. package/dist/server/master/api.js +1 -1
  86. package/dist/server/master/api.js.map +1 -1
  87. package/dist/server/master/pool.d.ts +4 -3
  88. package/dist/server/master/pool.js +13 -66
  89. package/dist/server/master/pool.js.map +1 -1
  90. package/dist/server/master/queue.d.ts +13 -0
  91. package/dist/server/master/queue.js +71 -0
  92. package/dist/server/master/queue.js.map +1 -0
  93. package/dist/server/master/runner.d.ts +3 -0
  94. package/dist/server/master/runner.js +78 -10
  95. package/dist/server/master/runner.js.map +1 -1
  96. package/dist/server/master/server.js +1 -1
  97. package/dist/server/master/server.js.map +1 -1
  98. package/dist/server/master/start.js +13 -11
  99. package/dist/server/master/start.js.map +1 -1
  100. package/dist/server/playwright/docker-file.d.ts +1 -1
  101. package/dist/server/playwright/docker-file.js +15 -6
  102. package/dist/server/playwright/docker-file.js.map +1 -1
  103. package/dist/server/playwright/docker.d.ts +2 -1
  104. package/dist/server/playwright/docker.js +10 -2
  105. package/dist/server/playwright/docker.js.map +1 -1
  106. package/dist/server/playwright/index-source.mjs +16 -0
  107. package/dist/server/playwright/internal.d.ts +6 -6
  108. package/dist/server/playwright/internal.js +143 -91
  109. package/dist/server/playwright/internal.js.map +1 -1
  110. package/dist/server/playwright/webdriver.d.ts +1 -1
  111. package/dist/server/playwright/webdriver.js +5 -8
  112. package/dist/server/playwright/webdriver.js.map +1 -1
  113. package/dist/server/providers/browser.js +6 -4
  114. package/dist/server/providers/browser.js.map +1 -1
  115. package/dist/server/providers/hybrid.js +1 -1
  116. package/dist/server/providers/hybrid.js.map +1 -1
  117. package/dist/server/reporters/creevey.d.ts +7 -0
  118. package/dist/server/reporters/creevey.js +63 -0
  119. package/dist/server/reporters/creevey.js.map +1 -0
  120. package/dist/server/reporters/index.d.ts +2 -0
  121. package/dist/server/reporters/index.js +16 -0
  122. package/dist/server/reporters/index.js.map +1 -0
  123. package/dist/server/reporters/junit.d.ts +16 -0
  124. package/dist/server/reporters/junit.js +165 -0
  125. package/dist/server/reporters/junit.js.map +1 -0
  126. package/dist/server/reporters/teamcity.d.ts +7 -0
  127. package/dist/server/reporters/teamcity.js +60 -0
  128. package/dist/server/reporters/teamcity.js.map +1 -0
  129. package/dist/server/selenium/internal.d.ts +3 -4
  130. package/dist/server/selenium/internal.js +127 -108
  131. package/dist/server/selenium/internal.js.map +1 -1
  132. package/dist/server/selenium/selenoid.js +8 -6
  133. package/dist/server/selenium/selenoid.js.map +1 -1
  134. package/dist/server/selenium/webdriver.d.ts +1 -1
  135. package/dist/server/selenium/webdriver.js +5 -9
  136. package/dist/server/selenium/webdriver.js.map +1 -1
  137. package/dist/server/telemetry.js +2 -2
  138. package/dist/server/testsFiles/parser.js +45 -5
  139. package/dist/server/testsFiles/parser.js.map +1 -1
  140. package/dist/server/utils.d.ts +19 -1
  141. package/dist/server/utils.js +87 -8
  142. package/dist/server/utils.js.map +1 -1
  143. package/dist/server/webdriver.d.ts +5 -4
  144. package/dist/server/webdriver.js +23 -10
  145. package/dist/server/webdriver.js.map +1 -1
  146. package/dist/server/worker/chai-image.d.ts +1 -2
  147. package/dist/server/worker/chai-image.js +4 -3
  148. package/dist/server/worker/chai-image.js.map +1 -1
  149. package/dist/server/worker/context.d.ts +3 -0
  150. package/dist/server/worker/context.js +15 -0
  151. package/dist/server/worker/context.js.map +1 -0
  152. package/dist/server/worker/match-image.d.ts +4 -4
  153. package/dist/server/worker/match-image.js +7 -4
  154. package/dist/server/worker/match-image.js.map +1 -1
  155. package/dist/server/worker/start.js +47 -73
  156. package/dist/server/worker/start.js.map +1 -1
  157. package/dist/shared/index.d.ts +1 -1
  158. package/dist/types.d.ts +46 -10
  159. package/dist/types.js +2 -0
  160. package/dist/types.js.map +1 -1
  161. package/docs/cli.md +12 -0
  162. package/docs/config.md +179 -165
  163. package/docs/storybook.md +60 -0
  164. package/docs/tests.md +50 -45
  165. package/package.json +64 -63
  166. package/src/client/addon/components/Panel.tsx +2 -2
  167. package/src/client/addon/withCreevey.ts +10 -2
  168. package/src/client/shared/components/ImagesView/SwapView.tsx +18 -0
  169. package/src/client/shared/components/PageHeader/ImagePreview.tsx +1 -0
  170. package/src/client/shared/components/PageHeader/PageHeader.tsx +4 -2
  171. package/src/client/shared/components/ResultsPage.tsx +31 -8
  172. package/src/client/shared/creeveyClientApi.ts +9 -1
  173. package/src/client/shared/helpers.ts +4 -24
  174. package/src/client/web/CreeveyApp.tsx +27 -8
  175. package/src/client/web/CreeveyContext.tsx +9 -0
  176. package/src/client/web/CreeveyLoader.tsx +1 -1
  177. package/src/client/web/CreeveyView/SideBar/Search.tsx +3 -3
  178. package/src/client/web/CreeveyView/SideBar/SideBar.tsx +1 -0
  179. package/src/client/web/CreeveyView/SideBar/SideBarFooter.tsx +37 -6
  180. package/src/client/web/CreeveyView/SideBar/SuiteLink.tsx +3 -5
  181. package/src/client/web/CreeveyView/SideBar/TestLink.tsx +2 -4
  182. package/src/client/web/KeyboardEventsContext.tsx +61 -73
  183. package/src/client/web/themes.ts +24 -0
  184. package/src/creevey.ts +16 -10
  185. package/src/server/config.ts +30 -7
  186. package/src/server/connection.ts +26 -0
  187. package/src/server/docker.ts +63 -34
  188. package/src/server/index.ts +72 -14
  189. package/src/server/logger.ts +6 -2
  190. package/src/server/master/api.ts +1 -1
  191. package/src/server/master/pool.ts +23 -59
  192. package/src/server/master/queue.ts +77 -0
  193. package/src/server/master/runner.ts +96 -10
  194. package/src/server/master/server.ts +1 -1
  195. package/src/server/master/start.ts +16 -11
  196. package/src/server/playwright/docker-file.ts +18 -6
  197. package/src/server/playwright/docker.ts +16 -3
  198. package/src/server/playwright/index-source.mjs +16 -0
  199. package/src/server/playwright/internal.ts +182 -111
  200. package/src/server/playwright/webdriver.ts +6 -9
  201. package/src/server/providers/browser.ts +6 -4
  202. package/src/server/providers/hybrid.ts +1 -1
  203. package/src/server/reporters/creevey.ts +71 -0
  204. package/src/server/reporters/index.ts +11 -0
  205. package/src/server/reporters/junit.ts +205 -0
  206. package/src/server/reporters/teamcity.ts +74 -0
  207. package/src/server/selenium/internal.ts +131 -116
  208. package/src/server/selenium/selenoid.ts +8 -6
  209. package/src/server/selenium/webdriver.ts +6 -10
  210. package/src/server/telemetry.ts +2 -2
  211. package/src/server/testsFiles/parser.ts +52 -4
  212. package/src/server/utils.ts +97 -9
  213. package/src/server/webdriver.ts +24 -16
  214. package/src/server/worker/chai-image.ts +4 -4
  215. package/src/server/worker/context.ts +14 -0
  216. package/src/server/worker/match-image.ts +12 -8
  217. package/src/server/worker/start.ts +51 -86
  218. package/src/shared/index.ts +1 -1
  219. package/src/types.ts +50 -11
  220. package/types/global.d.ts +1 -0
  221. package/.yarnrc.yml +0 -1
  222. package/chromatic.config.json +0 -5
  223. package/dist/client/web/assets/index-DkmZfG9C.js +0 -591
  224. package/dist/server/reporter.d.ts +0 -26
  225. package/dist/server/reporter.js +0 -108
  226. package/dist/server/reporter.js.map +0 -1
  227. package/src/server/reporter.ts +0 -138
package/docs/config.md CHANGED
@@ -1,212 +1,226 @@
1
- ## Config/Options
1
+ # Creevey Configuration Examples
2
2
 
3
- ### CLI Options
3
+ Creevey is highly configurable and can be tailored to your specific needs. Here are some examples of how to configure Creevey for your Storybook.
4
4
 
5
- - `--config` — Specify path to config file. Default `.creevey/config.js` or `creevey.config.js`
6
- - `--ui` — Start runner web server
7
- - `--update` — Approve all images from `report` directory
8
- - `--port` — Specify port for web server. Default `3000`
9
- - `--reportDir` — Path where reports will be stored
10
- - `--screenDir` — Path where reference images are located
11
- - `--debug` — Enable debug output
5
+ ## Zero Configuration
12
6
 
13
- ### Creevey config
7
+ The simplest way to get started with Creevey, just run it without any configuration:
14
8
 
15
- In default configuration Creevey take screenshots of `#storybook-root` element only for chrome browser in one concurrent instance, to run tests in different browsers or speedup tests and run in parallel, you need to define config file `.creevey/config.js`
9
+ ```bash
10
+ yarn creevey -s
11
+ ```
12
+
13
+ This will start Creevey with default settings, using Chrome as the browser and also start Storybook hosted at `http://localhost:6006`. Adding `--ui` flag will start the web server for the UI Runner.
14
+
15
+ **NOTE** By default, Creevey uses Selenium WebDriver, but it's done for backward compatibility and it's recommended to define webdriver explicitly in the configuration.
16
16
 
17
17
  ```ts
18
- module.exports = {
19
- browsers: {
20
- chrome: {
21
- browserName: 'chrome',
22
- // Define initial viewport size
23
- viewport: { width: 1024, height: 720 },
24
- // Increase parallel sessions
25
- limit: 2,
26
- },
27
- firefox: {
28
- browserName: 'firefox',
29
- viewport: { width: 1024, height: 720 },
30
- },
31
- },
18
+ // creevey.config.ts
19
+ import { SeleniumWebdriver } from 'creevey/selenium';
20
+
21
+ const config = {
22
+ webdriver: SeleniumWebdriver,
23
+ };
24
+
25
+ // or use Playwright instead
26
+
27
+ import { PlaywrightWebdriver } from 'creevey/playwright';
28
+
29
+ const config = {
30
+ webdriver: PlaywrightWebdriver,
32
31
  };
33
32
  ```
34
33
 
35
- ### All possible config options
34
+ ## Basic Configuration
36
35
 
37
- :warning: **WARN** :warning: This config is just an example with all possible options. :warning: **WARN** :warning:
36
+ The minimal configuration to test your stories might be:
38
37
 
39
38
  ```ts
40
- const path = require('path');
39
+ // creevey.config.ts
40
+ import { CreeveyConfig } from 'creevey';
41
+ import { PlaywrightWebdriver } from 'creevey/playwright';
42
+
43
+ const config: CreeveyConfig = {
44
+ webdriver: PlaywrightWebdriver,
41
45
 
42
- module.exports = {
43
- // Specify custom Selenium Grid url (see usage below)
44
- // In most cases you don't need this option
45
- gridUrl: '<gridUrl>/wd/hub',
46
+ // The URL where your Storybook is hosted
47
+ storybookUrl: 'http://localhost:9000',
48
+
49
+ // Define which browsers to use for testing
50
+ browsers: {
51
+ chromium: {
52
+ // The browser type name which will be used by Playwright
53
+ browserName: 'chromium',
54
+ // Default viewport dimensions
55
+ viewport: { width: 1024, height: 768 },
56
+ // Limit of retries for failed tests
57
+ maxRetries: 2,
58
+ },
59
+ },
60
+ };
46
61
 
47
- // Default Storybook url
48
- storybookUrl: 'http://localhost:6006',
62
+ export default config;
63
+ ```
49
64
 
50
- // Where original images are stored
51
- screenDir: path.join(__dirname, '../images'),
65
+ ## Multiple Browsers Configuration
52
66
 
53
- // Report directory that contains data from previous runs
54
- reportDir: path.join(__dirname, '../report'),
67
+ It's possible to est your stories across different browsers:
55
68
 
56
- // Pixelmatch options
57
- diffOptions: { threshold: 0.1 },
69
+ ```ts
70
+ // creevey.config.ts
71
+ import { CreeveyConfig } from 'creevey';
72
+ import { PlaywrightWebdriver } from 'creevey/playwright';
58
73
 
59
- // How many times test should be retried before to consider it as failed
60
- maxRetries: 2,
74
+ const config: CreeveyConfig = {
75
+ webdriver: PlaywrightWebdriver,
61
76
 
62
- // Describe browsers and their options
63
77
  browsers: {
64
- // Shorthand declarations of browsers
65
- chrome: true,
66
- ff: 'firefox',
67
-
68
- otherChrome: {
69
- browserName: 'chrome',
70
- // Define initial viewport size
71
- viewport: { width: 1024, height: 720 },
72
- // Increase parallel sessions
78
+ chromium: {
79
+ browserName: 'chromium',
80
+ // Amount of parallel browser sessions
73
81
  limit: 2,
74
- /* Also you can define any browser capabilities here */
75
- version: '86.0',
76
- // It's possible to set Storybook's globals
77
- // https://github.com/storybookjs/storybook/blob/v6.0.0/docs/essentials/toolbars-and-globals.md
78
- // NOTE: This is an experimental feature and will be replaced in future
79
- _storybookGlobals: {
80
- myTheme: 'dark',
81
- },
82
82
  },
83
-
84
- // You can override some global options for specific browser
85
- ie11: {
86
- browserName: 'internet explorer',
87
- // Like user another Selenium Grid url
88
- gridUrl: '<anotherGridUrl>/wd/hub',
89
- // Or use different storybook instance
90
- storybookUrl: 'http://mystoryhost:6007',
91
- // And use you own docker image
92
- // By default Creevey will use selenoid image according browser name and version:
93
- // `selenoid/${browserName}:${version ?? 'latest'}` image
94
- dockerImage: 'microsoft/ie:11.0',
83
+ firefox: {
84
+ browserName: 'firefox',
85
+ limit: 2,
95
86
  },
96
87
  },
88
+ };
89
+
90
+ export default config;
91
+ ```
92
+
93
+ ## Test stories with different themes
94
+
95
+ Test your components with different themes:
97
96
 
98
- // You may want to do something before tests started (for example start browserstack-local)
99
- hooks: {
100
- async before() {
101
- /* ... */
97
+ ```ts
98
+ // creevey.config.ts
99
+ import { CreeveyConfig } from 'creevey';
100
+ import { PlaywrightWebdriver } from 'creevey/playwright';
101
+
102
+ const config: CreeveyConfig = {
103
+ webdriver: PlaywrightWebdriver,
104
+ browsers: {
105
+ dark: {
106
+ browserName: 'chromium',
107
+ // Define a storybook globals which will be applied to the stories
108
+ _storybookGlobals: {
109
+ theme: 'dark',
110
+ },
102
111
  },
103
- async after() {
104
- /* ... */
112
+ light: {
113
+ browserName: 'chromium',
114
+ _storybookGlobals: {
115
+ theme: 'light',
116
+ },
105
117
  },
106
118
  },
107
119
  };
120
+
121
+ export default config;
108
122
  ```
109
123
 
110
- ### Storybook parameters
124
+ ## Using dedicated Selenium Grid server
111
125
 
112
- Also you could define parameters on `global`, `kind` or `story` levels. All these parameters are deeply merged by Storybook for each story. But bear in mind when you define skip option as an array Storybook treats it as primitive value and doesn't merge with other skip options.
126
+ Use Selenium Grid for distributed testing:
113
127
 
114
- ```tsx
115
- // .storybook/preview.tsx
116
- export const parameters = {
117
- creevey: {
118
- // Skip all *hover tests in IE11 on the global level
119
- skip: {
120
- "hovers don't work in ie11": { in: 'ie11', tests: /.*hover$/ },
128
+ ```ts
129
+ // creevey.config.ts
130
+ import { CreeveyConfig } from 'creevey';
131
+ import { SeleniumWebdriver } from 'creevey/selenium';
132
+
133
+ const config: CreeveyConfig = {
134
+ webdriver: SeleniumWebdriver,
135
+ // Selenium Grid connection settings
136
+ gridUrl: 'http://selenium-hub:4444/wd/hub',
137
+ browsers: {
138
+ chrome: {
139
+ browserName: 'chrome',
140
+ // You can define any additional selenium capabilities here
141
+ // https://w3c.github.io/webdriver/#capabilities
142
+ seleniumCapabilities: {
143
+ browserVersion: '128.0',
144
+ platformName: 'linux',
145
+ },
121
146
  },
122
147
  },
123
148
  };
149
+
150
+ export default config;
124
151
  ```
125
152
 
126
- ```tsx
127
- import React from 'react';
128
- import { Meta, Story } from '@storybook/react';
129
- import { CreeveyMeta, CreeveyStory } from 'creevey';
130
- import MyComponent from './src/components/MyComponent';
131
-
132
- export default {
133
- title: 'MyComponent'
134
- parameters: {
135
- creevey: {
136
- // You could skip some browsers/stories or even specific tests
137
- skip: {
138
- "`MyComponent` doesn't support ie11": { in: 'ie11' },
139
- "Loading stories are flaky in firefox": { in: 'firefox', stories: 'Loading' },
140
- "`MyComponent` hovering doesn't work correctly": {
141
- in: ['firefox', 'chrome'],
142
- tests: /.*hover$/,
143
- },
153
+ ## Playwright configuration options
154
+
155
+ Leverage Playwright for testing:
156
+
157
+ ```ts
158
+ // creevey.config.ts
159
+ import { CreeveyConfig } from 'creevey';
160
+ import { PlaywrightWebdriver } from 'creevey/playwright';
161
+
162
+ const config: CreeveyConfig = {
163
+ webdriver: PlaywrightWebdriver,
164
+ browsers: {
165
+ chromium: {
166
+ browserName: 'chromium',
167
+ // Playwright-specific options
168
+ // https://playwright.dev/docs/api/class-browsertype#browser-type-launch-server
169
+ playwrightOptions: {
170
+ headless: false,
171
+ channel: 'chrome-canary',
172
+ slowMo: 50, // Slow down Playwright operations by 50ms
144
173
  },
145
174
  },
146
175
  },
147
- } as Meta & CreeveyMeta;
148
-
149
- export const Basic: Story & CreeveyStory = () => <MyComponent />;
150
- Basic.parameters = {
151
- creevey: {
152
- captureElement: '.container',
153
- // elements to ignore in capturing screenshot
154
- ignoreElements: ['button', '.local-time'],
155
- // Delay before test starts in ms
156
- delay: 1000,
157
- tests: {
158
- /* ... */
159
- },
160
- },
161
176
  };
177
+
178
+ export default config;
162
179
  ```
163
180
 
164
- ### `skip` option examples:
181
+ ## Advanced Configuration
182
+
183
+ Comprehensive example combining multiple features and additional options:
165
184
 
166
185
  ```ts
167
- interface SkipOption {
168
- in?: string | string[] | RegExp;
169
- kinds?: string | string[] | RegExp;
170
- stories?: string | string[] | RegExp;
171
- tests?: string | string[] | RegExp;
172
- }
173
-
174
- type SkipOptions = boolean | string | Record<string, SkipOption | SkipOption[]>;
175
- ```
186
+ // creevey.config.ts
187
+ import path from 'path';
188
+ import MochaJUnitReporter from 'mocha-junit-reporter';
189
+ import { CreeveyConfig } from 'creevey';
190
+ import { PlaywrightWebdriver } from 'creevey/playwright';
191
+
192
+ const config: CreeveyConfig = {
193
+ webdriver: PlaywrightWebdriver,
194
+
195
+ // It's possible to resolve Storybook URL at the runtime
196
+ resolveStorybookUrl: () =>
197
+ fetch('https://example.com/resolve-ip')
198
+ .then((res) => res.text())
199
+ .then((data) => `http://${data}:6006`),
200
+
201
+ // Define custom reference screenshots directory
202
+ screenDir: path.join(process.cwd(), 'screenshots'),
203
+
204
+ // Define custom report directory
205
+ reportDir: path.join(process.cwd(), 'reports'),
206
+
207
+ // Define path where Creevey tests are located
208
+ testDir: path.join(process.cwd(), 'tests'),
209
+
210
+ // You can use any Mocha-like reporter
211
+ reporter: MochaJUnitReporter,
176
212
 
177
- - Skip all stories for all browsers:
178
- - `skip: true`
179
- - `skip: 'Skip reason message'`
180
- - `skip: { 'Skip reason message': true }`
181
- - Skip all stories for specific browsers:
182
- - `skip: { 'Skip reason message': { in: 'ie11' } }`
183
- - `skip: { 'Skip reason message': { in: ['ie11', 'chrome'] } }`
184
- - `skip: { 'Skip reason message': { in: /^fire.*/ } }`
185
- - Skip all stories in specific kinds:
186
- - `skip: { 'Skip reason message': { kinds: 'Button' } }`
187
- - `skip: { 'Skip reason message': { kinds: ['Button', 'Input'] } }`
188
- - `skip: { 'Skip reason message': { kinds: /.*Modal$/ } }`
189
- - Skip all tests in specific stories:
190
- - `skip: { 'Skip reason message': { stories: 'simple' } }`
191
- - `skip: { 'Skip reason message': { stories: ['simple', 'special'] } }`
192
- - `skip: { 'Skip reason message': { stories: /.*large$/ } }`
193
- - Skip specific tests:
194
- - `skip: { 'Skip reason message': { tests: 'click' } }`
195
- - `skip: { 'Skip reason message': { tests: ['hover', 'click'] } }`
196
- - `skip: { 'Skip reason message': { tests: /^press.*$/ } }`
197
- - Multiple skip options:
198
- - for one reason
199
- ```
200
- skip: {
201
- "reason": [{ /* ... */ }, { /* ... */ }],
202
- }
203
- ```
204
- - for several reasons
205
- ```
206
- skip: {
207
- "reason 1": { /* ... */ },
208
- "reason 2": { /* ... */ },
209
- }
210
- ```
211
-
212
- NOTE: If you try to skip stories by story name, the storybook name format will be used (For more info see [storybook-export-vs-name-handling](https://storybook.js.org/docs/formats/component-story-format/#storybook-export-vs-name-handling))
213
+ // Pixelmatch options
214
+ diffOptions: { threshold: 0.1 },
215
+
216
+ // Regex pattern to match test files
217
+ testsRegex: /\.creevey\.ts$/,
218
+
219
+ // Disable using docker, to start browsers locally, it's useful for CI
220
+ useDocker: process.env.CI,
221
+
222
+ browsers: {
223
+ /* ... */
224
+ },
225
+ };
226
+ ```
@@ -0,0 +1,60 @@
1
+ ## Creevey Storybook Parameters
2
+
3
+ Creevey allows you to customize how stories will be captured. You could define parameters on `global`, `kind` or `story` levels. All these parameters are deeply merged by Storybook for each story.
4
+
5
+ ```ts
6
+ // .storybook/preview.tsx
7
+ export const parameters = {
8
+ creevey: {
9
+ // Global parameters are applied to all stories
10
+ captureElement: '#storybook-root',
11
+ },
12
+ };
13
+ ```
14
+
15
+ ```ts
16
+ // stories/MyModal.stories.tsx
17
+ import React from 'react';
18
+ import { Meta, StoryObj } from '@storybook/react';
19
+ import { CreeveyMeta, CreeveyStory } from 'creevey';
20
+ import MyModal from './src/components/MyModal';
21
+
22
+ const Kind: Meta<typeof MyModal> = {
23
+ title: 'MyModal',
24
+ component: MyModal,
25
+ parameters: {
26
+ creevey: {
27
+ // It's possible to add additional delay before capturing screenshot
28
+ delay: 1000,
29
+
30
+ // For capturing the whole browser viewport, you can define `null` instead of css selector.
31
+ captureElement: null,
32
+
33
+ // You can skip some stories from capturing, by defining `skip` option:
34
+ // skip: { "The reason why story is skipped": { in: 'chrome', stories: 'Loading' } }
35
+ // - `in` - browser name, regex or array of browser names, which are defined in the Creevey config
36
+ // - `stories` - story name, regex or array of story names
37
+ // - `tests` - test name, regex or array of test names
38
+ // NOTE: If you try to skip stories by story name, the storybook name format will be used
39
+ // For more info see [storybook-export-vs-name-handling](https://storybook.js.org/docs/formats/component-story-format/#storybook-export-vs-name-handling))
40
+ skip: {
41
+ "`MyModal` doesn't support ie11": { in: 'ie11' },
42
+ 'Loading stories are flaky in firefox': { in: 'firefox', stories: 'Loading' },
43
+ "`MyModal` hovering doesn't work correctly": {
44
+ in: ['firefox', 'chrome'],
45
+ tests: /.*hover$/,
46
+ },
47
+ },
48
+ },
49
+ },
50
+ };
51
+
52
+ export default Kind;
53
+
54
+ export const Basic: StoryObj<typeof MyModal> = {
55
+ creevey: {
56
+ // Lastly some elements can be ignored in capturing screenshot
57
+ ignoreElements: ['button', '.local-time'],
58
+ },
59
+ };
60
+ ```
package/docs/tests.md CHANGED
@@ -1,63 +1,68 @@
1
- ## Write tests
1
+ ## Write interactive screenshot tests
2
2
 
3
- By default Creevey generate for each story very simple screenshot test. In most cases it would be enough to test your UI. But you may want to do some interactions and capture one or multiple screenshots with different states of your story. For this case you could write custom tests, like this
3
+ In most cases following Storybook's ideology of [writing stories](https://storybook.js.org/docs/get-started/whats-a-story) is enough to test your UI components. Where each component has a separate stories file with its different states. But sometimes you might have pretty complicated components with a lot of interactions and internal states. In this case, you can write tests for your stories.
4
4
 
5
- ```tsx
6
- import React from 'react';
7
- import { Story } from '@storybook/react';
8
- import { CreeveyStory } from 'creevey';
9
- import MyComponent from './src/components/MyComponent';
5
+ There are two different ways how to write interactive tests with Creevey:
10
6
 
11
- export default { title: 'MyComponent' };
7
+ ### Write tests in `*.creevey.ts` files
12
8
 
13
- export const Basic: Story & CreeveyStory = () => <MyComponent />;
14
- Basic.parameters = {
15
- creevey: {
16
- captureElement: '#storybook-root',
17
- tests: {
18
- async click() {
19
- await this.browser.actions().click(this.captureElement).perform();
9
+ It's the recommended way to write tests. It allows you to run these tests by Creevey itself and utilize webdriver benefits. The crucial part of it is webdriver action calls are more close to real user interactions and mitigate flakiness and false-negative results. Here is a simple example of how to write tests in `*.creevey.ts` files
20
10
 
21
- await this.expect(await this.takeScreenshot()).to.matchImage('clicked component');
22
- },
23
- },
24
- },
25
- };
11
+ ```ts
12
+ // stories/MyComponent.creevey.ts
13
+ import { kind, story, test } from 'creevey';
14
+
15
+ kind('MyComponent', () => {
16
+ story('Story', ({ setStoryParameters }) => {
17
+ // It's possible to pass Creevey parameters to story
18
+ setStoryParameters({
19
+ captureElement: 'span[data-test-id~="x"]',
20
+ ignoreElements: [],
21
+ });
22
+
23
+ test('idle', async (context) => {
24
+ await context.matchImage(await context.takeScreenshot());
25
+ });
26
+
27
+ test('input', async (context) => {
28
+ await context.webdriver.keyboard.press('Tab');
29
+ const focus = await context.takeScreenshot();
30
+ await context.webdriver.keyboard.type('Hello Creevey');
31
+ const input = await context.takeScreenshot();
32
+ await context.matchImages({ focus, input });
33
+ });
34
+ });
35
+ });
26
36
  ```
27
37
 
28
- NOTE: Here you define story parameters with simple test `click`. Where you setup capturing element `#storybook-root` then click on that element and taking screenshot to assert it. `this.browser` allow you to access to native selenium webdriver instance you could check [API here](https://www.selenium.dev/selenium/docs/api/javascript/module/selenium-webdriver/index_exports_WebDriver.html).
38
+ In the example above, we used Playwright API to interact with the story. But Creevey also supports Selenium webdriver. And in that case `context.webdriver` will be an instance of Selenium webdriver. Obviously Selenium API is different from Playwright.
29
39
 
30
- You also could write more powerful tests with asserting multiple screenshots
40
+ ### Using Storybook's `play` function
31
41
 
32
- ```tsx
33
- import React from 'react';
34
- import { CSFStory } from 'creevey';
35
- import MyForm from './src/components/MyForm';
42
+ Storybook allows you to write tests in the story file itself by using [`play` function](https://storybook.js.org/docs/writing-tests/component-testing). It's a good way to write simple tests. But there are couple drawbacks of this approach:
36
43
 
37
- export default { title: 'MyForm' };
44
+ - You can have only one test per story. Which is not a big deal, but sometimes you might not want to have multiple stories with the same markup.
45
+ - Tests are running in browser environment and use https://testing-library.com API under the hood. It's good for unit tests, but might not be suitable for visual regression tests, because testing-library relies on DOM API and not even close to real user interactions. For example, you might have a button that could be visible for user, but it's covered by some other transparent element. With testing-library the button easily accessible and clickable, but the user can't interact with it.
38
46
 
39
- export const Basic: CSFStory<JSX.Element> = () => <MyForm />;
40
- Basic.story = {
41
- parameters: {
42
- creevey: {
43
- captureElement: '#storybook-root',
44
- delay: 1000,
45
- tests: {
46
- async submit() {
47
- const input = await this.browser.findElement({ css: '.my-input' });
47
+ Here is an example of how to write tests using Storybook's `play` function:
48
48
 
49
- const empty = await this.takeScreenshot();
49
+ ```tsx
50
+ // stories/MyComponent.stories.tsx
51
+ import React from 'react';
52
+ import { Meta, StoryObj } from '@storybook/react';
53
+ import { fireEvent, within } from '@storybook/test';
54
+ import MyComponent from './src/components/MyComponent';
50
55
 
51
- await this.browser.actions().click(input).sendKeys('Hello Creevey').sendKeys(this.keys.ENTER).perform();
56
+ export default {
57
+ title: 'MyComponent',
58
+ component: MyComponent,
59
+ };
52
60
 
53
- const submitted = await this.takeScreenshot();
61
+ export const Basic: StoryObj<typeof MyComponent> = {
62
+ play: async ({ canvasElement }) => {
63
+ const slider = await within(canvasElement).findByTestId('slider');
54
64
 
55
- await this.expect({ empty, submitted }).to.matchImages();
56
- },
57
- },
58
- },
65
+ await fireEvent.change(slider, { target: { value: 50 } });
59
66
  },
60
67
  };
61
68
  ```
62
-
63
- NOTE: In this example I fill some simple form and submit it. Also as you could see, I taking two different screenshots `empty` and `submitted` and assert these in the end.