creevey 0.9.0-beta.1 → 0.9.0-non-webpack.0

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 (267) hide show
  1. package/AUTHORS +15 -15
  2. package/CHANGELOG.md +1275 -1275
  3. package/LICENSE +21 -21
  4. package/README.md +7 -0
  5. package/addon/README.md +3 -0
  6. package/addon/package.json +4 -0
  7. package/docs/config.md +212 -212
  8. package/docs/grid.md +10 -10
  9. package/docs/tests.md +63 -63
  10. package/jest.config.js +6 -0
  11. package/lib/cjs/cli.js +5 -0
  12. package/lib/cjs/client/addon/Manager.js +418 -0
  13. package/lib/cjs/client/addon/components/Addon.js +76 -0
  14. package/lib/cjs/client/addon/components/Icons.js +42 -0
  15. package/lib/cjs/client/addon/components/Panel.js +68 -0
  16. package/lib/cjs/client/addon/components/TestSelect.js +63 -0
  17. package/lib/cjs/client/addon/components/Tools.js +114 -0
  18. package/lib/cjs/client/addon/decorator.js +11 -0
  19. package/lib/cjs/client/addon/index.js +31 -0
  20. package/lib/cjs/client/addon/preset.js +81 -0
  21. package/lib/cjs/client/addon/readyForCapture.js +12 -0
  22. package/lib/cjs/client/addon/register.js +100 -0
  23. package/lib/cjs/client/addon/utils.js +38 -0
  24. package/lib/cjs/client/addon/withCreevey.js +558 -0
  25. package/lib/cjs/client/shared/components/ImagesView/BlendView.js +85 -0
  26. package/lib/cjs/client/shared/components/ImagesView/ImagesView.js +88 -0
  27. package/lib/cjs/client/shared/components/ImagesView/SideBySideView.js +176 -0
  28. package/lib/cjs/client/shared/components/ImagesView/SlideView.js +179 -0
  29. package/lib/cjs/client/shared/components/ImagesView/SwapView.js +110 -0
  30. package/lib/cjs/client/shared/components/ImagesView/index.js +45 -0
  31. package/lib/cjs/client/shared/components/PageFooter/PageFooter.js +46 -0
  32. package/lib/cjs/client/shared/components/PageFooter/Paging.js +98 -0
  33. package/lib/cjs/client/shared/components/PageHeader/ImagePreview.js +78 -0
  34. package/lib/cjs/client/shared/components/PageHeader/PageHeader.js +144 -0
  35. package/lib/cjs/client/shared/components/ResultsPage.js +173 -0
  36. package/lib/cjs/client/shared/creeveyClientApi.js +107 -0
  37. package/lib/cjs/client/shared/helpers.js +482 -0
  38. package/lib/cjs/client/shared/viewMode.js +17 -0
  39. package/lib/cjs/client/web/142.js +2 -0
  40. package/lib/cjs/client/web/142.js.LICENSE.txt +12 -0
  41. package/lib/cjs/client/web/32.js +1 -0
  42. package/lib/cjs/client/web/551.js +1 -0
  43. package/lib/cjs/client/web/566.js +2 -0
  44. package/lib/cjs/client/web/566.js.LICENSE.txt +31 -0
  45. package/lib/cjs/client/web/691.js +2 -0
  46. package/lib/cjs/client/web/691.js.LICENSE.txt +8 -0
  47. package/lib/cjs/client/web/725.js +1 -0
  48. package/lib/cjs/client/web/index.html +19 -0
  49. package/lib/cjs/client/web/main.js +2 -38
  50. package/lib/cjs/client/web/main.js.LICENSE.txt +49 -0
  51. package/lib/cjs/creevey.js +69 -0
  52. package/lib/cjs/index.js +62 -0
  53. package/lib/cjs/server/config.js +96 -0
  54. package/lib/cjs/server/docker.js +146 -0
  55. package/lib/cjs/server/extract.js +50 -0
  56. package/lib/cjs/server/index.js +83 -0
  57. package/lib/cjs/server/loaders/babel/creevey-plugin.js +86 -0
  58. package/lib/cjs/server/loaders/babel/helpers.js +469 -0
  59. package/lib/cjs/server/loaders/babel/register.js +124 -0
  60. package/lib/cjs/server/loaders/hooks/mdx.js +30 -0
  61. package/lib/cjs/server/loaders/hooks/svelte.js +65 -0
  62. package/lib/cjs/server/loaders/webpack/compile.js +293 -0
  63. package/lib/cjs/server/loaders/webpack/creevey-loader.js +179 -0
  64. package/lib/cjs/server/loaders/webpack/dummy-hmr.js +39 -0
  65. package/lib/cjs/server/loaders/webpack/mdx-loader.js +72 -0
  66. package/lib/cjs/server/loaders/webpack/start.js +41 -0
  67. package/lib/cjs/server/logger.js +48 -0
  68. package/lib/cjs/server/master/api.js +71 -0
  69. package/lib/cjs/server/master/index.js +146 -0
  70. package/lib/cjs/server/master/master.js +57 -0
  71. package/lib/cjs/server/master/pool.js +197 -0
  72. package/lib/cjs/server/master/runner.js +281 -0
  73. package/lib/cjs/server/master/server.js +129 -0
  74. package/lib/cjs/server/messages.js +264 -0
  75. package/lib/cjs/server/selenium/browser.js +672 -0
  76. package/lib/cjs/server/selenium/index.js +31 -0
  77. package/lib/cjs/server/selenium/selenoid.js +172 -0
  78. package/lib/cjs/server/stories.js +159 -0
  79. package/lib/cjs/server/storybook/entry.js +70 -0
  80. package/lib/cjs/server/storybook/helpers.js +159 -0
  81. package/lib/cjs/server/storybook/providers/browser.js +74 -0
  82. package/lib/cjs/server/storybook/providers/hybrid.js +84 -0
  83. package/lib/cjs/server/storybook/providers/nodejs.js +239 -0
  84. package/lib/cjs/server/testsFiles/parser.js +72 -0
  85. package/lib/cjs/server/testsFiles/register.js +48 -0
  86. package/lib/cjs/server/update.js +79 -0
  87. package/lib/cjs/server/utils.js +183 -0
  88. package/lib/cjs/server/worker/chai-image.js +142 -0
  89. package/lib/cjs/server/worker/helpers.js +69 -0
  90. package/lib/cjs/server/worker/index.js +15 -0
  91. package/lib/cjs/server/worker/reporter.js +108 -0
  92. package/lib/cjs/server/worker/worker.js +268 -0
  93. package/lib/cjs/shared/index.js +89 -0
  94. package/lib/cjs/shared/serializeRegExp.js +41 -0
  95. package/lib/cjs/types.js +74 -0
  96. package/lib/esm/cli.js +4 -0
  97. package/lib/esm/client/addon/Manager.js +402 -0
  98. package/lib/esm/client/addon/components/Addon.js +58 -0
  99. package/lib/esm/client/addon/components/Icons.js +27 -0
  100. package/lib/esm/client/addon/components/Panel.js +49 -0
  101. package/lib/esm/client/addon/components/TestSelect.js +49 -0
  102. package/lib/esm/client/addon/components/Tools.js +91 -0
  103. package/lib/esm/client/addon/decorator.js +2 -0
  104. package/lib/esm/client/addon/index.js +2 -0
  105. package/lib/esm/client/addon/preset.js +56 -0
  106. package/lib/esm/client/addon/readyForCapture.js +5 -0
  107. package/lib/esm/client/addon/register.js +79 -0
  108. package/lib/esm/client/addon/utils.js +31 -0
  109. package/lib/esm/client/addon/withCreevey.js +534 -0
  110. package/lib/esm/client/shared/components/ImagesView/BlendView.js +63 -0
  111. package/lib/esm/client/shared/components/ImagesView/ImagesView.js +65 -0
  112. package/lib/esm/client/shared/components/ImagesView/SideBySideView.js +151 -0
  113. package/lib/esm/client/shared/components/ImagesView/SlideView.js +154 -0
  114. package/lib/esm/client/shared/components/ImagesView/SwapView.js +88 -0
  115. package/lib/esm/client/shared/components/ImagesView/index.js +5 -0
  116. package/lib/esm/client/shared/components/PageFooter/PageFooter.js +32 -0
  117. package/lib/esm/client/shared/components/PageFooter/Paging.js +84 -0
  118. package/lib/esm/client/shared/components/PageHeader/ImagePreview.js +64 -0
  119. package/lib/esm/client/shared/components/PageHeader/PageHeader.js +120 -0
  120. package/lib/esm/client/shared/components/ResultsPage.js +143 -0
  121. package/lib/esm/client/shared/creeveyClientApi.js +98 -0
  122. package/lib/esm/client/shared/helpers.js +424 -0
  123. package/lib/esm/client/shared/viewMode.js +6 -0
  124. package/lib/esm/creevey.js +54 -0
  125. package/lib/esm/index.js +5 -0
  126. package/lib/esm/server/config.js +73 -0
  127. package/lib/esm/server/docker.js +123 -0
  128. package/lib/esm/server/extract.js +34 -0
  129. package/lib/esm/server/index.js +64 -0
  130. package/lib/esm/server/loaders/babel/creevey-plugin.js +72 -0
  131. package/lib/esm/server/loaders/babel/helpers.js +452 -0
  132. package/lib/esm/server/loaders/babel/register.js +103 -0
  133. package/lib/esm/server/loaders/hooks/mdx.js +15 -0
  134. package/lib/esm/server/loaders/hooks/svelte.js +49 -0
  135. package/lib/esm/server/loaders/webpack/compile.js +270 -0
  136. package/lib/esm/server/loaders/webpack/creevey-loader.js +158 -0
  137. package/lib/esm/server/loaders/webpack/dummy-hmr.js +32 -0
  138. package/lib/esm/server/loaders/webpack/mdx-loader.js +58 -0
  139. package/lib/esm/server/loaders/webpack/start.js +27 -0
  140. package/lib/esm/server/logger.js +20 -0
  141. package/lib/esm/server/master/api.js +60 -0
  142. package/lib/esm/server/master/index.js +125 -0
  143. package/lib/esm/server/master/master.js +38 -0
  144. package/lib/esm/server/master/pool.js +176 -0
  145. package/lib/esm/server/master/runner.js +259 -0
  146. package/lib/esm/server/master/server.js +105 -0
  147. package/lib/esm/server/messages.js +232 -0
  148. package/lib/esm/server/selenium/browser.js +639 -0
  149. package/lib/esm/server/selenium/index.js +2 -0
  150. package/lib/esm/server/selenium/selenoid.js +149 -0
  151. package/lib/esm/server/stories.js +140 -0
  152. package/lib/esm/server/storybook/entry.js +46 -0
  153. package/lib/esm/server/storybook/helpers.js +98 -0
  154. package/lib/esm/server/storybook/providers/browser.js +60 -0
  155. package/lib/esm/server/storybook/providers/hybrid.js +64 -0
  156. package/lib/esm/server/storybook/providers/nodejs.js +217 -0
  157. package/lib/esm/server/testsFiles/parser.js +50 -0
  158. package/lib/esm/server/testsFiles/register.js +35 -0
  159. package/lib/esm/server/update.js +61 -0
  160. package/lib/esm/server/utils.js +142 -0
  161. package/lib/esm/server/worker/chai-image.js +130 -0
  162. package/lib/esm/server/worker/helpers.js +60 -0
  163. package/lib/esm/server/worker/index.js +1 -0
  164. package/lib/esm/server/worker/reporter.js +86 -0
  165. package/lib/esm/server/worker/worker.js +238 -0
  166. package/lib/esm/shared/index.js +66 -0
  167. package/lib/esm/shared/serializeRegExp.js +23 -0
  168. package/lib/esm/types.js +43 -0
  169. package/lib/types/cli.d.ts +1 -1
  170. package/lib/types/client/addon/Manager.d.ts +37 -37
  171. package/lib/types/client/addon/components/Addon.d.ts +8 -8
  172. package/lib/types/client/addon/components/Icons.d.ts +7 -7
  173. package/lib/types/client/addon/components/Panel.d.ts +9 -9
  174. package/lib/types/client/addon/components/TestSelect.d.ts +8 -9
  175. package/lib/types/client/addon/components/Tools.d.ts +6 -6
  176. package/lib/types/client/addon/decorator.d.ts +1 -1
  177. package/lib/types/client/addon/index.d.ts +2 -0
  178. package/lib/types/client/addon/preset.d.ts +23 -24
  179. package/lib/types/client/addon/readyForCapture.d.ts +6 -6
  180. package/lib/types/client/addon/register.d.ts +3 -3
  181. package/lib/types/client/addon/utils.d.ts +2 -2
  182. package/lib/types/client/addon/withCreevey.d.ts +24 -24
  183. package/lib/types/client/shared/components/ImagesView/BlendView.d.ts +3 -3
  184. package/lib/types/client/shared/components/ImagesView/ImagesView.d.ts +24 -25
  185. package/lib/types/client/shared/components/ImagesView/SideBySideView.d.ts +3 -3
  186. package/lib/types/client/shared/components/ImagesView/SlideView.d.ts +3 -3
  187. package/lib/types/client/shared/components/ImagesView/SwapView.d.ts +3 -3
  188. package/lib/types/client/shared/components/ImagesView/index.d.ts +5 -5
  189. package/lib/types/client/shared/components/PageFooter/PageFooter.d.ts +8 -9
  190. package/lib/types/client/shared/components/PageFooter/Paging.d.ts +7 -8
  191. package/lib/types/client/shared/components/PageHeader/ImagePreview.d.ts +12 -12
  192. package/lib/types/client/shared/components/PageHeader/PageHeader.d.ts +16 -17
  193. package/lib/types/client/shared/components/ResultsPage.d.ts +18 -18
  194. package/lib/types/client/shared/creeveyClientApi.d.ts +9 -9
  195. package/lib/types/client/shared/helpers.d.ts +46 -46
  196. package/lib/types/client/shared/viewMode.d.ts +4 -4
  197. package/lib/types/client/web/CreeveyApp.d.ts +11 -12
  198. package/lib/types/client/web/CreeveyContext.d.ts +11 -11
  199. package/lib/types/client/web/CreeveyLoader.d.ts +2 -3
  200. package/lib/types/client/web/CreeveyView/SideBar/Checkbox.d.ts +19 -19
  201. package/lib/types/client/web/CreeveyView/SideBar/Search.d.ts +6 -6
  202. package/lib/types/client/web/CreeveyView/SideBar/SideBar.d.ts +14 -14
  203. package/lib/types/client/web/CreeveyView/SideBar/SideBarHeader.d.ts +12 -13
  204. package/lib/types/client/web/CreeveyView/SideBar/SuiteLink.d.ts +33 -33
  205. package/lib/types/client/web/CreeveyView/SideBar/TestLink.d.ts +7 -8
  206. package/lib/types/client/web/CreeveyView/SideBar/TestStatusIcon.d.ts +10 -10
  207. package/lib/types/client/web/CreeveyView/SideBar/TestsStatus.d.ts +9 -9
  208. package/lib/types/client/web/CreeveyView/SideBar/Toggle.d.ts +6 -6
  209. package/lib/types/client/web/CreeveyView/SideBar/index.d.ts +1 -1
  210. package/lib/types/client/web/KeyboardEventsContext.d.ts +13 -13
  211. package/lib/types/client/web/index.d.ts +4 -4
  212. package/lib/types/creevey.d.ts +1 -1
  213. package/lib/types/index.d.ts +1 -4
  214. package/lib/types/server/config.d.ts +4 -4
  215. package/lib/types/server/docker.d.ts +7 -7
  216. package/lib/types/server/extract.d.ts +2 -2
  217. package/lib/types/server/index.d.ts +2 -2
  218. package/lib/types/server/loaders/babel/creevey-plugin.d.ts +1 -1
  219. package/lib/types/server/loaders/babel/helpers.d.ts +19 -19
  220. package/lib/types/server/loaders/babel/register.d.ts +5 -5
  221. package/lib/types/server/loaders/hooks/mdx.d.ts +1 -1
  222. package/lib/types/server/loaders/hooks/svelte.d.ts +1 -1
  223. package/lib/types/server/loaders/webpack/compile.d.ts +2 -2
  224. package/lib/types/server/loaders/webpack/creevey-loader.d.ts +4 -2
  225. package/lib/types/server/loaders/webpack/dummy-hmr.d.ts +10 -10
  226. package/lib/types/server/loaders/webpack/mdx-loader.d.ts +6 -6
  227. package/lib/types/server/loaders/webpack/start.d.ts +1 -1
  228. package/lib/types/server/logger.d.ts +10 -6
  229. package/lib/types/server/master/api.d.ts +7 -7
  230. package/lib/types/server/master/index.d.ts +3 -3
  231. package/lib/types/server/master/master.d.ts +7 -7
  232. package/lib/types/server/master/pool.d.ts +31 -31
  233. package/lib/types/server/master/runner.d.ts +26 -26
  234. package/lib/types/server/master/server.d.ts +2 -2
  235. package/lib/types/server/messages.d.ts +27 -27
  236. package/lib/types/server/selenium/browser.d.ts +17 -17
  237. package/lib/types/server/selenium/index.d.ts +2 -2
  238. package/lib/types/server/selenium/selenoid.d.ts +3 -3
  239. package/lib/types/server/stories.d.ts +8 -8
  240. package/lib/types/server/storybook/entry.d.ts +18 -18
  241. package/lib/types/server/storybook/helpers.d.ts +24 -24
  242. package/lib/types/server/storybook/providers/browser.d.ts +4 -4
  243. package/lib/types/server/storybook/providers/hybrid.d.ts +4 -4
  244. package/lib/types/server/storybook/providers/nodejs.d.ts +9 -9
  245. package/lib/types/server/testsFiles/parser.d.ts +12 -12
  246. package/lib/types/server/testsFiles/register.d.ts +2 -2
  247. package/lib/types/server/update.d.ts +2 -2
  248. package/lib/types/server/utils.d.ts +20 -20
  249. package/lib/types/server/worker/chai-image.d.ts +6 -6
  250. package/lib/types/server/worker/helpers.d.ts +8 -8
  251. package/lib/types/server/worker/index.d.ts +1 -1
  252. package/lib/types/server/worker/reporter.d.ts +8 -8
  253. package/lib/types/server/worker/worker.d.ts +4 -4
  254. package/lib/types/{shared.d.ts → shared/index.d.ts} +7 -16
  255. package/lib/types/shared/serializeRegExp.d.ts +9 -0
  256. package/lib/types/types.d.ts +490 -489
  257. package/package.json +115 -102
  258. package/preset.js +9 -9
  259. package/types/babel__register.d.ts +1 -1
  260. package/types/chai.d.ts +12 -12
  261. package/types/event-source-polyfill.d.ts +6 -6
  262. package/types/mdx.d.ts +3 -2
  263. package/types/mocha.d.ts +20 -20
  264. package/types/png.d.ts +4 -4
  265. package/lib/cjs/client/web/1.js +0 -13
  266. package/lib/cjs/client/web/2.js +0 -1
  267. package/storybook-static/stories.json +0 -21
@@ -0,0 +1,424 @@
1
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
2
+
3
+ function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
4
+
5
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
6
+
7
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
8
+
9
+ 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; }
10
+
11
+ function _toArray(arr) { return _arrayWithHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableRest(); }
12
+
13
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
14
+
15
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
16
+
17
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
18
+
19
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
20
+
21
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
22
+
23
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
24
+
25
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
26
+
27
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
28
+
29
+ import { themes } from '@storybook/theming';
30
+ import { parse, stringify } from 'qs';
31
+ import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
32
+ import { isTest, isDefined } from '../../types';
33
+ var statusUpdatesMap = new Map([[undefined, /(unknown|success|failed|pending|running)/], ['unknown', /(success|failed|pending|running)/], ['success', /(failed|pending|running)/], ['failed', /(pending|running)/], ['pending', /running/]]);
34
+
35
+ function makeEmptySuiteNode() {
36
+ var path = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
37
+ return {
38
+ path: path,
39
+ skip: true,
40
+ opened: false,
41
+ checked: true,
42
+ indeterminate: false,
43
+ children: {}
44
+ };
45
+ }
46
+
47
+ export function calcStatus(oldStatus, newStatus) {
48
+ var _statusUpdatesMap$get;
49
+
50
+ return newStatus && (_statusUpdatesMap$get = statusUpdatesMap.get(oldStatus)) !== null && _statusUpdatesMap$get !== void 0 && _statusUpdatesMap$get.test(newStatus) ? newStatus : oldStatus;
51
+ }
52
+ export function getTestPath(test) {
53
+ var browser = test.browser,
54
+ testName = test.testName,
55
+ storyPath = test.storyPath;
56
+ return [].concat(_toConsumableArray(storyPath), [testName, browser]).filter(isDefined);
57
+ }
58
+ export function getSuiteByPath(suite, path) {
59
+ return path.reduce(function (suiteOrTest, pathToken) {
60
+ return isTest(suiteOrTest) ? suiteOrTest : suiteOrTest === null || suiteOrTest === void 0 ? void 0 : suiteOrTest.children[pathToken];
61
+ }, suite);
62
+ }
63
+ export function getTestByPath(suite, path) {
64
+ var _getSuiteByPath;
65
+
66
+ var test = (_getSuiteByPath = getSuiteByPath(suite, path)) !== null && _getSuiteByPath !== void 0 ? _getSuiteByPath : suite;
67
+ return isTest(test) ? test : null;
68
+ }
69
+ export function getTestsByStoryId(suite, storyId) {
70
+ return Object.values(suite.children).filter(isDefined).flatMap(function (suiteOrTest) {
71
+ if (isTest(suiteOrTest)) return suiteOrTest.storyId === storyId ? suiteOrTest : [];
72
+ return getTestsByStoryId(suiteOrTest, storyId);
73
+ }).filter(isDefined);
74
+ }
75
+
76
+ function checkTests(suiteOrTest, checked) {
77
+ suiteOrTest.checked = checked;
78
+
79
+ if (!isTest(suiteOrTest)) {
80
+ suiteOrTest.indeterminate = false;
81
+ Object.values(suiteOrTest.children).filter(isDefined).forEach(function (child) {
82
+ return checkTests(child, checked);
83
+ });
84
+ }
85
+ }
86
+
87
+ function updateChecked(suite) {
88
+ var children = Object.values(suite.children).filter(isDefined).filter(function (child) {
89
+ return !child.skip;
90
+ });
91
+ var checkedEvery = children.every(function (test) {
92
+ return test.checked;
93
+ });
94
+ var checkedSome = children.some(function (test) {
95
+ return test.checked;
96
+ });
97
+ var indeterminate = children.some(function (test) {
98
+ return isTest(test) ? false : test.indeterminate;
99
+ }) || !checkedEvery && checkedSome;
100
+ var checked = indeterminate || suite.checked == checkedEvery ? suite.checked : checkedEvery;
101
+ suite.checked = checked;
102
+ suite.indeterminate = indeterminate;
103
+ }
104
+
105
+ export function checkSuite(suite, path, checked) {
106
+ var subSuite = getSuiteByPath(suite, path);
107
+ if (subSuite) checkTests(subSuite, checked);
108
+ path.slice(0, -1).map(function (_, index, tokens) {
109
+ return tokens.slice(0, tokens.length - index);
110
+ }).forEach(function (parentPath) {
111
+ var parentSuite = getSuiteByPath(suite, parentPath);
112
+ if (isTest(parentSuite)) return;
113
+ if (parentSuite) updateChecked(parentSuite);
114
+ });
115
+ updateChecked(suite);
116
+ }
117
+ export function treeifyTests(testsById) {
118
+ var rootSuite = makeEmptySuiteNode();
119
+ rootSuite.opened = true;
120
+ Object.values(testsById).forEach(function (test) {
121
+ if (!test) return;
122
+
123
+ var _getTestPath$reverse = getTestPath(test).reverse(),
124
+ _getTestPath$reverse2 = _toArray(_getTestPath$reverse),
125
+ browser = _getTestPath$reverse2[0],
126
+ testPath = _getTestPath$reverse2.slice(1);
127
+
128
+ var lastSuite = testPath.reverse().reduce(function (suite, token) {
129
+ var subSuite = suite.children[token] || makeEmptySuiteNode([].concat(_toConsumableArray(suite.path), [token]));
130
+ subSuite.status = calcStatus(subSuite.status, test.status);
131
+ if (!test.skip) subSuite.skip = false;
132
+ if (!subSuite.skip) suite.skip = false;
133
+ suite.children[token] = subSuite;
134
+ suite.status = calcStatus(suite.status, subSuite.status);
135
+
136
+ if (isTest(subSuite)) {
137
+ throw new Error("Suite and Test should not have same path '".concat(JSON.stringify(getTestPath(subSuite)), "'"));
138
+ }
139
+
140
+ return subSuite;
141
+ }, rootSuite);
142
+ lastSuite.children[browser] = _objectSpread(_objectSpread({}, test), {}, {
143
+ checked: true
144
+ });
145
+ });
146
+ return rootSuite;
147
+ }
148
+ export function getCheckedTests(suite) {
149
+ return Object.values(suite.children).filter(isDefined).flatMap(function (suiteOrTest) {
150
+ if (isTest(suiteOrTest)) return suiteOrTest.checked ? suiteOrTest : [];
151
+ if (!suiteOrTest.checked && !suiteOrTest.indeterminate) return [];
152
+ return getCheckedTests(suiteOrTest);
153
+ });
154
+ }
155
+ export function updateTestStatus(suite, path, update) {
156
+ var _suite$children$title;
157
+
158
+ var title = path.shift();
159
+ if (!title) return;
160
+ var suiteOrTest = (_suite$children$title = suite.children[title]) !== null && _suite$children$title !== void 0 ? _suite$children$title : suite.children[title] = _objectSpread(_objectSpread({}, path.length == 0 ? update : makeEmptySuiteNode([].concat(_toConsumableArray(suite.path), [title]))), {}, {
161
+ checked: suite.checked
162
+ });
163
+
164
+ if (isTest(suiteOrTest)) {
165
+ var _test$results;
166
+
167
+ var test = suiteOrTest;
168
+ var skip = update.skip,
169
+ status = update.status,
170
+ results = update.results,
171
+ approved = update.approved;
172
+ if (isDefined(skip)) test.skip = skip;
173
+ if (isDefined(status)) test.status = status;
174
+ if (isDefined(results)) test.results ? (_test$results = test.results).push.apply(_test$results, _toConsumableArray(results)) : test.results = results;
175
+ if (isDefined(approved)) Object.entries(approved).forEach(function (_ref) {
176
+ var _ref2 = _slicedToArray(_ref, 2),
177
+ image = _ref2[0],
178
+ retry = _ref2[1];
179
+
180
+ return retry !== undefined && ((test.approved = test.approved || {})[image] = retry);
181
+ });
182
+ } else {
183
+ var subSuite = suiteOrTest;
184
+ updateTestStatus(subSuite, path, update);
185
+ }
186
+
187
+ suite.skip = Object.values(suite.children).filter(isDefined).map(function (_ref3) {
188
+ var skip = _ref3.skip;
189
+ return skip;
190
+ }).every(Boolean);
191
+ suite.status = Object.values(suite.children).filter(isDefined).map(function (_ref4) {
192
+ var status = _ref4.status;
193
+ return status;
194
+ }).reduce(calcStatus);
195
+ }
196
+ export function removeTests(suite, path) {
197
+ var _suiteOrTest$children;
198
+
199
+ var title = path.shift();
200
+ if (!title) return;
201
+ var suiteOrTest = suite.children[title];
202
+ if (suiteOrTest && !isTest(suiteOrTest)) removeTests(suiteOrTest, path);
203
+ if (isTest(suiteOrTest) || Object.keys((_suiteOrTest$children = suiteOrTest === null || suiteOrTest === void 0 ? void 0 : suiteOrTest.children) !== null && _suiteOrTest$children !== void 0 ? _suiteOrTest$children : {}).length == 0) delete suite.children[title];
204
+ if (Object.keys(suite.children).length == 0) return;
205
+ updateChecked(suite);
206
+ suite.skip = Object.values(suite.children).filter(isDefined).map(function (_ref5) {
207
+ var skip = _ref5.skip;
208
+ return skip;
209
+ }).every(Boolean);
210
+ suite.status = Object.values(suite.children).filter(isDefined).map(function (_ref6) {
211
+ var status = _ref6.status;
212
+ return status;
213
+ }).reduce(calcStatus);
214
+ }
215
+ export function filterTests(suite, filter) {
216
+ var status = filter.status,
217
+ subStrings = filter.subStrings;
218
+ if (!status && !subStrings.length) return suite;
219
+
220
+ var filteredSuite = _objectSpread(_objectSpread({}, suite), {}, {
221
+ children: {}
222
+ });
223
+
224
+ Object.entries(suite.children).forEach(function (_ref7) {
225
+ var _ref8 = _slicedToArray(_ref7, 2),
226
+ title = _ref8[0],
227
+ suiteOrTest = _ref8[1];
228
+
229
+ if (!suiteOrTest || suiteOrTest.skip) return;
230
+
231
+ if (!status && subStrings.some(function (subString) {
232
+ return title.toLowerCase().includes(subString);
233
+ })) {
234
+ filteredSuite.children[title] = suiteOrTest;
235
+ } else if (isTest(suiteOrTest)) {
236
+ if (status && suiteOrTest.status && ['pending', 'running', status].includes(suiteOrTest.status)) filteredSuite.children[title] = suiteOrTest;
237
+ } else {
238
+ var filteredSubSuite = filterTests(suiteOrTest, filter);
239
+ if (Object.keys(filteredSubSuite.children).length == 0) return;
240
+ filteredSuite.children[title] = filteredSubSuite;
241
+ }
242
+ });
243
+ return filteredSuite;
244
+ }
245
+ export function openSuite(suite, path, opened) {
246
+ var subSuite = path.reduce(function (suiteOrTest, pathToken) {
247
+ if (suiteOrTest && !isTest(suiteOrTest)) {
248
+ if (opened) suiteOrTest.opened = opened;
249
+ return suiteOrTest.children[pathToken];
250
+ }
251
+ }, suite);
252
+ if (subSuite && !isTest(subSuite)) subSuite.opened = opened;
253
+ }
254
+ export function flattenSuite(suite) {
255
+ if (!suite.opened) return [];
256
+ return Object.entries(suite.children).flatMap(function (_ref9) {
257
+ var _ref10 = _slicedToArray(_ref9, 2),
258
+ title = _ref10[0],
259
+ subSuite = _ref10[1];
260
+
261
+ return subSuite ? [{
262
+ title: title,
263
+ suite: subSuite
264
+ }].concat(_toConsumableArray(isTest(subSuite) ? [] : flattenSuite(subSuite))) : [];
265
+ });
266
+ }
267
+ export function countTestsStatus(suite) {
268
+ var successCount = 0;
269
+ var failedCount = 0;
270
+ var skippedCount = 0;
271
+ var pendingCount = 0;
272
+ var cases = Object.values(suite.children).filter(isDefined);
273
+ var suiteOrTest;
274
+
275
+ while (suiteOrTest = cases.pop()) {
276
+ if (isTest(suiteOrTest)) {
277
+ if (suiteOrTest.skip) skippedCount++;
278
+ if (suiteOrTest.status === 'success') successCount++;
279
+ if (suiteOrTest.status === 'failed') failedCount++;
280
+ if (suiteOrTest.status === 'pending') pendingCount++;
281
+ } else {
282
+ cases.push.apply(cases, _toConsumableArray(Object.values(suiteOrTest.children).filter(isDefined)));
283
+ }
284
+ }
285
+
286
+ return {
287
+ successCount: successCount,
288
+ failedCount: failedCount,
289
+ skippedCount: skippedCount,
290
+ pendingCount: pendingCount
291
+ };
292
+ }
293
+ export function getConnectionUrl() {
294
+ return [typeof __CREEVEY_SERVER_HOST__ == 'undefined' ? window.location.hostname : __CREEVEY_SERVER_HOST__, typeof __CREEVEY_SERVER_PORT__ == 'undefined' ? window.location.port : __CREEVEY_SERVER_PORT__].filter(Boolean).join(':');
295
+ }
296
+ export function getImageUrl(path, imageName) {
297
+ // path => [kind, story, test, browser]
298
+ var browser = path.slice(-1)[0];
299
+ var imagesUrl = window.location.host ? "".concat(window.location.protocol, "//").concat(getConnectionUrl()).concat(window.location.pathname == '/' ? '/report' : window.location.pathname.split('/').slice(0, -1).join('/'), "/").concat(encodeURI(path.slice(0, -1).join('/'))) : encodeURI(path.slice(0, -1).join('/'));
300
+ return imageName == browser ? imagesUrl : "".concat(imagesUrl, "/").concat(encodeURI(browser));
301
+ }
302
+ export function getBorderSize(element) {
303
+ // NOTE Firefox returns empty string for `borderWidth` prop
304
+ var borderSize = parseFloat(getComputedStyle(element).borderTopWidth);
305
+ return Number.isNaN(borderSize) ? 0 : borderSize;
306
+ }
307
+ export function useLoadImages(s1, s2, s3) {
308
+ var _useState = useState(false),
309
+ _useState2 = _slicedToArray(_useState, 2),
310
+ loaded = _useState2[0],
311
+ setLoaded = _useState2[1];
312
+
313
+ useEffect(function () {
314
+ setLoaded(false);
315
+ void Promise.all([s1, s2, s3].map(function (url) {
316
+ return new Promise(function (resolve) {
317
+ var image = document.createElement('img');
318
+ image.src = url;
319
+ image.onload = resolve;
320
+ image.onerror = resolve;
321
+ });
322
+ })).then(function () {
323
+ return setLoaded(true);
324
+ });
325
+ }, [s1, s2, s3]);
326
+ return loaded;
327
+ }
328
+ /**
329
+ * Uses the ResizeObserver API to observe changes within the given HTML Element DOM Rect.
330
+ *
331
+ * @returns dimensions of element's content box (which means without paddings and border width)
332
+ */
333
+
334
+ export function useResizeObserver(elementRef, onResize) {
335
+ var debounceTimeout = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 16;
336
+ var observerRef = useRef(null);
337
+ useEffect(function () {
338
+ if (!elementRef.current) return;
339
+ observerRef.current = new ResizeObserver(onResize);
340
+ observerRef.current.observe(elementRef.current);
341
+ return function () {
342
+ var _observerRef$current;
343
+
344
+ return (_observerRef$current = observerRef.current) === null || _observerRef$current === void 0 ? void 0 : _observerRef$current.disconnect();
345
+ };
346
+ }, [debounceTimeout, elementRef, onResize]);
347
+ }
348
+ export function useApplyScale(imageRef, scale, dependency) {
349
+ useLayoutEffect(function () {
350
+ if (!imageRef.current) return;
351
+ var image = imageRef.current;
352
+ var borderSize = getBorderSize(image);
353
+ image.style.height = "".concat(image.naturalHeight * scale + borderSize * 2, "px");
354
+ }, [imageRef, scale, dependency]);
355
+ }
356
+ export function useCalcScale(diffImageRef, loaded) {
357
+ var _useState3 = useState(1),
358
+ _useState4 = _slicedToArray(_useState3, 2),
359
+ scale = _useState4[0],
360
+ setScale = _useState4[1];
361
+
362
+ var calcScale = useCallback(function () {
363
+ var diffImage = diffImageRef.current;
364
+ if (!diffImage || !loaded) return setScale(1);
365
+ var borderSize = getBorderSize(diffImage);
366
+ var ratio = (diffImage.getBoundingClientRect().width - borderSize * 2) / diffImage.naturalWidth;
367
+ setScale(Math.min(1, ratio));
368
+ }, [diffImageRef, loaded]);
369
+ useResizeObserver(diffImageRef, calcScale);
370
+ useLayoutEffect(calcScale, [calcScale]);
371
+ return scale;
372
+ }
373
+ var CREEVEY_THEME = 'Creevey_theme';
374
+
375
+ function isTheme(theme) {
376
+ return isDefined(theme) && Object.prototype.hasOwnProperty.call(themes, theme);
377
+ }
378
+
379
+ function initialTheme() {
380
+ var theme = localStorage.getItem(CREEVEY_THEME);
381
+ return isTheme(theme) ? theme : 'light';
382
+ }
383
+
384
+ export function useTheme() {
385
+ var _useState5 = useState(initialTheme()),
386
+ _useState6 = _slicedToArray(_useState5, 2),
387
+ theme = _useState6[0],
388
+ setTheme = _useState6[1];
389
+
390
+ useEffect(function () {
391
+ localStorage.setItem(CREEVEY_THEME, theme);
392
+ }, [theme]);
393
+ return [theme, setTheme];
394
+ }
395
+ export function setSearchParams(testPath) {
396
+ var pageUrl = "?".concat(stringify({
397
+ testPath: testPath
398
+ }));
399
+ window.history.pushState({
400
+ testPath: testPath
401
+ }, '', pageUrl);
402
+ }
403
+ export function getTestPathFromSearch() {
404
+ var _parse = parse(window.location.search.slice(1)),
405
+ testPath = _parse.testPath; //@ts-expect-error: This expression is not callable.
406
+
407
+
408
+ if (Array.isArray(testPath) && testPath.every(function (token) {
409
+ return typeof token == 'string';
410
+ })) {
411
+ return testPath;
412
+ }
413
+
414
+ return [];
415
+ }
416
+ export function useForceUpdate() {
417
+ var _useState7 = useState({}),
418
+ _useState8 = _slicedToArray(_useState7, 2),
419
+ update = _useState8[1];
420
+
421
+ return useCallback(function () {
422
+ return update({});
423
+ }, []);
424
+ }
@@ -0,0 +1,6 @@
1
+ export var VIEW_MODE_KEY = 'Creevey_view_mode';
2
+ export var viewModes = ['side-by-side', 'swap', 'slide', 'blend'];
3
+ export var getViewMode = function getViewMode() {
4
+ var item = localStorage.getItem(VIEW_MODE_KEY);
5
+ return item && viewModes.includes(item) ? item : 'side-by-side';
6
+ };
@@ -0,0 +1,54 @@
1
+ import cluster from 'cluster';
2
+ import minimist from 'minimist';
3
+ import creevey from './server';
4
+ import { noop } from './types';
5
+ import { emitWorkerMessage } from './server/messages';
6
+ import { isShuttingDown, shutdown, shutdownWorkers } from './server/utils';
7
+ import { setDefaultLevel, levels } from 'loglevel';
8
+ import { logger } from './server/logger';
9
+
10
+ function shutdownOnException(reason) {
11
+ if (isShuttingDown.current) return;
12
+ const error = reason instanceof Error ? reason.stack ?? reason.message : reason;
13
+ logger.error(error);
14
+ process.exitCode = -1;
15
+ if (cluster.isWorker) emitWorkerMessage({
16
+ type: 'error',
17
+ payload: {
18
+ error
19
+ }
20
+ });
21
+ if (cluster.isPrimary && !isShuttingDown.current) void shutdownWorkers();
22
+ }
23
+
24
+ process.on('uncaughtException', shutdownOnException);
25
+ process.on('unhandledRejection', shutdownOnException);
26
+ if (cluster.isWorker) process.on('SIGINT', noop);
27
+ if (cluster.isPrimary) process.on('SIGINT', shutdown);
28
+ const argv = minimist(process.argv.slice(2), {
29
+ string: ['browser', 'config', 'reporter', 'reportDir', 'screenDir'],
30
+ boolean: ['debug', 'ui', 'saveReport', 'webpack', 'tests'],
31
+ default: {
32
+ port: 3000,
33
+ saveReport: true
34
+ },
35
+ alias: {
36
+ port: 'p',
37
+ config: 'c',
38
+ debug: 'd',
39
+ update: 'u',
40
+ extract: 'e'
41
+ }
42
+ }); // @ts-expect-error: define log level for storybook
43
+
44
+ global.LOGLEVEL = argv.debug ? 'debug' : 'warn';
45
+
46
+ if (argv.debug) {
47
+ logger.setDefaultLevel(levels.DEBUG);
48
+ setDefaultLevel(levels.DEBUG);
49
+ } else {
50
+ logger.setDefaultLevel(levels.INFO);
51
+ setDefaultLevel(levels.INFO);
52
+ }
53
+
54
+ void creevey(argv);
@@ -0,0 +1,5 @@
1
+ export * from './types';
2
+ export { loadStories as browserStoriesProvider } from './server/storybook/providers/browser';
3
+ export { loadStories as nodejsStoriesProvider } from './server/storybook/providers/nodejs';
4
+ export { loadStories as hybridStoriesProvider } from './server/storybook/providers/hybrid';
5
+ export * from './server/testsFiles/parser';
@@ -0,0 +1,73 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { isCSFv3Enabled, isStorybookVersionGreaterThan, isStorybookVersionLessThan, storybookDirRef } from './storybook/helpers';
4
+ import { loadStories as nodejsStoriesProvider } from './storybook/providers/nodejs';
5
+ import { loadStories as browserStoriesProvider } from './storybook/providers/browser';
6
+ import { isDefined } from '../types';
7
+ export const defaultBrowser = 'chrome';
8
+ export const defaultConfig = {
9
+ useDocker: true,
10
+ useWebpackToExtractTests: false,
11
+ dockerImage: 'aerokube/selenoid:latest-release',
12
+ dockerImagePlatform: '',
13
+ pullImages: true,
14
+ failFast: false,
15
+ storybookUrl: 'http://localhost:6006',
16
+ screenDir: path.resolve('images'),
17
+ reportDir: path.resolve('report'),
18
+ storybookDir: path.resolve('.storybook'),
19
+ maxRetries: 0,
20
+ diffOptions: {
21
+ threshold: 0,
22
+ includeAA: true
23
+ },
24
+ browsers: {
25
+ [defaultBrowser]: true
26
+ },
27
+ hooks: {},
28
+ babelOptions: _ => _,
29
+ testsRegex: /\.creevey\.(t|j)s$/
30
+ };
31
+
32
+ function normalizeBrowserConfig(name, config) {
33
+ if (typeof config == 'boolean') return {
34
+ browserName: name
35
+ };
36
+ if (typeof config == 'string') return {
37
+ browserName: config
38
+ };
39
+ return config;
40
+ }
41
+
42
+ function resolveConfigPath(configPath) {
43
+ const rootDir = process.cwd();
44
+ const configDir = path.resolve('.creevey');
45
+
46
+ if (isDefined(configPath)) {
47
+ configPath = path.resolve(configPath);
48
+ } else if (fs.existsSync(configDir)) {
49
+ configPath = path.join(configDir, 'config'); // TODO We already find file with extension, why not use it?
50
+ } else if (fs.readdirSync(rootDir).find(filename => filename.startsWith('creevey.config'))) {
51
+ configPath = path.join(rootDir, 'creevey.config');
52
+ }
53
+
54
+ return configPath;
55
+ }
56
+
57
+ export async function readConfig(options) {
58
+ const configPath = resolveConfigPath(options.config);
59
+ const userConfig = { ...defaultConfig
60
+ };
61
+ 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");
66
+ if (options.failFast != undefined) userConfig.failFast = Boolean(options.failFast);
67
+ 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
69
+
70
+ const config = userConfig;
71
+ Object.entries(config.browsers).forEach(([browser, browserConfig]) => config.browsers[browser] = normalizeBrowserConfig(browser, browserConfig));
72
+ return config;
73
+ }
@@ -0,0 +1,123 @@
1
+ import cluster from 'cluster';
2
+ import { isDockerMessage } from '../types';
3
+ import { subscribeOn, sendDockerMessage, emitDockerMessage } from './messages';
4
+ import { isInsideDocker, LOCALHOST_REGEXP } from './utils';
5
+ import Dockerode from 'dockerode';
6
+ import { Writable } from 'stream';
7
+ import ora from 'ora';
8
+ import { logger } from './logger';
9
+ const docker = new Dockerode();
10
+
11
+ class DevNull extends Writable {
12
+ _write(_chunk, _encoding, callback) {
13
+ setImmediate(callback);
14
+ }
15
+
16
+ }
17
+
18
+ export async function pullImages(images, {
19
+ auth,
20
+ platform
21
+ } = {}) {
22
+ const args = {};
23
+ if (auth) args.authconfig = auth;
24
+ if (platform) args.platform = platform;
25
+ logger.info('Pull docker images');
26
+
27
+ for (const image of images) {
28
+ await new Promise((resolve, reject) => {
29
+ const spinner = ora(`${image}: Pull start`).start(); // eslint-disable-next-line @typescript-eslint/no-floating-promises
30
+
31
+ docker.pull(image, args, function (pullError, stream) {
32
+ if (pullError) {
33
+ spinner.fail();
34
+ return reject(pullError);
35
+ } // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
36
+
37
+
38
+ docker.modem.followProgress(stream, onFinished, onProgress);
39
+
40
+ function onFinished(error) {
41
+ if (error) {
42
+ spinner.fail();
43
+ return reject(error);
44
+ }
45
+
46
+ spinner.succeed(`${image}: Pull complete`);
47
+ resolve();
48
+ }
49
+
50
+ function onProgress(event) {
51
+ if (!/^[a-z0-9]{12}$/i.test(event.id)) return;
52
+ spinner.text = `${image}: [${event.id}] ${event.status} ${event.progress ? `${event.progress}` : ''}`;
53
+ }
54
+ });
55
+ });
56
+ }
57
+ }
58
+ export async function runImage(image, args, options, debug) {
59
+ await Promise.all((await docker.listContainers({
60
+ all: true,
61
+ filters: {
62
+ ancestor: [image]
63
+ }
64
+ })).map(async info => {
65
+ const container = docker.getContainer(info.Id);
66
+
67
+ try {
68
+ await container.stop();
69
+ } catch (_) {
70
+ /* noop */
71
+ }
72
+
73
+ await container.remove();
74
+ }));
75
+ const hub = docker.run(image, args, debug ? process.stdout : new DevNull(), options, error => {
76
+ if (error) throw error;
77
+ });
78
+ return new Promise(resolve => {
79
+ hub.once('container', container => {
80
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
81
+ subscribeOn('shutdown', async () => {
82
+ try {
83
+ await container.stop();
84
+ await container.remove();
85
+ } catch (error) {
86
+ /* noop */
87
+ }
88
+ });
89
+ });
90
+ hub.once('start', container => void container.inspect().then(info => resolve(info.NetworkSettings.Networks.bridge.IPAddress)));
91
+ });
92
+ }
93
+ export default async function (config, browser, startContainer) {
94
+ if (cluster.isPrimary) {
95
+ const host = await startContainer();
96
+ let gridUrl = 'http://localhost:4444/wd/hub';
97
+ gridUrl = isInsideDocker ? gridUrl.replace(LOCALHOST_REGEXP, host) : gridUrl;
98
+ cluster.on('message', (worker, message) => {
99
+ if (!isDockerMessage(message)) return;
100
+ const dockerMessage = message;
101
+ if (dockerMessage.type != 'start') return;
102
+ sendDockerMessage(worker, {
103
+ type: 'success',
104
+ payload: {
105
+ gridUrl
106
+ }
107
+ });
108
+ });
109
+ } else {
110
+ if (browser && config.browsers[browser].gridUrl) return Promise.resolve();
111
+ return new Promise(resolve => {
112
+ subscribeOn('docker', message => {
113
+ if (message.type == 'success') {
114
+ config.gridUrl = message.payload.gridUrl;
115
+ resolve();
116
+ }
117
+ });
118
+ emitDockerMessage({
119
+ type: 'start'
120
+ });
121
+ });
122
+ }
123
+ }