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.
- package/AUTHORS +15 -15
- package/CHANGELOG.md +1275 -1275
- package/LICENSE +21 -21
- package/README.md +7 -0
- package/addon/README.md +3 -0
- package/addon/package.json +4 -0
- package/docs/config.md +212 -212
- package/docs/grid.md +10 -10
- package/docs/tests.md +63 -63
- package/jest.config.js +6 -0
- package/lib/cjs/cli.js +5 -0
- package/lib/cjs/client/addon/Manager.js +418 -0
- package/lib/cjs/client/addon/components/Addon.js +76 -0
- package/lib/cjs/client/addon/components/Icons.js +42 -0
- package/lib/cjs/client/addon/components/Panel.js +68 -0
- package/lib/cjs/client/addon/components/TestSelect.js +63 -0
- package/lib/cjs/client/addon/components/Tools.js +114 -0
- package/lib/cjs/client/addon/decorator.js +11 -0
- package/lib/cjs/client/addon/index.js +31 -0
- package/lib/cjs/client/addon/preset.js +81 -0
- package/lib/cjs/client/addon/readyForCapture.js +12 -0
- package/lib/cjs/client/addon/register.js +100 -0
- package/lib/cjs/client/addon/utils.js +38 -0
- package/lib/cjs/client/addon/withCreevey.js +558 -0
- package/lib/cjs/client/shared/components/ImagesView/BlendView.js +85 -0
- package/lib/cjs/client/shared/components/ImagesView/ImagesView.js +88 -0
- package/lib/cjs/client/shared/components/ImagesView/SideBySideView.js +176 -0
- package/lib/cjs/client/shared/components/ImagesView/SlideView.js +179 -0
- package/lib/cjs/client/shared/components/ImagesView/SwapView.js +110 -0
- package/lib/cjs/client/shared/components/ImagesView/index.js +45 -0
- package/lib/cjs/client/shared/components/PageFooter/PageFooter.js +46 -0
- package/lib/cjs/client/shared/components/PageFooter/Paging.js +98 -0
- package/lib/cjs/client/shared/components/PageHeader/ImagePreview.js +78 -0
- package/lib/cjs/client/shared/components/PageHeader/PageHeader.js +144 -0
- package/lib/cjs/client/shared/components/ResultsPage.js +173 -0
- package/lib/cjs/client/shared/creeveyClientApi.js +107 -0
- package/lib/cjs/client/shared/helpers.js +482 -0
- package/lib/cjs/client/shared/viewMode.js +17 -0
- package/lib/cjs/client/web/142.js +2 -0
- package/lib/cjs/client/web/142.js.LICENSE.txt +12 -0
- package/lib/cjs/client/web/32.js +1 -0
- package/lib/cjs/client/web/551.js +1 -0
- package/lib/cjs/client/web/566.js +2 -0
- package/lib/cjs/client/web/566.js.LICENSE.txt +31 -0
- package/lib/cjs/client/web/691.js +2 -0
- package/lib/cjs/client/web/691.js.LICENSE.txt +8 -0
- package/lib/cjs/client/web/725.js +1 -0
- package/lib/cjs/client/web/index.html +19 -0
- package/lib/cjs/client/web/main.js +2 -38
- package/lib/cjs/client/web/main.js.LICENSE.txt +49 -0
- package/lib/cjs/creevey.js +69 -0
- package/lib/cjs/index.js +62 -0
- package/lib/cjs/server/config.js +96 -0
- package/lib/cjs/server/docker.js +146 -0
- package/lib/cjs/server/extract.js +50 -0
- package/lib/cjs/server/index.js +83 -0
- package/lib/cjs/server/loaders/babel/creevey-plugin.js +86 -0
- package/lib/cjs/server/loaders/babel/helpers.js +469 -0
- package/lib/cjs/server/loaders/babel/register.js +124 -0
- package/lib/cjs/server/loaders/hooks/mdx.js +30 -0
- package/lib/cjs/server/loaders/hooks/svelte.js +65 -0
- package/lib/cjs/server/loaders/webpack/compile.js +293 -0
- package/lib/cjs/server/loaders/webpack/creevey-loader.js +179 -0
- package/lib/cjs/server/loaders/webpack/dummy-hmr.js +39 -0
- package/lib/cjs/server/loaders/webpack/mdx-loader.js +72 -0
- package/lib/cjs/server/loaders/webpack/start.js +41 -0
- package/lib/cjs/server/logger.js +48 -0
- package/lib/cjs/server/master/api.js +71 -0
- package/lib/cjs/server/master/index.js +146 -0
- package/lib/cjs/server/master/master.js +57 -0
- package/lib/cjs/server/master/pool.js +197 -0
- package/lib/cjs/server/master/runner.js +281 -0
- package/lib/cjs/server/master/server.js +129 -0
- package/lib/cjs/server/messages.js +264 -0
- package/lib/cjs/server/selenium/browser.js +672 -0
- package/lib/cjs/server/selenium/index.js +31 -0
- package/lib/cjs/server/selenium/selenoid.js +172 -0
- package/lib/cjs/server/stories.js +159 -0
- package/lib/cjs/server/storybook/entry.js +70 -0
- package/lib/cjs/server/storybook/helpers.js +159 -0
- package/lib/cjs/server/storybook/providers/browser.js +74 -0
- package/lib/cjs/server/storybook/providers/hybrid.js +84 -0
- package/lib/cjs/server/storybook/providers/nodejs.js +239 -0
- package/lib/cjs/server/testsFiles/parser.js +72 -0
- package/lib/cjs/server/testsFiles/register.js +48 -0
- package/lib/cjs/server/update.js +79 -0
- package/lib/cjs/server/utils.js +183 -0
- package/lib/cjs/server/worker/chai-image.js +142 -0
- package/lib/cjs/server/worker/helpers.js +69 -0
- package/lib/cjs/server/worker/index.js +15 -0
- package/lib/cjs/server/worker/reporter.js +108 -0
- package/lib/cjs/server/worker/worker.js +268 -0
- package/lib/cjs/shared/index.js +89 -0
- package/lib/cjs/shared/serializeRegExp.js +41 -0
- package/lib/cjs/types.js +74 -0
- package/lib/esm/cli.js +4 -0
- package/lib/esm/client/addon/Manager.js +402 -0
- package/lib/esm/client/addon/components/Addon.js +58 -0
- package/lib/esm/client/addon/components/Icons.js +27 -0
- package/lib/esm/client/addon/components/Panel.js +49 -0
- package/lib/esm/client/addon/components/TestSelect.js +49 -0
- package/lib/esm/client/addon/components/Tools.js +91 -0
- package/lib/esm/client/addon/decorator.js +2 -0
- package/lib/esm/client/addon/index.js +2 -0
- package/lib/esm/client/addon/preset.js +56 -0
- package/lib/esm/client/addon/readyForCapture.js +5 -0
- package/lib/esm/client/addon/register.js +79 -0
- package/lib/esm/client/addon/utils.js +31 -0
- package/lib/esm/client/addon/withCreevey.js +534 -0
- package/lib/esm/client/shared/components/ImagesView/BlendView.js +63 -0
- package/lib/esm/client/shared/components/ImagesView/ImagesView.js +65 -0
- package/lib/esm/client/shared/components/ImagesView/SideBySideView.js +151 -0
- package/lib/esm/client/shared/components/ImagesView/SlideView.js +154 -0
- package/lib/esm/client/shared/components/ImagesView/SwapView.js +88 -0
- package/lib/esm/client/shared/components/ImagesView/index.js +5 -0
- package/lib/esm/client/shared/components/PageFooter/PageFooter.js +32 -0
- package/lib/esm/client/shared/components/PageFooter/Paging.js +84 -0
- package/lib/esm/client/shared/components/PageHeader/ImagePreview.js +64 -0
- package/lib/esm/client/shared/components/PageHeader/PageHeader.js +120 -0
- package/lib/esm/client/shared/components/ResultsPage.js +143 -0
- package/lib/esm/client/shared/creeveyClientApi.js +98 -0
- package/lib/esm/client/shared/helpers.js +424 -0
- package/lib/esm/client/shared/viewMode.js +6 -0
- package/lib/esm/creevey.js +54 -0
- package/lib/esm/index.js +5 -0
- package/lib/esm/server/config.js +73 -0
- package/lib/esm/server/docker.js +123 -0
- package/lib/esm/server/extract.js +34 -0
- package/lib/esm/server/index.js +64 -0
- package/lib/esm/server/loaders/babel/creevey-plugin.js +72 -0
- package/lib/esm/server/loaders/babel/helpers.js +452 -0
- package/lib/esm/server/loaders/babel/register.js +103 -0
- package/lib/esm/server/loaders/hooks/mdx.js +15 -0
- package/lib/esm/server/loaders/hooks/svelte.js +49 -0
- package/lib/esm/server/loaders/webpack/compile.js +270 -0
- package/lib/esm/server/loaders/webpack/creevey-loader.js +158 -0
- package/lib/esm/server/loaders/webpack/dummy-hmr.js +32 -0
- package/lib/esm/server/loaders/webpack/mdx-loader.js +58 -0
- package/lib/esm/server/loaders/webpack/start.js +27 -0
- package/lib/esm/server/logger.js +20 -0
- package/lib/esm/server/master/api.js +60 -0
- package/lib/esm/server/master/index.js +125 -0
- package/lib/esm/server/master/master.js +38 -0
- package/lib/esm/server/master/pool.js +176 -0
- package/lib/esm/server/master/runner.js +259 -0
- package/lib/esm/server/master/server.js +105 -0
- package/lib/esm/server/messages.js +232 -0
- package/lib/esm/server/selenium/browser.js +639 -0
- package/lib/esm/server/selenium/index.js +2 -0
- package/lib/esm/server/selenium/selenoid.js +149 -0
- package/lib/esm/server/stories.js +140 -0
- package/lib/esm/server/storybook/entry.js +46 -0
- package/lib/esm/server/storybook/helpers.js +98 -0
- package/lib/esm/server/storybook/providers/browser.js +60 -0
- package/lib/esm/server/storybook/providers/hybrid.js +64 -0
- package/lib/esm/server/storybook/providers/nodejs.js +217 -0
- package/lib/esm/server/testsFiles/parser.js +50 -0
- package/lib/esm/server/testsFiles/register.js +35 -0
- package/lib/esm/server/update.js +61 -0
- package/lib/esm/server/utils.js +142 -0
- package/lib/esm/server/worker/chai-image.js +130 -0
- package/lib/esm/server/worker/helpers.js +60 -0
- package/lib/esm/server/worker/index.js +1 -0
- package/lib/esm/server/worker/reporter.js +86 -0
- package/lib/esm/server/worker/worker.js +238 -0
- package/lib/esm/shared/index.js +66 -0
- package/lib/esm/shared/serializeRegExp.js +23 -0
- package/lib/esm/types.js +43 -0
- package/lib/types/cli.d.ts +1 -1
- package/lib/types/client/addon/Manager.d.ts +37 -37
- package/lib/types/client/addon/components/Addon.d.ts +8 -8
- package/lib/types/client/addon/components/Icons.d.ts +7 -7
- package/lib/types/client/addon/components/Panel.d.ts +9 -9
- package/lib/types/client/addon/components/TestSelect.d.ts +8 -9
- package/lib/types/client/addon/components/Tools.d.ts +6 -6
- package/lib/types/client/addon/decorator.d.ts +1 -1
- package/lib/types/client/addon/index.d.ts +2 -0
- package/lib/types/client/addon/preset.d.ts +23 -24
- package/lib/types/client/addon/readyForCapture.d.ts +6 -6
- package/lib/types/client/addon/register.d.ts +3 -3
- package/lib/types/client/addon/utils.d.ts +2 -2
- package/lib/types/client/addon/withCreevey.d.ts +24 -24
- package/lib/types/client/shared/components/ImagesView/BlendView.d.ts +3 -3
- package/lib/types/client/shared/components/ImagesView/ImagesView.d.ts +24 -25
- package/lib/types/client/shared/components/ImagesView/SideBySideView.d.ts +3 -3
- package/lib/types/client/shared/components/ImagesView/SlideView.d.ts +3 -3
- package/lib/types/client/shared/components/ImagesView/SwapView.d.ts +3 -3
- package/lib/types/client/shared/components/ImagesView/index.d.ts +5 -5
- package/lib/types/client/shared/components/PageFooter/PageFooter.d.ts +8 -9
- package/lib/types/client/shared/components/PageFooter/Paging.d.ts +7 -8
- package/lib/types/client/shared/components/PageHeader/ImagePreview.d.ts +12 -12
- package/lib/types/client/shared/components/PageHeader/PageHeader.d.ts +16 -17
- package/lib/types/client/shared/components/ResultsPage.d.ts +18 -18
- package/lib/types/client/shared/creeveyClientApi.d.ts +9 -9
- package/lib/types/client/shared/helpers.d.ts +46 -46
- package/lib/types/client/shared/viewMode.d.ts +4 -4
- package/lib/types/client/web/CreeveyApp.d.ts +11 -12
- package/lib/types/client/web/CreeveyContext.d.ts +11 -11
- package/lib/types/client/web/CreeveyLoader.d.ts +2 -3
- package/lib/types/client/web/CreeveyView/SideBar/Checkbox.d.ts +19 -19
- package/lib/types/client/web/CreeveyView/SideBar/Search.d.ts +6 -6
- package/lib/types/client/web/CreeveyView/SideBar/SideBar.d.ts +14 -14
- package/lib/types/client/web/CreeveyView/SideBar/SideBarHeader.d.ts +12 -13
- package/lib/types/client/web/CreeveyView/SideBar/SuiteLink.d.ts +33 -33
- package/lib/types/client/web/CreeveyView/SideBar/TestLink.d.ts +7 -8
- package/lib/types/client/web/CreeveyView/SideBar/TestStatusIcon.d.ts +10 -10
- package/lib/types/client/web/CreeveyView/SideBar/TestsStatus.d.ts +9 -9
- package/lib/types/client/web/CreeveyView/SideBar/Toggle.d.ts +6 -6
- package/lib/types/client/web/CreeveyView/SideBar/index.d.ts +1 -1
- package/lib/types/client/web/KeyboardEventsContext.d.ts +13 -13
- package/lib/types/client/web/index.d.ts +4 -4
- package/lib/types/creevey.d.ts +1 -1
- package/lib/types/index.d.ts +1 -4
- package/lib/types/server/config.d.ts +4 -4
- package/lib/types/server/docker.d.ts +7 -7
- package/lib/types/server/extract.d.ts +2 -2
- package/lib/types/server/index.d.ts +2 -2
- package/lib/types/server/loaders/babel/creevey-plugin.d.ts +1 -1
- package/lib/types/server/loaders/babel/helpers.d.ts +19 -19
- package/lib/types/server/loaders/babel/register.d.ts +5 -5
- package/lib/types/server/loaders/hooks/mdx.d.ts +1 -1
- package/lib/types/server/loaders/hooks/svelte.d.ts +1 -1
- package/lib/types/server/loaders/webpack/compile.d.ts +2 -2
- package/lib/types/server/loaders/webpack/creevey-loader.d.ts +4 -2
- package/lib/types/server/loaders/webpack/dummy-hmr.d.ts +10 -10
- package/lib/types/server/loaders/webpack/mdx-loader.d.ts +6 -6
- package/lib/types/server/loaders/webpack/start.d.ts +1 -1
- package/lib/types/server/logger.d.ts +10 -6
- package/lib/types/server/master/api.d.ts +7 -7
- package/lib/types/server/master/index.d.ts +3 -3
- package/lib/types/server/master/master.d.ts +7 -7
- package/lib/types/server/master/pool.d.ts +31 -31
- package/lib/types/server/master/runner.d.ts +26 -26
- package/lib/types/server/master/server.d.ts +2 -2
- package/lib/types/server/messages.d.ts +27 -27
- package/lib/types/server/selenium/browser.d.ts +17 -17
- package/lib/types/server/selenium/index.d.ts +2 -2
- package/lib/types/server/selenium/selenoid.d.ts +3 -3
- package/lib/types/server/stories.d.ts +8 -8
- package/lib/types/server/storybook/entry.d.ts +18 -18
- package/lib/types/server/storybook/helpers.d.ts +24 -24
- package/lib/types/server/storybook/providers/browser.d.ts +4 -4
- package/lib/types/server/storybook/providers/hybrid.d.ts +4 -4
- package/lib/types/server/storybook/providers/nodejs.d.ts +9 -9
- package/lib/types/server/testsFiles/parser.d.ts +12 -12
- package/lib/types/server/testsFiles/register.d.ts +2 -2
- package/lib/types/server/update.d.ts +2 -2
- package/lib/types/server/utils.d.ts +20 -20
- package/lib/types/server/worker/chai-image.d.ts +6 -6
- package/lib/types/server/worker/helpers.d.ts +8 -8
- package/lib/types/server/worker/index.d.ts +1 -1
- package/lib/types/server/worker/reporter.d.ts +8 -8
- package/lib/types/server/worker/worker.d.ts +4 -4
- package/lib/types/{shared.d.ts → shared/index.d.ts} +7 -16
- package/lib/types/shared/serializeRegExp.d.ts +9 -0
- package/lib/types/types.d.ts +490 -489
- package/package.json +115 -102
- package/preset.js +9 -9
- package/types/babel__register.d.ts +1 -1
- package/types/chai.d.ts +12 -12
- package/types/event-source-polyfill.d.ts +6 -6
- package/types/mdx.d.ts +3 -2
- package/types/mocha.d.ts +20 -20
- package/types/png.d.ts +4 -4
- package/lib/cjs/client/web/1.js +0 -13
- package/lib/cjs/client/web/2.js +0 -1
- 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);
|
package/lib/esm/index.js
ADDED
@@ -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
|
+
}
|