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
@@ -1,46 +1,32 @@
1
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
2
-
3
- import cluster from 'cluster';
1
+ import cluster, { Worker as ClusterWorker } from 'cluster';
4
2
  import { EventEmitter } from 'events';
5
3
  import { isWorkerMessage } from '../../types';
6
4
  import { sendTestMessage, sendShutdownMessage, subscribeOnWorker } from '../messages';
7
5
  import { isShuttingDown } from '../utils';
8
6
  const FORK_RETRIES = 5;
9
7
  export default class Pool extends EventEmitter {
8
+ workers = [];
9
+ queue = [];
10
+ forcedStop = false;
10
11
  get isRunning() {
11
12
  return this.workers.length !== this.freeWorkers.length;
12
13
  }
13
-
14
14
  constructor(config, browser) {
15
15
  super();
16
16
  this.browser = browser;
17
-
18
- _defineProperty(this, "maxRetries", void 0);
19
-
20
- _defineProperty(this, "config", void 0);
21
-
22
- _defineProperty(this, "workers", []);
23
-
24
- _defineProperty(this, "queue", []);
25
-
26
- _defineProperty(this, "forcedStop", false);
27
-
28
- _defineProperty(this, "failFast", void 0);
29
-
30
17
  this.failFast = config.failFast;
31
18
  this.maxRetries = config.maxRetries;
32
19
  this.config = config.browsers[browser];
33
20
  }
34
-
35
21
  async init() {
36
22
  const poolSize = this.config.limit || 1;
23
+ // TODO Init queue for workers to smooth browser starting load
37
24
  this.workers = (await Promise.all(Array.from({
38
25
  length: poolSize
39
- }).map(() => this.forkWorker()))).filter(workerOrError => workerOrError instanceof cluster.Worker);
26
+ }).map(() => this.forkWorker()))).filter(workerOrError => workerOrError instanceof ClusterWorker);
40
27
  if (this.workers.length != poolSize) throw new Error(`Can't instantiate workers for ${this.browser} due many errors`);
41
28
  this.workers.forEach(worker => this.exitHandler(worker));
42
29
  }
43
-
44
30
  start(tests) {
45
31
  if (this.isRunning) return false;
46
32
  this.queue = tests.map(({
@@ -54,27 +40,22 @@ export default class Pool extends EventEmitter {
54
40
  this.process();
55
41
  return true;
56
42
  }
57
-
58
43
  stop() {
59
44
  if (!this.isRunning) {
60
45
  this.emit('stop');
61
46
  return;
62
47
  }
63
-
64
48
  this.forcedStop = true;
65
49
  this.queue = [];
66
50
  }
67
-
68
51
  process() {
69
52
  const worker = this.getFreeWorker();
70
53
  const [test] = this.queue;
71
-
72
54
  if (this.queue.length == 0 && this.workers.length === this.freeWorkers.length) {
73
55
  this.forcedStop = false;
74
56
  this.emit('stop');
75
57
  return;
76
58
  }
77
-
78
59
  if (!worker || !test) return;
79
60
  worker.isRunning = true;
80
61
  const {
@@ -92,25 +73,20 @@ export default class Pool extends EventEmitter {
92
73
  });
93
74
  this.process();
94
75
  }
95
-
96
76
  sendStatus(message) {
97
77
  this.emit('test', message);
98
78
  }
99
-
100
79
  getFreeWorker() {
101
80
  return this.freeWorkers[Math.floor(Math.random() * this.freeWorkers.length)];
102
81
  }
103
-
104
82
  get aliveWorkers() {
105
83
  return this.workers.filter(worker => !worker.exitedAfterDisconnect);
106
84
  }
107
-
108
85
  get freeWorkers() {
109
86
  return this.aliveWorkers.filter(worker => !worker.isRunning);
110
87
  }
111
-
112
88
  async forkWorker(retry = 0) {
113
- cluster.setupMaster({
89
+ cluster.setupPrimary({
114
90
  args: ['--browser', this.browser, ...process.argv.slice(2)]
115
91
  });
116
92
  const worker = cluster.fork();
@@ -120,7 +96,6 @@ export default class Pool extends EventEmitter {
120
96
  worker.off('message', readyHandler);
121
97
  resolve(message);
122
98
  };
123
-
124
99
  worker.on('message', readyHandler);
125
100
  });
126
101
  if (message.type != 'error') return worker;
@@ -128,37 +103,31 @@ export default class Pool extends EventEmitter {
128
103
  if (retry == FORK_RETRIES) return message.payload;
129
104
  return this.forkWorker(retry + 1);
130
105
  }
131
-
132
106
  exitHandler(worker) {
133
107
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
134
108
  worker.once('exit', async () => {
135
109
  if (isShuttingDown.current) return;
136
110
  const workerOrError = await this.forkWorker();
137
- if (!(workerOrError instanceof cluster.Worker)) throw new Error(`Can't instantiate worker for ${this.browser} due many errors`);
111
+ if (!(workerOrError instanceof ClusterWorker)) throw new Error(`Can't instantiate worker for ${this.browser} due many errors`);
138
112
  this.exitHandler(workerOrError);
139
113
  this.workers[this.workers.indexOf(worker)] = workerOrError;
140
114
  this.process();
141
115
  });
142
116
  }
143
-
144
117
  gracefullyKill(worker) {
145
118
  const timeout = setTimeout(() => worker.kill(), 10000);
146
119
  worker.on('exit', () => clearTimeout(timeout));
147
120
  sendShutdownMessage(worker);
148
121
  }
149
-
150
122
  shouldRetry(test) {
151
123
  return test.retries < this.maxRetries && !this.forcedStop;
152
124
  }
153
-
154
125
  handleTestResult(worker, test, result) {
155
126
  const shouldRetry = result.status == 'failed' && this.shouldRetry(test);
156
-
157
127
  if (shouldRetry) {
158
128
  test.retries += 1;
159
129
  this.queue[this.failFast ? 'unshift' : 'push'](test);
160
130
  }
161
-
162
131
  this.sendStatus({
163
132
  id: test.id,
164
133
  status: shouldRetry ? 'retrying' : result.status,
@@ -167,7 +136,6 @@ export default class Pool extends EventEmitter {
167
136
  worker.isRunning = false;
168
137
  setImmediate(() => this.process());
169
138
  }
170
-
171
139
  subscribe(worker, test) {
172
140
  const subscriptions = [subscribeOnWorker(worker, 'worker', message => {
173
141
  if (message.type != 'error') return;
@@ -183,5 +151,4 @@ export default class Pool extends EventEmitter {
183
151
  this.handleTestResult(worker, test, message.payload);
184
152
  })];
185
153
  }
186
-
187
154
  }
@@ -1,5 +1,3 @@
1
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
2
-
3
1
  import path from 'path';
4
2
  import { copyFile, mkdir } from 'fs';
5
3
  import { promisify } from 'util';
@@ -9,63 +7,36 @@ import Pool from './pool';
9
7
  const copyFileAsync = promisify(copyFile);
10
8
  const mkdirAsync = promisify(mkdir);
11
9
  export default class Runner extends EventEmitter {
10
+ pools = {};
11
+ tests = {};
12
12
  get isRunning() {
13
13
  return Object.values(this.pools).some(pool => pool.isRunning);
14
14
  }
15
-
16
15
  constructor(config) {
17
16
  super();
18
-
19
- _defineProperty(this, "failFast", void 0);
20
-
21
- _defineProperty(this, "screenDir", void 0);
22
-
23
- _defineProperty(this, "reportDir", void 0);
24
-
25
- _defineProperty(this, "browsers", void 0);
26
-
27
- _defineProperty(this, "pools", {});
28
-
29
- _defineProperty(this, "tests", {});
30
-
31
- _defineProperty(this, "handlePoolMessage", message => {
32
- const {
33
- id,
34
- status,
35
- result
36
- } = message;
37
- const test = this.tests[id];
38
- if (!test) return;
39
- const {
40
- browser,
41
- testName,
42
- storyPath,
43
- storyId
44
- } = test; // TODO Handle 'retrying' status
45
-
46
- test.status = status == 'retrying' ? 'failed' : status;
47
-
48
- if (!result) {
49
- this.sendUpdate({
50
- tests: {
51
- [id]: {
52
- id,
53
- browser,
54
- testName,
55
- storyPath,
56
- status: test.status,
57
- storyId
58
- }
59
- }
60
- });
61
- return;
62
- }
63
-
64
- if (!test.results) {
65
- test.results = [];
66
- }
67
-
68
- test.results.push(result);
17
+ this.failFast = config.failFast;
18
+ this.screenDir = config.screenDir;
19
+ this.reportDir = config.reportDir;
20
+ this.browsers = Object.keys(config.browsers);
21
+ this.browsers.map(browser => this.pools[browser] = new Pool(config, browser)).map(pool => pool.on('test', this.handlePoolMessage));
22
+ }
23
+ handlePoolMessage = message => {
24
+ const {
25
+ id,
26
+ status,
27
+ result
28
+ } = message;
29
+ const test = this.tests[id];
30
+ if (!test) return;
31
+ const {
32
+ browser,
33
+ testName,
34
+ storyPath,
35
+ storyId
36
+ } = test;
37
+ // TODO Handle 'retrying' status
38
+ test.status = status == 'retrying' ? 'failed' : status;
39
+ if (!result) {
69
40
  this.sendUpdate({
70
41
  tests: {
71
42
  [id]: {
@@ -74,56 +45,65 @@ export default class Runner extends EventEmitter {
74
45
  testName,
75
46
  storyPath,
76
47
  status: test.status,
77
- results: [result],
78
48
  storyId
79
49
  }
80
50
  }
81
51
  });
82
- if (this.failFast && status == 'failed') this.stop();
83
- });
84
-
85
- _defineProperty(this, "handlePoolStop", () => {
86
- if (!this.isRunning) {
87
- this.sendUpdate({
88
- isRunning: false
89
- });
90
- this.emit('stop');
52
+ return;
53
+ }
54
+ if (!test.results) {
55
+ test.results = [];
56
+ }
57
+ test.results.push(result);
58
+ this.sendUpdate({
59
+ tests: {
60
+ [id]: {
61
+ id,
62
+ browser,
63
+ testName,
64
+ storyPath,
65
+ status: test.status,
66
+ results: [result],
67
+ storyId
68
+ }
91
69
  }
92
70
  });
93
-
94
- this.failFast = config.failFast;
95
- this.screenDir = config.screenDir;
96
- this.reportDir = config.reportDir;
97
- this.browsers = Object.keys(config.browsers);
98
- this.browsers.map(browser => this.pools[browser] = new Pool(config, browser)).map(pool => pool.on('test', this.handlePoolMessage));
99
- }
100
-
71
+ if (this.failFast && status == 'failed') this.stop();
72
+ };
73
+ handlePoolStop = () => {
74
+ if (!this.isRunning) {
75
+ this.sendUpdate({
76
+ isRunning: false
77
+ });
78
+ this.emit('stop');
79
+ }
80
+ };
101
81
  async init() {
102
82
  await Promise.all(Object.values(this.pools).map(pool => pool.init()));
103
83
  }
104
-
105
84
  updateTests(testsDiff) {
106
85
  const tests = {};
107
86
  const removedTests = [];
108
87
  Object.entries(testsDiff).forEach(([id, newTest]) => {
109
88
  const oldTest = this.tests[id];
110
-
111
89
  if (newTest) {
112
90
  if (oldTest) {
113
- this.tests[id] = { ...newTest,
91
+ this.tests[id] = {
92
+ ...newTest,
114
93
  retries: oldTest.retries,
115
94
  results: oldTest.results,
116
95
  approved: oldTest.approved
117
96
  };
118
- } else this.tests[id] = newTest; // eslint-disable-next-line @typescript-eslint/no-unused-vars
119
-
97
+ } else this.tests[id] = newTest;
120
98
 
99
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
121
100
  const {
122
101
  story,
123
102
  fn,
124
103
  ...restTest
125
104
  } = newTest;
126
- tests[id] = { ...restTest,
105
+ tests[id] = {
106
+ ...restTest,
127
107
  status: 'unknown'
128
108
  };
129
109
  } else if (oldTest) {
@@ -149,7 +129,6 @@ export default class Runner extends EventEmitter {
149
129
  removedTests
150
130
  });
151
131
  }
152
-
153
132
  start(ids) {
154
133
  if (this.isRunning) return;
155
134
  const testsToStart = ids.map(id => this.tests[id]).filter(isDefined).filter(test => !test.skip);
@@ -162,7 +141,8 @@ export default class Runner extends EventEmitter {
162
141
  browser,
163
142
  testName,
164
143
  storyPath
165
- }) => ({ ...update,
144
+ }) => ({
145
+ ...update,
166
146
  [id]: {
167
147
  id,
168
148
  browser,
@@ -182,7 +162,8 @@ export default class Runner extends EventEmitter {
182
162
  } = test;
183
163
  const restPath = [...storyPath, testName].filter(isDefined);
184
164
  test.status = 'pending';
185
- return { ...tests,
165
+ return {
166
+ ...tests,
186
167
  [browser]: [...(tests[browser] || []), {
187
168
  id,
188
169
  path: restPath
@@ -192,21 +173,19 @@ export default class Runner extends EventEmitter {
192
173
  this.browsers.forEach(browser => {
193
174
  const pool = this.pools[browser];
194
175
  const tests = testsByBrowser[browser];
195
-
196
176
  if (tests && tests.length > 0 && pool.start(tests)) {
197
177
  pool.once('stop', this.handlePoolStop);
198
178
  }
199
179
  });
200
180
  }
201
-
202
181
  stop() {
203
182
  if (!this.isRunning) return;
204
183
  this.browsers.forEach(browser => this.pools[browser].stop());
205
184
  }
206
-
207
185
  get status() {
208
186
  const tests = {};
209
- Object.values(this.tests).filter(isDefined) // eslint-disable-next-line @typescript-eslint/no-unused-vars
187
+ Object.values(this.tests).filter(isDefined)
188
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
210
189
  .forEach(({
211
190
  story,
212
191
  fn,
@@ -218,7 +197,6 @@ export default class Runner extends EventEmitter {
218
197
  browsers: this.browsers
219
198
  };
220
199
  }
221
-
222
200
  async approve({
223
201
  id,
224
202
  retry,
@@ -230,11 +208,9 @@ export default class Runner extends EventEmitter {
230
208
  if (!result || !result.images) return;
231
209
  const images = result.images[image];
232
210
  if (!images) return;
233
-
234
211
  if (!test.approved) {
235
212
  test.approved = {};
236
213
  }
237
-
238
214
  const {
239
215
  browser,
240
216
  testName,
@@ -264,9 +240,7 @@ export default class Runner extends EventEmitter {
264
240
  }
265
241
  });
266
242
  }
267
-
268
243
  sendUpdate(data) {
269
244
  this.emit('update', data);
270
245
  }
271
-
272
246
  }
@@ -27,17 +27,14 @@ export default function server(reportDir, port, ui) {
27
27
  ctx.body = 'pong';
28
28
  return;
29
29
  }
30
-
31
30
  await next();
32
31
  });
33
-
34
32
  if (ui) {
35
33
  app.use(async (_, next) => {
36
34
  await creeveyApi;
37
35
  await next();
38
36
  });
39
37
  }
40
-
41
38
  app.use(async (ctx, next) => {
42
39
  if (ctx.method == 'POST' && ctx.path == '/stories') {
43
40
  const {
@@ -51,13 +48,12 @@ export default function server(reportDir, port, ui) {
51
48
  type: 'update',
52
49
  payload: deserializedStories
53
50
  });
54
- Object.values(cluster.workers).filter(isDefined).filter(worker => worker.isConnected()).forEach(worker => sendStoriesMessage(worker, {
51
+ Object.values(cluster.workers ?? {}).filter(isDefined).filter(worker => worker.isConnected()).forEach(worker => sendStoriesMessage(worker, {
55
52
  type: 'update',
56
53
  payload: deserializedStories
57
54
  }));
58
55
  return;
59
56
  }
60
-
61
57
  await next();
62
58
  });
63
59
  app.use(async (ctx, next) => {
@@ -66,8 +62,8 @@ export default function server(reportDir, port, ui) {
66
62
  workerId,
67
63
  options
68
64
  } = ctx.request.body;
69
- const worker = Object.values(cluster.workers).filter(isDefined).find(worker => worker.process.pid == workerId); // NOTE: Hypothetical case when someone send to us capture req and we don't have a worker with browser session for it
70
-
65
+ const worker = Object.values(cluster.workers ?? {}).filter(isDefined).find(worker => worker.process.pid == workerId);
66
+ // NOTE: Hypothetical case when someone send to us capture req and we don't have a worker with browser session for it
71
67
  if (!worker) return;
72
68
  await new Promise(resolve => {
73
69
  const unsubscribe = subscribeOnWorker(worker, 'stories', message => {
@@ -79,12 +75,11 @@ export default function server(reportDir, port, ui) {
79
75
  type: 'capture',
80
76
  payload: options
81
77
  });
82
- }); // TODO Pass screenshot result to show it in inspector
83
-
78
+ });
79
+ // TODO Pass screenshot result to show it in inspector
84
80
  ctx.body = 'Ok';
85
81
  return;
86
82
  }
87
-
88
83
  await next();
89
84
  });
90
85
  app.use(serve(path.join(__dirname, '../../client/web')));
@@ -94,11 +89,14 @@ export default function server(reportDir, port, ui) {
94
89
  subscribeOn('shutdown', () => {
95
90
  server.close();
96
91
  wss.close();
92
+ wss.clients.forEach(ws => ws.close());
97
93
  });
98
94
  void creeveyApi.then(api => {
99
95
  api.subscribe(wss);
100
96
  wss.on('connection', ws => {
101
- ws.on('message', message => api.handleMessage(ws, message));
97
+ ws.on('message', (message, isBinary) => {
98
+ api.handleMessage(ws, isBinary ? message : message.toString());
99
+ });
102
100
  });
103
101
  });
104
102
  return resolveApi;