creevey 0.9.0-beta.2 → 0.9.0-beta.20

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 (226) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/.yarnrc.yml +1 -0
  3. package/CHANGELOG.md +51 -0
  4. package/README.md +9 -1
  5. package/addon/README.md +3 -0
  6. package/addon/package.json +5 -0
  7. package/docs/config.md +29 -26
  8. package/jest.config.js +6 -0
  9. package/lib/cjs/cli.js +1 -0
  10. package/lib/cjs/client/addon/Manager.js +170 -390
  11. package/lib/cjs/client/addon/components/Addon.js +17 -45
  12. package/lib/cjs/client/addon/components/Icons.js +12 -14
  13. package/lib/cjs/client/addon/components/Panel.js +21 -30
  14. package/lib/cjs/client/addon/components/TestSelect.js +20 -31
  15. package/lib/cjs/client/addon/components/Tools.js +35 -65
  16. package/lib/cjs/client/addon/decorator.js +1 -4
  17. package/lib/cjs/client/addon/index.js +27 -0
  18. package/lib/cjs/client/addon/preset.js +3 -76
  19. package/lib/cjs/client/addon/preview.js +11 -0
  20. package/lib/cjs/client/addon/readyForCapture.js +1 -4
  21. package/lib/cjs/client/addon/register.js +43 -82
  22. package/lib/cjs/client/addon/utils.js +4 -8
  23. package/lib/cjs/client/addon/withCreevey.js +145 -404
  24. package/lib/cjs/client/shared/components/ImagesView/BlendView.js +25 -35
  25. package/lib/cjs/client/shared/components/ImagesView/ImagesView.js +29 -41
  26. package/lib/cjs/client/shared/components/ImagesView/SideBySideView.js +46 -83
  27. package/lib/cjs/client/shared/components/ImagesView/SlideView.js +39 -67
  28. package/lib/cjs/client/shared/components/ImagesView/SwapView.js +26 -57
  29. package/lib/cjs/client/shared/components/ImagesView/index.js +9 -14
  30. package/lib/cjs/client/shared/components/PageFooter/PageFooter.js +13 -16
  31. package/lib/cjs/client/shared/components/PageFooter/Paging.js +16 -37
  32. package/lib/cjs/client/shared/components/PageHeader/ImagePreview.js +42 -34
  33. package/lib/cjs/client/shared/components/PageHeader/PageHeader.js +40 -84
  34. package/lib/cjs/client/shared/components/ResultsPage.js +42 -99
  35. package/lib/cjs/client/shared/creeveyClientApi.js +56 -93
  36. package/lib/cjs/client/shared/helpers.js +149 -274
  37. package/lib/cjs/client/shared/viewMode.js +5 -9
  38. package/lib/cjs/client/web/192.js +1 -0
  39. package/lib/cjs/client/web/632.js +43 -0
  40. package/lib/cjs/client/web/794.js +1 -0
  41. package/lib/cjs/client/web/main.js +79 -38
  42. package/lib/cjs/client/web/main.js.LICENSE.txt +34 -0
  43. package/lib/cjs/creevey.js +15 -30
  44. package/lib/cjs/index.js +0 -15
  45. package/lib/cjs/server/config.js +16 -36
  46. package/lib/cjs/server/docker.js +8 -34
  47. package/lib/cjs/server/index.js +9 -34
  48. package/lib/cjs/server/logger.js +7 -20
  49. package/lib/cjs/server/master/api.js +1 -14
  50. package/lib/cjs/server/master/index.js +25 -49
  51. package/lib/cjs/server/master/master.js +6 -21
  52. package/lib/cjs/server/master/pool.js +10 -53
  53. package/lib/cjs/server/master/runner.js +65 -105
  54. package/lib/cjs/server/master/server.js +10 -29
  55. package/lib/cjs/server/messages.js +14 -62
  56. package/lib/cjs/server/selenium/browser.js +149 -185
  57. package/lib/cjs/server/selenium/index.js +0 -4
  58. package/lib/cjs/server/selenium/selenoid.js +18 -44
  59. package/lib/cjs/server/stories.js +35 -57
  60. package/lib/cjs/server/storybook/providers/browser.js +15 -29
  61. package/lib/cjs/server/storybook/providers/hybrid.js +16 -37
  62. package/lib/cjs/server/telemetry.js +167 -0
  63. package/lib/cjs/server/testsFiles/parser.js +3 -19
  64. package/lib/cjs/server/testsFiles/register.js +8 -14
  65. package/lib/cjs/server/update.js +4 -25
  66. package/lib/cjs/server/utils.js +35 -76
  67. package/lib/cjs/server/worker/chai-image.js +1 -27
  68. package/lib/cjs/server/worker/helpers.js +2 -12
  69. package/lib/cjs/server/worker/index.js +1 -3
  70. package/lib/cjs/server/worker/reporter.js +16 -43
  71. package/lib/cjs/server/worker/worker.js +32 -72
  72. package/lib/cjs/shared/index.js +87 -0
  73. package/lib/cjs/shared/serializeRegExp.js +34 -0
  74. package/lib/cjs/types.js +11 -20
  75. package/lib/esm/cli.js +1 -1
  76. package/lib/esm/client/addon/Manager.js +170 -381
  77. package/lib/esm/client/addon/components/Addon.js +15 -34
  78. package/lib/esm/client/addon/components/Icons.js +10 -6
  79. package/lib/esm/client/addon/components/Panel.js +20 -18
  80. package/lib/esm/client/addon/components/TestSelect.js +19 -23
  81. package/lib/esm/client/addon/components/Tools.js +33 -49
  82. package/lib/esm/client/addon/decorator.js +1 -1
  83. package/lib/esm/client/addon/index.js +2 -0
  84. package/lib/esm/client/addon/preset.js +2 -56
  85. package/lib/esm/client/addon/preview.js +5 -0
  86. package/lib/esm/client/addon/readyForCapture.js +1 -3
  87. package/lib/esm/client/addon/register.js +41 -67
  88. package/lib/esm/client/addon/utils.js +3 -7
  89. package/lib/esm/client/addon/withCreevey.js +142 -388
  90. package/lib/esm/client/shared/components/ImagesView/BlendView.js +22 -18
  91. package/lib/esm/client/shared/components/ImagesView/ImagesView.js +27 -25
  92. package/lib/esm/client/shared/components/ImagesView/SideBySideView.js +43 -63
  93. package/lib/esm/client/shared/components/ImagesView/SlideView.js +36 -47
  94. package/lib/esm/client/shared/components/ImagesView/SwapView.js +23 -40
  95. package/lib/esm/client/shared/components/PageFooter/PageFooter.js +12 -8
  96. package/lib/esm/client/shared/components/PageFooter/Paging.js +15 -29
  97. package/lib/esm/client/shared/components/PageHeader/ImagePreview.js +40 -25
  98. package/lib/esm/client/shared/components/PageHeader/PageHeader.js +38 -66
  99. package/lib/esm/client/shared/components/ResultsPage.js +39 -75
  100. package/lib/esm/client/shared/creeveyClientApi.js +56 -90
  101. package/lib/esm/client/shared/helpers.js +133 -230
  102. package/lib/esm/client/shared/viewMode.js +4 -4
  103. package/lib/esm/client/web/192.js +1 -0
  104. package/lib/esm/client/web/632.js +43 -0
  105. package/lib/esm/client/web/794.js +1 -0
  106. package/lib/esm/client/web/index.html +19 -0
  107. package/lib/esm/client/web/main.js +79 -0
  108. package/lib/esm/client/web/main.js.LICENSE.txt +34 -0
  109. package/lib/esm/creevey.js +13 -16
  110. package/lib/esm/index.js +1 -4
  111. package/lib/esm/server/config.js +9 -16
  112. package/lib/esm/server/docker.js +6 -14
  113. package/lib/esm/server/index.js +8 -22
  114. package/lib/esm/server/logger.js +0 -1
  115. package/lib/esm/server/master/api.js +0 -9
  116. package/lib/esm/server/master/index.js +25 -35
  117. package/lib/esm/server/master/master.js +2 -7
  118. package/lib/esm/server/master/pool.js +8 -41
  119. package/lib/esm/server/master/runner.js +64 -90
  120. package/lib/esm/server/master/server.js +9 -11
  121. package/lib/esm/server/messages.js +8 -42
  122. package/lib/esm/server/selenium/browser.js +147 -163
  123. package/lib/esm/server/selenium/selenoid.js +16 -27
  124. package/lib/esm/server/stories.js +34 -46
  125. package/lib/esm/server/storybook/providers/browser.js +12 -17
  126. package/lib/esm/server/storybook/providers/hybrid.js +11 -22
  127. package/lib/esm/server/telemetry.js +160 -0
  128. package/lib/esm/server/testsFiles/parser.js +0 -6
  129. package/lib/esm/server/testsFiles/register.js +6 -7
  130. package/lib/esm/server/update.js +1 -13
  131. package/lib/esm/server/utils.js +20 -41
  132. package/lib/esm/server/worker/chai-image.js +0 -21
  133. package/lib/esm/server/worker/helpers.js +2 -9
  134. package/lib/esm/server/worker/reporter.js +15 -29
  135. package/lib/esm/server/worker/worker.js +31 -48
  136. package/lib/esm/shared/index.js +77 -0
  137. package/lib/esm/shared/serializeRegExp.js +24 -0
  138. package/lib/esm/types.js +5 -1
  139. package/lib/types/client/addon/Manager.d.ts +3 -3
  140. package/lib/types/client/addon/components/Addon.d.ts +1 -0
  141. package/lib/types/client/addon/components/Icons.d.ts +1 -0
  142. package/lib/types/client/addon/components/Panel.d.ts +1 -0
  143. package/lib/types/client/addon/components/Tools.d.ts +1 -0
  144. package/lib/types/client/addon/decorator.d.ts +1 -1
  145. package/lib/types/client/addon/index.d.ts +2 -0
  146. package/lib/types/client/addon/preset.d.ts +2 -24
  147. package/lib/types/client/addon/preview.d.ts +4 -0
  148. package/lib/types/client/addon/utils.d.ts +1 -0
  149. package/lib/types/client/addon/withCreevey.d.ts +4 -3
  150. package/lib/types/client/shared/components/ImagesView/BlendView.d.ts +3 -1
  151. package/lib/types/client/shared/components/ImagesView/SideBySideView.d.ts +3 -1
  152. package/lib/types/client/shared/components/ImagesView/SlideView.d.ts +3 -1
  153. package/lib/types/client/shared/components/ImagesView/SwapView.d.ts +3 -1
  154. package/lib/types/client/shared/components/PageHeader/ImagePreview.d.ts +3 -1
  155. package/lib/types/client/shared/components/ResultsPage.d.ts +3 -1
  156. package/lib/types/client/web/CreeveyLoader.d.ts +1 -1
  157. package/lib/types/client/web/CreeveyView/SideBar/Checkbox.d.ts +6 -3
  158. package/lib/types/client/web/CreeveyView/SideBar/Search.d.ts +1 -0
  159. package/lib/types/client/web/CreeveyView/SideBar/SuiteLink.d.ts +19 -14
  160. package/lib/types/client/web/CreeveyView/SideBar/TestStatusIcon.d.ts +3 -1
  161. package/lib/types/client/web/CreeveyView/SideBar/TestsStatus.d.ts +3 -1
  162. package/lib/types/client/web/CreeveyView/SideBar/Toggle.d.ts +1 -0
  163. package/lib/types/client/web/KeyboardEventsContext.d.ts +4 -2
  164. package/lib/types/index.d.ts +4 -1
  165. package/lib/types/server/logger.d.ts +6 -2
  166. package/lib/types/server/messages.d.ts +14 -12
  167. package/lib/types/server/selenium/browser.d.ts +5 -3
  168. package/lib/types/server/storybook/providers/browser.d.ts +2 -4
  169. package/lib/types/server/storybook/providers/hybrid.d.ts +2 -4
  170. package/lib/types/server/telemetry.d.ts +2 -0
  171. package/lib/types/server/utils.d.ts +5 -1
  172. package/lib/types/shared/index.d.ts +7 -0
  173. package/lib/types/shared/serializeRegExp.d.ts +9 -0
  174. package/lib/types/types.d.ts +29 -36
  175. package/package.json +132 -133
  176. package/types/global.d.ts +5 -0
  177. package/lib/cjs/client/web/1.js +0 -13
  178. package/lib/cjs/client/web/2.js +0 -1
  179. package/lib/cjs/server/extract.js +0 -50
  180. package/lib/cjs/server/loaders/babel/creevey-plugin.js +0 -88
  181. package/lib/cjs/server/loaders/babel/helpers.js +0 -479
  182. package/lib/cjs/server/loaders/babel/register.js +0 -126
  183. package/lib/cjs/server/loaders/hooks/mdx.js +0 -30
  184. package/lib/cjs/server/loaders/hooks/svelte.js +0 -65
  185. package/lib/cjs/server/loaders/webpack/compile.js +0 -286
  186. package/lib/cjs/server/loaders/webpack/creevey-loader.js +0 -174
  187. package/lib/cjs/server/loaders/webpack/dummy-hmr.js +0 -44
  188. package/lib/cjs/server/loaders/webpack/mdx-loader.js +0 -72
  189. package/lib/cjs/server/loaders/webpack/start.js +0 -41
  190. package/lib/cjs/server/storybook/entry.js +0 -68
  191. package/lib/cjs/server/storybook/helpers.js +0 -165
  192. package/lib/cjs/server/storybook/providers/nodejs.js +0 -239
  193. package/lib/cjs/shared.js +0 -124
  194. package/lib/esm/server/extract.js +0 -34
  195. package/lib/esm/server/loaders/babel/creevey-plugin.js +0 -74
  196. package/lib/esm/server/loaders/babel/helpers.js +0 -462
  197. package/lib/esm/server/loaders/babel/register.js +0 -105
  198. package/lib/esm/server/loaders/hooks/mdx.js +0 -15
  199. package/lib/esm/server/loaders/hooks/svelte.js +0 -49
  200. package/lib/esm/server/loaders/webpack/compile.js +0 -263
  201. package/lib/esm/server/loaders/webpack/creevey-loader.js +0 -153
  202. package/lib/esm/server/loaders/webpack/dummy-hmr.js +0 -36
  203. package/lib/esm/server/loaders/webpack/mdx-loader.js +0 -58
  204. package/lib/esm/server/loaders/webpack/start.js +0 -27
  205. package/lib/esm/server/storybook/entry.js +0 -44
  206. package/lib/esm/server/storybook/helpers.js +0 -106
  207. package/lib/esm/server/storybook/providers/nodejs.js +0 -217
  208. package/lib/esm/shared.js +0 -93
  209. package/lib/types/server/extract.d.ts +0 -2
  210. package/lib/types/server/loaders/babel/creevey-plugin.d.ts +0 -1
  211. package/lib/types/server/loaders/babel/helpers.d.ts +0 -19
  212. package/lib/types/server/loaders/babel/register.d.ts +0 -5
  213. package/lib/types/server/loaders/hooks/mdx.d.ts +0 -1
  214. package/lib/types/server/loaders/hooks/svelte.d.ts +0 -1
  215. package/lib/types/server/loaders/webpack/compile.d.ts +0 -2
  216. package/lib/types/server/loaders/webpack/creevey-loader.d.ts +0 -2
  217. package/lib/types/server/loaders/webpack/dummy-hmr.d.ts +0 -10
  218. package/lib/types/server/loaders/webpack/mdx-loader.d.ts +0 -6
  219. package/lib/types/server/loaders/webpack/start.d.ts +0 -1
  220. package/lib/types/server/storybook/entry.d.ts +0 -18
  221. package/lib/types/server/storybook/helpers.d.ts +0 -24
  222. package/lib/types/server/storybook/providers/nodejs.d.ts +0 -9
  223. package/lib/types/shared.d.ts +0 -16
  224. package/preset.js +0 -9
  225. package/storybook-static/stories.json +0 -21
  226. package/types/mdx.d.ts +0 -6
@@ -0,0 +1,34 @@
1
+ /*
2
+ object-assign
3
+ (c) Sindre Sorhus
4
+ @license MIT
5
+ */
6
+
7
+ /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
8
+
9
+ /** @license React v0.20.2
10
+ * scheduler.production.min.js
11
+ *
12
+ * Copyright (c) Facebook, Inc. and its affiliates.
13
+ *
14
+ * This source code is licensed under the MIT license found in the
15
+ * LICENSE file in the root directory of this source tree.
16
+ */
17
+
18
+ /** @license React v17.0.2
19
+ * react-dom.production.min.js
20
+ *
21
+ * Copyright (c) Facebook, Inc. and its affiliates.
22
+ *
23
+ * This source code is licensed under the MIT license found in the
24
+ * LICENSE file in the root directory of this source tree.
25
+ */
26
+
27
+ /** @license React v17.0.2
28
+ * react.production.min.js
29
+ *
30
+ * Copyright (c) Facebook, Inc. and its affiliates.
31
+ *
32
+ * This source code is licensed under the MIT license found in the
33
+ * LICENSE file in the root directory of this source tree.
34
+ */
@@ -6,12 +6,9 @@ import { emitWorkerMessage } from './server/messages';
6
6
  import { isShuttingDown, shutdown, shutdownWorkers } from './server/utils';
7
7
  import { setDefaultLevel, levels } from 'loglevel';
8
8
  import { logger } from './server/logger';
9
-
10
9
  function shutdownOnException(reason) {
11
- var _reason$stack;
12
-
13
10
  if (isShuttingDown.current) return;
14
- const error = reason instanceof Error ? (_reason$stack = reason.stack) !== null && _reason$stack !== void 0 ? _reason$stack : reason.message : reason;
11
+ const error = reason instanceof Error ? reason.stack ?? reason.message : reason;
15
12
  logger.error(error);
16
13
  process.exitCode = -1;
17
14
  if (cluster.isWorker) emitWorkerMessage({
@@ -20,16 +17,15 @@ function shutdownOnException(reason) {
20
17
  error
21
18
  }
22
19
  });
23
- if (cluster.isMaster && !isShuttingDown.current) void shutdownWorkers();
20
+ if (cluster.isPrimary && !isShuttingDown.current) void shutdownWorkers();
24
21
  }
25
-
26
22
  process.on('uncaughtException', shutdownOnException);
27
23
  process.on('unhandledRejection', shutdownOnException);
28
24
  if (cluster.isWorker) process.on('SIGINT', noop);
29
- if (cluster.isMaster) process.on('SIGINT', shutdown);
25
+ if (cluster.isPrimary) process.on('SIGINT', shutdown);
30
26
  const argv = minimist(process.argv.slice(2), {
31
- string: ['browser', 'config', 'reporter', 'reportDir', 'screenDir'],
32
- boolean: ['debug', 'ui', 'saveReport', 'webpack', 'tests'],
27
+ string: ['browser', 'config', 'reporter', 'reportDir', 'screenDir', 'storybookUrl'],
28
+ boolean: ['debug', 'trace', 'ui', 'saveReport', 'tests'],
33
29
  default: {
34
30
  port: 3000,
35
31
  saveReport: true
@@ -38,19 +34,20 @@ const argv = minimist(process.argv.slice(2), {
38
34
  port: 'p',
39
35
  config: 'c',
40
36
  debug: 'd',
41
- update: 'u',
42
- extract: 'e'
37
+ update: 'u'
43
38
  }
44
- }); // @ts-expect-error: define log level for storybook
39
+ });
45
40
 
46
- global.LOGLEVEL = argv.debug ? 'debug' : 'warn';
47
-
48
- if (argv.debug) {
41
+ // @ts-expect-error: define log level for storybook
42
+ global.LOGLEVEL = argv.trace ? 'trace' : argv.debug ? 'debug' : 'warn';
43
+ if (argv.trace) {
44
+ logger.setDefaultLevel(levels.TRACE);
45
+ setDefaultLevel(levels.TRACE);
46
+ } else if (argv.debug) {
49
47
  logger.setDefaultLevel(levels.DEBUG);
50
48
  setDefaultLevel(levels.DEBUG);
51
49
  } else {
52
50
  logger.setDefaultLevel(levels.INFO);
53
51
  setDefaultLevel(levels.INFO);
54
52
  }
55
-
56
53
  void creevey(argv);
package/lib/esm/index.js CHANGED
@@ -1,7 +1,4 @@
1
- export * from './types'; // export * from './client/addon/withCreevey';
2
- // export * from './client/addon/readyForCapture';
3
-
1
+ export * from './types';
4
2
  export { loadStories as browserStoriesProvider } from './server/storybook/providers/browser';
5
- export { loadStories as nodejsStoriesProvider } from './server/storybook/providers/nodejs';
6
3
  export { loadStories as hybridStoriesProvider } from './server/storybook/providers/hybrid';
7
4
  export * from './server/testsFiles/parser';
@@ -1,13 +1,11 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
- import { isCSFv3Enabled, isStorybookVersionGreaterThan, isStorybookVersionLessThan, storybookDirRef } from './storybook/helpers';
4
- import { loadStories as nodejsStoriesProvider } from './storybook/providers/nodejs';
5
3
  import { loadStories as browserStoriesProvider } from './storybook/providers/browser';
6
4
  import { isDefined } from '../types';
7
5
  export const defaultBrowser = 'chrome';
8
6
  export const defaultConfig = {
7
+ disableTelemetry: false,
9
8
  useDocker: true,
10
- useWebpackToExtractTests: false,
11
9
  dockerImage: 'aerokube/selenoid:latest-release',
12
10
  dockerImagePlatform: '',
13
11
  pullImages: true,
@@ -15,7 +13,6 @@ export const defaultConfig = {
15
13
  storybookUrl: 'http://localhost:6006',
16
14
  screenDir: path.resolve('images'),
17
15
  reportDir: path.resolve('report'),
18
- storybookDir: path.resolve('.storybook'),
19
16
  maxRetries: 0,
20
17
  diffOptions: {
21
18
  threshold: 0,
@@ -28,7 +25,6 @@ export const defaultConfig = {
28
25
  babelOptions: _ => _,
29
26
  testsRegex: /\.creevey\.(t|j)s$/
30
27
  };
31
-
32
28
  function normalizeBrowserConfig(name, config) {
33
29
  if (typeof config == 'boolean') return {
34
30
  browserName: name
@@ -38,35 +34,32 @@ function normalizeBrowserConfig(name, config) {
38
34
  };
39
35
  return config;
40
36
  }
41
-
42
37
  function resolveConfigPath(configPath) {
43
38
  const rootDir = process.cwd();
44
39
  const configDir = path.resolve('.creevey');
45
-
46
40
  if (isDefined(configPath)) {
47
41
  configPath = path.resolve(configPath);
48
42
  } else if (fs.existsSync(configDir)) {
49
- configPath = path.join(configDir, 'config'); // TODO We already find file with extension, why not use it?
43
+ configPath = path.join(configDir, 'config');
44
+ // TODO We already find file with extension, why not use it?
50
45
  } else if (fs.readdirSync(rootDir).find(filename => filename.startsWith('creevey.config'))) {
51
46
  configPath = path.join(rootDir, 'creevey.config');
52
47
  }
53
-
54
48
  return configPath;
55
49
  }
56
-
57
50
  export async function readConfig(options) {
58
51
  const configPath = resolveConfigPath(options.config);
59
- const userConfig = { ...defaultConfig
52
+ const userConfig = {
53
+ ...defaultConfig
60
54
  };
61
55
  if (isDefined(configPath)) Object.assign(userConfig, (await import(configPath)).default);
62
- storybookDirRef.current = userConfig.storybookDir;
63
- if (isStorybookVersionLessThan(6, 2)) userConfig.useWebpackToExtractTests = true;
64
- if (!userConfig.storiesProvider) userConfig.storiesProvider = (await isCSFv3Enabled()) && isStorybookVersionGreaterThan(5) ? browserStoriesProvider : nodejsStoriesProvider;
65
- if (userConfig.storiesProvider == browserStoriesProvider && isStorybookVersionLessThan(6)) throw new Error("Creevey browser stories provider doesn't support Storybook 5.x or older versions");
56
+ if (!userConfig.storiesProvider) userConfig.storiesProvider = browserStoriesProvider;
66
57
  if (options.failFast != undefined) userConfig.failFast = Boolean(options.failFast);
67
58
  if (options.reportDir) userConfig.reportDir = path.resolve(options.reportDir);
68
- if (options.screenDir) userConfig.screenDir = path.resolve(options.screenDir); // NOTE: Hack to pass typescript checking
59
+ if (options.screenDir) userConfig.screenDir = path.resolve(options.screenDir);
60
+ if (options.storybookUrl) userConfig.storybookUrl = options.storybookUrl;
69
61
 
62
+ // NOTE: Hack to pass typescript checking
70
63
  const config = userConfig;
71
64
  Object.entries(config.browsers).forEach(([browser, browserConfig]) => config.browsers[browser] = normalizeBrowserConfig(browser, browserConfig));
72
65
  return config;
@@ -1,4 +1,4 @@
1
- import cluster, { isMaster } from 'cluster';
1
+ import cluster from 'cluster';
2
2
  import { isDockerMessage } from '../types';
3
3
  import { subscribeOn, sendDockerMessage, emitDockerMessage } from './messages';
4
4
  import { isInsideDocker, LOCALHOST_REGEXP } from './utils';
@@ -7,14 +7,11 @@ import { Writable } from 'stream';
7
7
  import ora from 'ora';
8
8
  import { logger } from './logger';
9
9
  const docker = new Dockerode();
10
-
11
10
  class DevNull extends Writable {
12
11
  _write(_chunk, _encoding, callback) {
13
12
  setImmediate(callback);
14
13
  }
15
-
16
14
  }
17
-
18
15
  export async function pullImages(images, {
19
16
  auth,
20
17
  platform
@@ -23,30 +20,27 @@ export async function pullImages(images, {
23
20
  if (auth) args.authconfig = auth;
24
21
  if (platform) args.platform = platform;
25
22
  logger.info('Pull docker images');
26
-
27
23
  for (const image of images) {
28
24
  await new Promise((resolve, reject) => {
29
- const spinner = ora(`${image}: Pull start`).start(); // eslint-disable-next-line @typescript-eslint/no-floating-promises
25
+ const spinner = ora(`${image}: Pull start`).start();
30
26
 
27
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
31
28
  docker.pull(image, args, function (pullError, stream) {
32
29
  if (pullError) {
33
30
  spinner.fail();
34
31
  return reject(pullError);
35
- } // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
36
-
32
+ }
37
33
 
34
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
38
35
  docker.modem.followProgress(stream, onFinished, onProgress);
39
-
40
36
  function onFinished(error) {
41
37
  if (error) {
42
38
  spinner.fail();
43
39
  return reject(error);
44
40
  }
45
-
46
41
  spinner.succeed(`${image}: Pull complete`);
47
42
  resolve();
48
43
  }
49
-
50
44
  function onProgress(event) {
51
45
  if (!/^[a-z0-9]{12}$/i.test(event.id)) return;
52
46
  spinner.text = `${image}: [${event.id}] ${event.status} ${event.progress ? `${event.progress}` : ''}`;
@@ -63,13 +57,11 @@ export async function runImage(image, args, options, debug) {
63
57
  }
64
58
  })).map(async info => {
65
59
  const container = docker.getContainer(info.Id);
66
-
67
60
  try {
68
61
  await container.stop();
69
62
  } catch (_) {
70
63
  /* noop */
71
64
  }
72
-
73
65
  await container.remove();
74
66
  }));
75
67
  const hub = docker.run(image, args, debug ? process.stdout : new DevNull(), options, error => {
@@ -91,7 +83,7 @@ export async function runImage(image, args, options, debug) {
91
83
  });
92
84
  }
93
85
  export default async function (config, browser, startContainer) {
94
- if (isMaster) {
86
+ if (cluster.isPrimary) {
95
87
  const host = await startContainer();
96
88
  let gridUrl = 'http://localhost:4444/wd/hub';
97
89
  gridUrl = isInsideDocker ? gridUrl.replace(LOCALHOST_REGEXP, host) : gridUrl;
@@ -1,7 +1,8 @@
1
1
  import cluster from 'cluster';
2
2
  import { readConfig, defaultBrowser } from './config';
3
- import { logger } from './logger'; // NOTE: Impure function, mutate config by adding gridUrl prop
3
+ import { logger } from './logger';
4
4
 
5
+ // NOTE: Impure function, mutate config by adding gridUrl prop
5
6
  async function startWebdriverServer(config, options) {
6
7
  if (config.useDocker) {
7
8
  return (await import('./docker')).default(config, options.browser, async () => (await import('./selenium/selenoid')).startSelenoidContainer(config, options.debug));
@@ -9,54 +10,39 @@ async function startWebdriverServer(config, options) {
9
10
  return (await import('./selenium/selenoid')).startSelenoidStandalone(config, options.debug);
10
11
  }
11
12
  }
12
-
13
13
  export default async function (options) {
14
14
  const config = await readConfig(options);
15
15
  const {
16
16
  browser = defaultBrowser,
17
- extract,
18
17
  tests,
19
18
  update,
20
- webpack,
21
19
  ui,
22
20
  port
23
21
  } = options;
24
- if (!config) return; // NOTE: We don't need docker nor selenoid for webpack or update options
22
+ if (!config) return;
25
23
 
24
+ // NOTE: We don't need docker nor selenoid for webpack or update options
26
25
  if (!(config.gridUrl || Object.values(config.browsers).every(({
27
26
  gridUrl
28
- }) => gridUrl)) && !extract && !webpack && !tests && !update) {
27
+ }) => gridUrl)) && !tests && !update) {
29
28
  await startWebdriverServer(config, options);
30
29
  }
31
-
32
30
  switch (true) {
33
- case Boolean(extract) || tests:
34
- {
35
- return (await import('./extract')).default(config, options);
36
- }
37
-
38
31
  case Boolean(update):
39
32
  {
40
33
  return (await import('./update')).default(config, typeof update == 'string' ? update : undefined);
41
34
  }
42
-
43
- case webpack:
44
- {
45
- logger.info('Starting Webpack Compiler');
46
- return (await import('./loaders/webpack/compile')).default(config, options);
47
- }
48
-
49
- case cluster.isMaster:
35
+ case cluster.isPrimary:
50
36
  {
51
37
  logger.info('Starting Master Process');
52
38
  const resolveApi = (await import('./master/server')).default(config.reportDir, port, ui);
53
39
  return (await import('./master')).default(config, options, resolveApi);
54
40
  }
55
-
56
41
  default:
57
42
  {
58
43
  logger.info(`Starting Worker for ${browser}`);
59
- return (await import('./worker')).default(config, { ...options,
44
+ return (await import('./worker')).default(config, {
45
+ ...options,
60
46
  browser
61
47
  });
62
48
  }
@@ -15,6 +15,5 @@ prefix.apply(Logger, {
15
15
  const levelColor = colors[level.toUpperCase()];
16
16
  return `[${name}:${chalk.gray(process.pid)}] ${levelColor(level)} =>`;
17
17
  }
18
-
19
18
  });
20
19
  export const logger = Logger.getLogger('Creevey');
@@ -1,6 +1,5 @@
1
1
  import WebSocket from 'ws';
2
2
  import { logger } from '../logger';
3
-
4
3
  function broadcast(wss, message) {
5
4
  wss.clients.forEach(ws => {
6
5
  if (ws.readyState === WebSocket.OPEN) {
@@ -8,7 +7,6 @@ function broadcast(wss, message) {
8
7
  }
9
8
  });
10
9
  }
11
-
12
10
  export default function creeveyApi(runner) {
13
11
  return {
14
12
  subscribe(wss) {
@@ -17,15 +15,12 @@ export default function creeveyApi(runner) {
17
15
  payload
18
16
  }));
19
17
  },
20
-
21
18
  handleMessage(ws, message) {
22
19
  if (typeof message != 'string') {
23
20
  logger.info('unhandled message', message);
24
21
  return;
25
22
  }
26
-
27
23
  const command = JSON.parse(message);
28
-
29
24
  switch (command.type) {
30
25
  case 'status':
31
26
  {
@@ -35,19 +30,16 @@ export default function creeveyApi(runner) {
35
30
  }));
36
31
  return;
37
32
  }
38
-
39
33
  case 'start':
40
34
  {
41
35
  runner.start(command.payload);
42
36
  return;
43
37
  }
44
-
45
38
  case 'stop':
46
39
  {
47
40
  runner.stop();
48
41
  return;
49
42
  }
50
-
51
43
  case 'approve':
52
44
  {
53
45
  void runner.approve(command.payload);
@@ -55,6 +47,5 @@ export default function creeveyApi(runner) {
55
47
  }
56
48
  }
57
49
  }
58
-
59
50
  };
60
51
  }
@@ -1,5 +1,5 @@
1
1
  import path from 'path';
2
- import { writeFileSync, copyFile, readdir, mkdir, existsSync } from 'fs';
2
+ import { copyFile, readdir, mkdir, existsSync, writeFile } from 'fs';
3
3
  import { promisify } from 'util';
4
4
  import master from './master';
5
5
  import creeveyApi from './api';
@@ -7,10 +7,11 @@ import { isDefined } from '../../types';
7
7
  import { shutdown, shutdownWorkers, testsToImages, readDirRecursive } from '../utils';
8
8
  import { subscribeOn } from '../messages';
9
9
  import { logger } from '../logger';
10
+ import { sendScreenshotsCount } from '../telemetry';
11
+ const writeFileAsync = promisify(writeFile);
10
12
  const copyFileAsync = promisify(copyFile);
11
13
  const readdirAsync = promisify(readdir);
12
14
  const mkdirAsync = promisify(mkdir);
13
-
14
15
  async function copyStatics(reportDir) {
15
16
  const clientDir = path.join(__dirname, '../../client/web');
16
17
  const files = (await readdirAsync(clientDir, {
@@ -19,12 +20,10 @@ async function copyStatics(reportDir) {
19
20
  await mkdirAsync(reportDir, {
20
21
  recursive: true
21
22
  });
22
-
23
23
  for (const file of files) {
24
24
  await copyFileAsync(path.join(clientDir, file), path.join(reportDir, file));
25
25
  }
26
26
  }
27
-
28
27
  function reportDataModule(data) {
29
28
  return `
30
29
  (function (root, factory) {
@@ -36,44 +35,34 @@ function reportDataModule(data) {
36
35
  }(this, function () { return ${JSON.stringify(data)} }));
37
36
  `;
38
37
  }
39
-
40
38
  function outputUnnecessaryImages(imagesDir, images) {
41
39
  if (!existsSync(imagesDir)) return;
42
40
  const unnecessaryImages = readDirRecursive(imagesDir).map(imagePath => path.posix.relative(imagesDir, imagePath)).filter(imagePath => !images.has(imagePath));
43
-
44
41
  if (unnecessaryImages.length > 0) {
45
42
  logger.warn('We found unnecessary screenshot images, those can be safely removed:\n', unnecessaryImages.join('\n'));
46
43
  }
47
44
  }
48
-
49
45
  export default async function (config, options, resolveApi) {
50
46
  let runner = null;
51
-
52
47
  if (config.hooks.before) {
53
48
  await config.hooks.before();
54
49
  }
55
-
56
50
  subscribeOn('shutdown', () => {
57
51
  var _config$hooks$after, _config$hooks;
58
-
59
52
  return (_config$hooks$after = (_config$hooks = config.hooks).after) === null || _config$hooks$after === void 0 ? void 0 : _config$hooks$after.call(_config$hooks);
60
53
  });
61
54
  process.removeListener('SIGINT', shutdown);
62
55
  process.on('SIGINT', () => {
63
56
  var _runner, _runner2;
64
-
65
- (_runner = runner) === null || _runner === void 0 ? void 0 : _runner.removeAllListeners('stop');
66
-
57
+ (_runner = runner) === null || _runner === void 0 || _runner.removeAllListeners('stop');
67
58
  if ((_runner2 = runner) !== null && _runner2 !== void 0 && _runner2.isRunning) {
68
59
  var _runner4;
69
-
70
60
  // TODO Better handle stop
71
61
  void Promise.race([new Promise(resolve => setTimeout(resolve, 10000)), new Promise(resolve => {
72
62
  var _runner3;
73
-
74
63
  return (_runner3 = runner) === null || _runner3 === void 0 ? void 0 : _runner3.once('stop', resolve);
75
64
  })]).then(() => shutdownWorkers());
76
- (_runner4 = runner) === null || _runner4 === void 0 ? void 0 : _runner4.stop();
65
+ (_runner4 = runner) === null || _runner4 === void 0 || _runner4.stop();
77
66
  } else {
78
67
  void shutdownWorkers();
79
68
  }
@@ -83,43 +72,44 @@ export default async function (config, options, resolveApi) {
83
72
  debug: options.debug,
84
73
  port: options.port
85
74
  });
86
-
87
75
  if (options.saveReport) {
88
- await copyStatics(config.reportDir);
89
76
  runner.on('stop', () => {
90
- var _runner5;
91
-
92
- return writeFileSync(path.join(config.reportDir, 'data.js'), reportDataModule((_runner5 = runner) === null || _runner5 === void 0 ? void 0 : _runner5.status.tests));
77
+ void copyStatics(config.reportDir).then(() => {
78
+ var _runner5;
79
+ return writeFileAsync(path.join(config.reportDir, 'data.js'), reportDataModule((_runner5 = runner) === null || _runner5 === void 0 ? void 0 : _runner5.status.tests));
80
+ });
93
81
  });
94
82
  }
95
-
96
83
  if (options.ui) {
97
84
  resolveApi(creeveyApi(runner));
98
85
  logger.info(`Started on http://localhost:${options.port}`);
99
86
  } else {
100
87
  if (Object.values(runner.status.tests).filter(test => test && !test.skip).length == 0) {
101
- logger.warn("Don't have any tests to run"); // eslint-disable-next-line no-process-exit
102
-
88
+ logger.warn("Don't have any tests to run");
89
+ // eslint-disable-next-line no-process-exit
103
90
  void shutdownWorkers().then(() => process.exit());
104
91
  return;
105
92
  }
106
-
107
93
  runner.once('stop', () => {
108
- var _runner$status$tests, _runner6;
109
-
110
- const tests = Object.values((_runner$status$tests = (_runner6 = runner) === null || _runner6 === void 0 ? void 0 : _runner6.status.tests) !== null && _runner$status$tests !== void 0 ? _runner$status$tests : {});
94
+ var _runner6, _runner7;
95
+ const tests = Object.values(((_runner6 = runner) === null || _runner6 === void 0 ? void 0 : _runner6.status.tests) ?? {});
111
96
  const isSuccess = tests.filter(isDefined).filter(({
112
97
  skip
113
98
  }) => !skip).every(({
114
99
  status
115
- }) => status == 'success'); // TODO output summary
116
-
100
+ }) => status == 'success');
101
+ // TODO output summary
117
102
  process.exitCode = isSuccess ? 0 : -1;
118
- if (!config.failFast) outputUnnecessaryImages(config.screenDir, testsToImages(tests)); // eslint-disable-next-line no-process-exit
119
-
120
- void shutdownWorkers().then(() => process.exit());
121
- }); // TODO grep
122
-
103
+ if (!config.failFast) outputUnnecessaryImages(config.screenDir, testsToImages(tests));
104
+ sendScreenshotsCount(config, options, (_runner7 = runner) === null || _runner7 === void 0 ? void 0 : _runner7.status).catch(reason => {
105
+ const error = reason instanceof Error ? reason.stack ?? reason.message : reason;
106
+ logger.warn(`Can't send telemetry: ${error}`);
107
+ }).finally(() => {
108
+ // eslint-disable-next-line no-process-exit
109
+ void shutdownWorkers().then(() => process.exit());
110
+ });
111
+ });
112
+ // TODO grep
123
113
  runner.start(Object.keys(runner.status.tests));
124
114
  }
125
115
  }
@@ -2,8 +2,6 @@ import path from 'path';
2
2
  import { isDefined } from '../../types';
3
3
  import { loadTestsFromStories, saveTestsJson } from '../stories';
4
4
  import Runner from './runner';
5
- import { startWebpackCompiler } from '../loaders/webpack/start';
6
-
7
5
  function mergeTests(testsWithReports, testsFromStories) {
8
6
  Object.values(testsFromStories).filter(isDefined).forEach(test => {
9
7
  const testWithReport = testsWithReports[test.id];
@@ -15,18 +13,15 @@ function mergeTests(testsWithReports, testsFromStories) {
15
13
  });
16
14
  return testsFromStories;
17
15
  }
18
-
19
16
  export default async function master(config, options) {
20
- if (config.useWebpackToExtractTests) await startWebpackCompiler();
21
17
  const runner = new Runner(config);
22
18
  const reportDataPath = path.join(config.reportDir, 'data.js');
23
19
  let testsFromReport = {};
24
-
25
20
  try {
26
21
  testsFromReport = await import(reportDataPath);
27
- } catch (error) {// Ignore error
22
+ } catch (error) {
23
+ // Ignore error
28
24
  }
29
-
30
25
  await runner.init();
31
26
  const tests = await loadTestsFromStories(Object.keys(config.browsers), listener => config.storiesProvider(config, options, listener), testsDiff => {
32
27
  runner.updateTests(testsDiff);