creevey 0.8.0-beta.0 → 0.8.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 (199) hide show
  1. package/CHANGELOG.md +30 -7
  2. package/README.md +9 -1
  3. package/addon/README.md +3 -0
  4. package/addon/package.json +4 -0
  5. package/docs/config.md +29 -26
  6. package/jest.config.js +6 -0
  7. package/lib/cjs/client/addon/Manager.js +122 -271
  8. package/lib/cjs/client/addon/components/Addon.js +17 -38
  9. package/lib/cjs/client/addon/components/Icons.js +11 -7
  10. package/lib/cjs/client/addon/components/Panel.js +17 -13
  11. package/lib/cjs/client/addon/components/TestSelect.js +11 -9
  12. package/lib/cjs/client/addon/components/Tools.js +21 -40
  13. package/lib/cjs/client/addon/decorator.js +1 -1
  14. package/lib/cjs/client/addon/index.js +31 -0
  15. package/lib/cjs/client/addon/preset.ie11.js +74 -0
  16. package/lib/cjs/client/addon/preset.js +13 -31
  17. package/lib/cjs/client/addon/readyForCapture.js +12 -0
  18. package/lib/cjs/client/addon/register.js +46 -70
  19. package/lib/cjs/client/addon/utils.js +6 -2
  20. package/lib/cjs/client/addon/withCreevey.js +221 -155
  21. package/lib/cjs/client/shared/components/ImagesView/BlendView.js +26 -24
  22. package/lib/cjs/client/shared/components/ImagesView/ImagesView.js +22 -18
  23. package/lib/cjs/client/shared/components/ImagesView/SideBySideView.js +44 -66
  24. package/lib/cjs/client/shared/components/ImagesView/SlideView.js +38 -50
  25. package/lib/cjs/client/shared/components/ImagesView/SwapView.js +26 -45
  26. package/lib/cjs/client/shared/components/ImagesView/index.js +9 -9
  27. package/lib/cjs/client/shared/components/PageFooter/PageFooter.js +12 -8
  28. package/lib/cjs/client/shared/components/PageFooter/Paging.js +14 -18
  29. package/lib/cjs/client/shared/components/PageHeader/ImagePreview.js +22 -18
  30. package/lib/cjs/client/shared/components/PageHeader/PageHeader.js +42 -67
  31. package/lib/cjs/client/shared/components/ResultsPage.js +39 -69
  32. package/lib/cjs/client/shared/creeveyClientApi.js +55 -82
  33. package/lib/cjs/client/shared/helpers.js +140 -211
  34. package/lib/cjs/client/shared/viewMode.js +5 -5
  35. package/lib/cjs/client/web/142.js +2 -0
  36. package/lib/cjs/client/web/142.js.LICENSE.txt +12 -0
  37. package/lib/cjs/client/web/32.js +1 -0
  38. package/lib/cjs/client/web/551.js +1 -0
  39. package/lib/cjs/client/web/566.js +2 -0
  40. package/lib/cjs/client/web/566.js.LICENSE.txt +31 -0
  41. package/lib/cjs/client/web/691.js +2 -0
  42. package/lib/cjs/client/web/691.js.LICENSE.txt +8 -0
  43. package/lib/cjs/client/web/725.js +1 -0
  44. package/lib/cjs/client/web/main.js +2 -38
  45. package/lib/cjs/client/web/main.js.LICENSE.txt +49 -0
  46. package/lib/cjs/creevey.js +3 -5
  47. package/lib/cjs/index.js +10 -15
  48. package/lib/cjs/server/config.js +5 -4
  49. package/lib/cjs/server/docker.js +3 -7
  50. package/lib/cjs/server/extract.js +7 -4
  51. package/lib/cjs/server/index.js +3 -5
  52. package/lib/cjs/server/loaders/babel/creevey-plugin.js +1 -3
  53. package/lib/cjs/server/loaders/babel/helpers.js +13 -23
  54. package/lib/cjs/server/loaders/babel/register.js +2 -4
  55. package/lib/cjs/server/loaders/webpack/compile.js +34 -51
  56. package/lib/cjs/server/loaders/webpack/creevey-loader.js +20 -22
  57. package/lib/cjs/server/loaders/webpack/dummy-hmr.js +2 -7
  58. package/lib/cjs/server/loaders/webpack/mdx-loader.js +2 -2
  59. package/lib/cjs/server/loaders/webpack/start.js +1 -1
  60. package/lib/cjs/server/logger.js +2 -1
  61. package/lib/cjs/server/master/index.js +4 -4
  62. package/lib/cjs/server/master/master.js +1 -0
  63. package/lib/cjs/server/master/pool.js +38 -47
  64. package/lib/cjs/server/master/runner.js +53 -66
  65. package/lib/cjs/server/master/server.js +78 -4
  66. package/lib/cjs/server/messages.js +128 -18
  67. package/lib/cjs/server/selenium/browser.js +129 -55
  68. package/lib/cjs/server/selenium/selenoid.js +5 -7
  69. package/lib/cjs/server/stories.js +58 -72
  70. package/lib/cjs/server/storybook/entry.js +7 -22
  71. package/lib/cjs/server/storybook/helpers.js +20 -27
  72. package/lib/cjs/server/storybook/providers/browser.js +74 -0
  73. package/lib/cjs/server/storybook/{nodejs-provider.js → providers/nodejs.js} +37 -20
  74. package/lib/cjs/server/update.js +1 -5
  75. package/lib/cjs/server/utils.js +26 -35
  76. package/lib/cjs/server/worker/helpers.js +2 -6
  77. package/lib/cjs/server/worker/reporter.js +8 -20
  78. package/lib/cjs/server/worker/worker.js +21 -19
  79. package/lib/cjs/shared/index.js +101 -0
  80. package/lib/cjs/shared/serializeRegExp.js +42 -0
  81. package/lib/cjs/types.js +11 -6
  82. package/lib/esm/client/addon/Manager.js +122 -271
  83. package/lib/esm/client/addon/components/Addon.js +15 -34
  84. package/lib/esm/client/addon/components/Icons.js +10 -6
  85. package/lib/esm/client/addon/components/Panel.js +17 -13
  86. package/lib/esm/client/addon/components/TestSelect.js +11 -9
  87. package/lib/esm/client/addon/components/Tools.js +19 -36
  88. package/lib/esm/client/addon/decorator.js +1 -1
  89. package/lib/esm/client/addon/index.js +2 -0
  90. package/lib/esm/client/addon/preset.ie11.js +59 -0
  91. package/lib/esm/client/addon/preset.js +12 -26
  92. package/lib/esm/client/addon/readyForCapture.js +5 -0
  93. package/lib/esm/client/addon/register.js +42 -66
  94. package/lib/esm/client/addon/utils.js +3 -2
  95. package/lib/esm/client/addon/withCreevey.js +209 -156
  96. package/lib/esm/client/shared/components/ImagesView/BlendView.js +23 -20
  97. package/lib/esm/client/shared/components/ImagesView/ImagesView.js +21 -17
  98. package/lib/esm/client/shared/components/ImagesView/SideBySideView.js +42 -63
  99. package/lib/esm/client/shared/components/ImagesView/SlideView.js +36 -47
  100. package/lib/esm/client/shared/components/ImagesView/SwapView.js +24 -42
  101. package/lib/esm/client/shared/components/PageFooter/PageFooter.js +12 -8
  102. package/lib/esm/client/shared/components/PageFooter/Paging.js +14 -18
  103. package/lib/esm/client/shared/components/PageHeader/ImagePreview.js +22 -18
  104. package/lib/esm/client/shared/components/PageHeader/PageHeader.js +37 -60
  105. package/lib/esm/client/shared/components/ResultsPage.js +36 -64
  106. package/lib/esm/client/shared/creeveyClientApi.js +57 -84
  107. package/lib/esm/client/shared/helpers.js +124 -195
  108. package/lib/esm/client/shared/viewMode.js +4 -4
  109. package/lib/esm/creevey.js +3 -5
  110. package/lib/esm/index.js +2 -3
  111. package/lib/esm/server/config.js +4 -5
  112. package/lib/esm/server/docker.js +2 -2
  113. package/lib/esm/server/extract.js +6 -4
  114. package/lib/esm/server/index.js +3 -4
  115. package/lib/esm/server/loaders/babel/creevey-plugin.js +1 -3
  116. package/lib/esm/server/loaders/babel/helpers.js +12 -22
  117. package/lib/esm/server/loaders/babel/register.js +3 -5
  118. package/lib/esm/server/loaders/webpack/compile.js +35 -52
  119. package/lib/esm/server/loaders/webpack/creevey-loader.js +9 -10
  120. package/lib/esm/server/loaders/webpack/dummy-hmr.js +2 -6
  121. package/lib/esm/server/loaders/webpack/mdx-loader.js +2 -2
  122. package/lib/esm/server/loaders/webpack/start.js +1 -1
  123. package/lib/esm/server/master/index.js +4 -4
  124. package/lib/esm/server/master/master.js +1 -0
  125. package/lib/esm/server/master/pool.js +38 -49
  126. package/lib/esm/server/master/runner.js +53 -66
  127. package/lib/esm/server/master/server.js +76 -6
  128. package/lib/esm/server/messages.js +118 -14
  129. package/lib/esm/server/selenium/browser.js +126 -57
  130. package/lib/esm/server/selenium/selenoid.js +4 -6
  131. package/lib/esm/server/stories.js +58 -70
  132. package/lib/esm/server/storybook/entry.js +5 -22
  133. package/lib/esm/server/storybook/helpers.js +11 -20
  134. package/lib/esm/server/storybook/providers/browser.js +60 -0
  135. package/lib/esm/server/storybook/{nodejs-provider.js → providers/nodejs.js} +35 -19
  136. package/lib/esm/server/update.js +1 -5
  137. package/lib/esm/server/utils.js +18 -31
  138. package/lib/esm/server/worker/helpers.js +2 -6
  139. package/lib/esm/server/worker/reporter.js +8 -20
  140. package/lib/esm/server/worker/worker.js +22 -20
  141. package/lib/esm/shared/index.js +78 -0
  142. package/lib/esm/shared/serializeRegExp.js +24 -0
  143. package/lib/esm/types.js +3 -0
  144. package/lib/types/client/addon/Manager.d.ts +2 -2
  145. package/lib/types/client/addon/components/TestSelect.d.ts +0 -1
  146. package/lib/types/client/addon/index.d.ts +2 -0
  147. package/lib/types/client/addon/preset.d.ts +2 -1
  148. package/lib/types/client/addon/preset.ie11.d.ts +10 -0
  149. package/lib/types/client/addon/readyForCapture.d.ts +6 -0
  150. package/lib/types/client/addon/utils.d.ts +1 -0
  151. package/lib/types/client/addon/withCreevey.d.ts +13 -2
  152. package/lib/types/client/shared/components/ImagesView/BlendView.d.ts +1 -1
  153. package/lib/types/client/shared/components/ImagesView/ImagesView.d.ts +0 -1
  154. package/lib/types/client/shared/components/ImagesView/SideBySideView.d.ts +1 -1
  155. package/lib/types/client/shared/components/ImagesView/SlideView.d.ts +1 -1
  156. package/lib/types/client/shared/components/ImagesView/SwapView.d.ts +1 -1
  157. package/lib/types/client/shared/components/PageFooter/PageFooter.d.ts +0 -1
  158. package/lib/types/client/shared/components/PageFooter/Paging.d.ts +0 -1
  159. package/lib/types/client/shared/components/PageHeader/ImagePreview.d.ts +1 -1
  160. package/lib/types/client/shared/components/PageHeader/PageHeader.d.ts +0 -1
  161. package/lib/types/client/shared/components/ResultsPage.d.ts +1 -1
  162. package/lib/types/client/web/CreeveyApp.d.ts +0 -1
  163. package/lib/types/client/web/CreeveyLoader.d.ts +1 -2
  164. package/lib/types/client/web/CreeveyView/SideBar/Checkbox.d.ts +1 -1
  165. package/lib/types/client/web/CreeveyView/SideBar/SideBarHeader.d.ts +0 -1
  166. package/lib/types/client/web/CreeveyView/SideBar/SuiteLink.d.ts +6 -6
  167. package/lib/types/client/web/CreeveyView/SideBar/TestLink.d.ts +0 -1
  168. package/lib/types/client/web/CreeveyView/SideBar/TestStatusIcon.d.ts +1 -1
  169. package/lib/types/client/web/CreeveyView/SideBar/TestsStatus.d.ts +1 -1
  170. package/lib/types/index.d.ts +0 -1
  171. package/lib/types/server/loaders/babel/register.d.ts +1 -1
  172. package/lib/types/server/loaders/webpack/creevey-loader.d.ts +4 -2
  173. package/lib/types/server/logger.d.ts +6 -2
  174. package/lib/types/server/master/master.d.ts +1 -0
  175. package/lib/types/server/master/pool.d.ts +1 -0
  176. package/lib/types/server/master/server.d.ts +1 -1
  177. package/lib/types/server/messages.d.ts +17 -6
  178. package/lib/types/server/selenium/browser.d.ts +5 -2
  179. package/lib/types/server/stories.d.ts +2 -2
  180. package/lib/types/server/storybook/entry.d.ts +2 -3
  181. package/lib/types/server/storybook/helpers.d.ts +1 -1
  182. package/lib/types/server/storybook/providers/browser.d.ts +4 -0
  183. package/lib/types/server/storybook/providers/nodejs.d.ts +9 -0
  184. package/lib/types/server/utils.d.ts +5 -1
  185. package/lib/types/server/worker/helpers.d.ts +2 -1
  186. package/lib/types/shared/index.d.ts +7 -0
  187. package/lib/types/shared/serializeRegExp.d.ts +9 -0
  188. package/lib/types/types.d.ts +32 -5
  189. package/package.json +120 -103
  190. package/preset/ie11.js +5 -0
  191. package/{preset.js → preset/index.js} +2 -2
  192. package/types/mdx.d.ts +3 -2
  193. package/types/mocha.d.ts +1 -0
  194. package/lib/cjs/client/web/1.js +0 -13
  195. package/lib/cjs/client/web/2.js +0 -1
  196. package/lib/cjs/shared.js +0 -35
  197. package/lib/esm/shared.js +0 -22
  198. package/lib/types/server/storybook/nodejs-provider.d.ts +0 -5
  199. package/lib/types/shared.d.ts +0 -4
@@ -3,14 +3,17 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.shouldSkip = shouldSkip;
7
- exports.shutdownWorkers = shutdownWorkers;
8
- exports.shutdown = shutdown;
6
+ exports.extensions = exports.downloadBinary = exports.LOCALHOST_REGEXP = void 0;
9
7
  exports.getCreeveyCache = getCreeveyCache;
8
+ exports.isShuttingDown = exports.isInsideDocker = void 0;
9
+ exports.removeProps = removeProps;
10
10
  exports.runSequence = runSequence;
11
+ exports.shouldSkip = shouldSkip;
12
+ exports.shouldSkipByOption = shouldSkipByOption;
13
+ exports.shutdown = shutdown;
14
+ exports.shutdownWorkers = shutdownWorkers;
15
+ exports.skipOptionKeys = void 0;
11
16
  exports.testsToImages = testsToImages;
12
- exports.removeProps = removeProps;
13
- exports.downloadBinary = exports.isInsideDocker = exports.skipOptionKeys = exports.extensions = exports.LOCALHOST_REGEXP = exports.isShuttingDown = void 0;
14
17
 
15
18
  var _fs = require("fs");
16
19
 
@@ -46,38 +49,30 @@ function shouldSkip(browser, meta, skipOptions, test) {
46
49
  return skipOptions;
47
50
  }
48
51
 
49
- if (Array.isArray(skipOptions)) {
50
- for (const skip of skipOptions) {
51
- const reason = shouldSkip(browser, meta, skip, test);
52
- if (reason) return reason;
53
- }
54
-
55
- return false;
52
+ for (const skipKey in skipOptions) {
53
+ const reason = shouldSkipByOption(browser, meta, skipOptions[skipKey], skipKey, test);
54
+ if (reason) return reason;
56
55
  }
57
56
 
58
- let hasSkipOptionKeys = false;
57
+ return false;
58
+ }
59
59
 
60
- for (const skipKey in skipOptions) {
61
- if (skipOptionKeys.includes(skipKey)) {
62
- hasSkipOptionKeys = true;
63
- continue;
60
+ function shouldSkipByOption(browser, meta, skipOption, reason, test) {
61
+ if (Array.isArray(skipOption)) {
62
+ for (const skip of skipOption) {
63
+ const result = shouldSkipByOption(browser, meta, skip, reason, test);
64
+ if (result) return result;
64
65
  }
65
66
 
66
- const reason = shouldSkip(browser, meta, {
67
- reason: skipKey,
68
- ...skipOptions[skipKey]
69
- }, test);
70
- if (reason) return reason;
67
+ return false;
71
68
  }
72
69
 
73
- if (!hasSkipOptionKeys) return false;
74
70
  const {
75
71
  in: browsers,
76
72
  kinds,
77
73
  stories,
78
- tests,
79
- reason = true
80
- } = skipOptions;
74
+ tests
75
+ } = skipOption;
81
76
  const {
82
77
  kind,
83
78
  story
@@ -91,7 +86,7 @@ function shouldSkip(browser, meta, skipOptions, test) {
91
86
 
92
87
  async function shutdownWorkers() {
93
88
  isShuttingDown.current = true;
94
- await Promise.all(Object.values(_cluster.default.workers).filter(_types.isDefined).filter(worker => worker.isConnected()).map(worker => new Promise(resolve => {
89
+ await Promise.all(Object.values(_cluster.default.workers ?? {}).filter(_types.isDefined).filter(worker => worker.isConnected()).map(worker => new Promise(resolve => {
95
90
  const timeout = setTimeout(() => worker.kill(), 10000);
96
91
  worker.on('exit', () => {
97
92
  clearTimeout(timeout);
@@ -127,9 +122,9 @@ function testsToImages(tests) {
127
122
  storyPath,
128
123
  results
129
124
  }) => {
130
- var _results$slice$0$imag, _results$slice$;
125
+ var _results$slice$;
131
126
 
132
- return Object.keys((_results$slice$0$imag = results === null || results === void 0 ? void 0 : (_results$slice$ = results.slice(-1)[0]) === null || _results$slice$ === void 0 ? void 0 : _results$slice$.images) !== null && _results$slice$0$imag !== void 0 ? _results$slice$0$imag : {}).map(image => `${[...storyPath, testName, browser, browser == image ? undefined : image].filter(_types.isDefined).join('/')}.png`);
127
+ return Object.keys((results === null || results === void 0 ? void 0 : (_results$slice$ = results.slice(-1)[0]) === null || _results$slice$ === void 0 ? void 0 : _results$slice$.images) ?? {}).map(image => `${[...storyPath, testName, browser, browser == image ? undefined : image].filter(_types.isDefined).join('/')}.png`);
133
128
  })));
134
129
  } // https://tuhrig.de/how-to-know-you-are-inside-a-docker-container/
135
130
 
@@ -138,19 +133,15 @@ const isInsideDocker = (0, _fs.existsSync)('/proc/1/cgroup') && /docker/.test((0
138
133
  exports.isInsideDocker = isInsideDocker;
139
134
 
140
135
  const downloadBinary = (downloadUrl, destination) => new Promise((resolve, reject) => (0, _https.get)(downloadUrl, response => {
141
- var _response$statusCode2;
142
-
143
136
  if (response.statusCode == 302) {
144
- var _response$statusCode;
145
-
146
137
  const {
147
138
  location
148
139
  } = response.headers;
149
- if (!location) return reject(new Error(`Couldn't download selenoid. Status code: ${(_response$statusCode = response.statusCode) !== null && _response$statusCode !== void 0 ? _response$statusCode : 'UNKNOWN'}`));
140
+ if (!location) return reject(new Error(`Couldn't download selenoid. Status code: ${response.statusCode ?? 'UNKNOWN'}`));
150
141
  return resolve(downloadBinary(location, destination));
151
142
  }
152
143
 
153
- if (response.statusCode != 200) return reject(new Error(`Couldn't download selenoid. Status code: ${(_response$statusCode2 = response.statusCode) !== null && _response$statusCode2 !== void 0 ? _response$statusCode2 : 'UNKNOWN'}`));
144
+ if (response.statusCode != 200) return reject(new Error(`Couldn't download selenoid. Status code: ${response.statusCode ?? 'UNKNOWN'}`));
154
145
  const fileStream = (0, _fs.createWriteStream)(destination);
155
146
  response.pipe(fileStream);
156
147
  fileStream.on('finish', () => {
@@ -56,14 +56,10 @@ function removeTestOrSuite(testOrSuite) {
56
56
 
57
57
  async function addTestsFromStories(rootSuite, config, {
58
58
  browser,
59
- watch,
60
- debug
59
+ ...options
61
60
  }) {
62
61
  const mochaTestsById = new Map();
63
- const tests = await (0, _stories.loadTestsFromStories)([browser], listener => config.storiesProvider(config, {
64
- watch,
65
- debug
66
- }, listener), testsDiff => Object.entries(testsDiff).forEach(([id, newTest]) => {
62
+ const tests = await (0, _stories.loadTestsFromStories)([browser], listener => config.storiesProvider(config, options, listener), testsDiff => Object.entries(testsDiff).forEach(([id, newTest]) => {
67
63
  const oldTest = mochaTestsById.get(id);
68
64
  mochaTestsById.delete(id);
69
65
  if (oldTest) removeTestOrSuite(oldTest);
@@ -17,8 +17,6 @@ var _logger = require("../logger");
17
17
 
18
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
19
 
20
- 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; }
21
-
22
20
  const testLevels = {
23
21
  INFO: _chalk.default.green('PASS'),
24
22
  WARN: _chalk.default.yellow('START'),
@@ -43,11 +41,7 @@ class CreeveyReporter extends _mocha.reporters.Base {
43
41
 
44
42
  runner.on('test', test => testLogger.warn(_chalk.default.cyan(test.titlePath().join('/'))));
45
43
  runner.on('pass', test => testLogger.info(_chalk.default.cyan(test.titlePath().join('/'))));
46
- runner.on('fail', (test, error) => testLogger.error(_chalk.default.cyan(test.titlePath().join('/')), '\n ', getErrors(error, (error, imageName) => `${_chalk.default.bold(imageName !== null && imageName !== void 0 ? imageName : topLevelSuite)}:${error}`, error => {
47
- var _error$stack;
48
-
49
- return `${(_error$stack = error.stack) !== null && _error$stack !== void 0 ? _error$stack : error.message}`;
50
- }).join('\n ')));
44
+ runner.on('fail', (test, error) => testLogger.error(_chalk.default.cyan(test.titlePath().join('/')), '\n ', getErrors(error, (error, imageName) => `${_chalk.default.bold(imageName ?? topLevelSuite)}:${error}`, error => `${error.stack ?? error.message}`).join('\n ')));
51
45
  }
52
46
 
53
47
  }
@@ -57,20 +51,11 @@ exports.CreeveyReporter = CreeveyReporter;
57
51
  class TeamcityReporter extends _mocha.reporters.Base {
58
52
  constructor(runner, options) {
59
53
  super(runner);
60
-
61
- _defineProperty(this, "escape", str => {
62
- if (!str) return '';
63
- return str.toString() // eslint-disable-next-line no-control-regex
64
- .replace(/\x1B.*?m/g, '').replace(/\|/g, '||').replace(/\n/g, '|n').replace(/\r/g, '|r').replace(/\[/g, '|[').replace(/\]/g, '|]').replace(/\u0085/g, '|x').replace(/\u2028/g, '|l').replace(/\u2029/g, '|p').replace(/'/g, "|'");
65
- });
66
-
67
54
  const topLevelSuite = this.escape(options.reporterOptions.topLevelSuite);
68
55
  const reporterOptions = options.reporterOptions;
69
56
  runner.on('suite', suite => suite.root ? console.log(`##teamcity[testSuiteStarted name='${topLevelSuite}' flowId='${process.pid}']`) : console.log(`##teamcity[testSuiteStarted name='${this.escape(suite.title)}' flowId='${process.pid}']`));
70
57
  runner.on('test', test => console.log(`##teamcity[testStarted name='${this.escape(test.title)}' flowId='${process.pid}']`));
71
58
  runner.on('fail', (test, error) => {
72
- var _error$stack2;
73
-
74
59
  Object.entries(reporterOptions.images).forEach(([name, image]) => {
75
60
  if (!image) return;
76
61
  const filePath = test.titlePath().concat(name == topLevelSuite ? [] : [topLevelSuite]).map(this.escape).join('/'); // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -86,7 +71,7 @@ class TeamcityReporter extends _mocha.reporters.Base {
86
71
  }); // Output failed test as passed due TC don't support retry mechanic
87
72
  // https://teamcity-support.jetbrains.com/hc/en-us/community/posts/207216829-Count-test-as-successful-if-at-least-one-try-is-successful?page=1#community_comment_207394125
88
73
 
89
- reporterOptions.willRetry ? console.log(`##teamcity[testFinished name='${this.escape(test.title)}' flowId='${process.pid}']`) : console.log(`##teamcity[testFailed name='${this.escape(test.title)}' message='${this.escape(error.message)}' details='${this.escape((_error$stack2 = error.stack) !== null && _error$stack2 !== void 0 ? _error$stack2 : '')}' flowId='${process.pid}']`);
74
+ reporterOptions.willRetry ? console.log(`##teamcity[testFinished name='${this.escape(test.title)}' flowId='${process.pid}']`) : console.log(`##teamcity[testFailed name='${this.escape(test.title)}' message='${this.escape(error.message)}' details='${this.escape(error.stack ?? '')}' flowId='${process.pid}']`);
90
75
  });
91
76
  runner.on('pending', test => console.log(`##teamcity[testIgnored name='${this.escape(test.title)}' message='${this.escape(typeof test.skipReason == 'boolean' ? test.title : test.skipReason)}' flowId='${process.pid}']`));
92
77
  runner.on('test end', test => console.log(`##teamcity[testFinished name='${this.escape(test.title)}' flowId='${process.pid}']`));
@@ -94,6 +79,11 @@ class TeamcityReporter extends _mocha.reporters.Base {
94
79
  runner.on('end', () => console.log(`##teamcity[testSuiteFinished name='${topLevelSuite}' flowId='${process.pid}']`));
95
80
  }
96
81
 
82
+ escape = str => {
83
+ if (!str) return '';
84
+ return str.toString() // eslint-disable-next-line no-control-regex
85
+ .replace(/\x1B.*?m/g, '').replace(/\|/g, '||').replace(/\n/g, '|n').replace(/\r/g, '|r').replace(/\[/g, '|[').replace(/\]/g, '|]').replace(/\u0085/g, '|x').replace(/\u2028/g, '|l').replace(/\u2029/g, '|p').replace(/'/g, "|'");
86
+ };
97
87
  }
98
88
 
99
89
  exports.TeamcityReporter = TeamcityReporter;
@@ -110,9 +100,7 @@ function getErrors(error, imageErrorToString, errorToString) {
110
100
  } else {
111
101
  const imageErrors = error.images;
112
102
  Object.keys(imageErrors).forEach(imageName => {
113
- var _imageErrors$imageNam;
114
-
115
- errors.push(imageErrorToString((_imageErrors$imageNam = imageErrors[imageName]) !== null && _imageErrors$imageNam !== void 0 ? _imageErrors$imageNam : '', imageName));
103
+ errors.push(imageErrorToString(imageErrors[imageName] ?? '', imageName));
116
104
  });
117
105
  }
118
106
 
@@ -57,9 +57,7 @@ async function getLastImageNumber(imageDir, imageName) {
57
57
  const actualImagesRegexp = new RegExp(`${imageName}-actual-(\\d+)\\.png`);
58
58
 
59
59
  try {
60
- var _await$readdirAsync$m;
61
-
62
- return (_await$readdirAsync$m = (await readdirAsync(imageDir)).map(filename => filename.replace(actualImagesRegexp, '$1')).map(Number).filter(x => !isNaN(x)).sort((a, b) => b - a)[0]) !== null && _await$readdirAsync$m !== void 0 ? _await$readdirAsync$m : 0;
60
+ return (await readdirAsync(imageDir)).map(filename => filename.replace(actualImagesRegexp, '$1')).map(Number).filter(x => !isNaN(x)).sort((a, b) => b - a)[0] ?? 0;
63
61
  } catch (_error) {
64
62
  return 0;
65
63
  }
@@ -72,12 +70,11 @@ async function worker(config, options) {
72
70
  let retries = 0;
73
71
  let images = {};
74
72
  let error = undefined;
73
+ const screenshots = [];
75
74
  const testScope = [];
76
75
 
77
76
  function runHandler(failures) {
78
77
  if (failures > 0 && (error || Object.values(images).some(image => (image === null || image === void 0 ? void 0 : image.error) != null))) {
79
- var _error2;
80
-
81
78
  const isTimeout = hasTimeout(error) || Object.values(images).some(image => hasTimeout(image === null || image === void 0 ? void 0 : image.error));
82
79
  const payload = {
83
80
  status: 'failed',
@@ -87,7 +84,7 @@ async function worker(config, options) {
87
84
  isTimeout ? (0, _messages.emitWorkerMessage)({
88
85
  type: 'error',
89
86
  payload: {
90
- error: (_error2 = error) !== null && _error2 !== void 0 ? _error2 : 'Unknown error'
87
+ error: error ?? 'Unknown error'
91
88
  }
92
89
  }) : (0, _messages.emitTestMessage)({
93
90
  type: 'end',
@@ -118,20 +115,18 @@ async function worker(config, options) {
118
115
  }
119
116
 
120
117
  async function getExpected(assertImageName) {
121
- var _images$imageName;
122
-
123
118
  // context => [kind, story, test, browser]
124
119
  // rootSuite -> kindSuite -> storyTest -> [browsers.png]
125
120
  // rootSuite -> kindSuite -> storySuite -> test -> [browsers.png]
126
121
  const testPath = [...testScope];
127
- const imageName = assertImageName !== null && assertImageName !== void 0 ? assertImageName : testPath.pop();
122
+ const imageName = assertImageName ?? testPath.pop();
128
123
  const imagesMeta = [];
129
124
 
130
125
  const reportImageDir = _path.default.join(config.reportDir, ...testPath);
131
126
 
132
127
  const imageNumber = (await getLastImageNumber(reportImageDir, imageName)) + 1;
133
128
  const actualImageName = `${imageName}-actual-${imageNumber}.png`;
134
- const image = images[imageName] = (_images$imageName = images[imageName]) !== null && _images$imageName !== void 0 ? _images$imageName : {
129
+ const image = images[imageName] = images[imageName] ?? {
135
130
  actual: actualImageName
136
131
  };
137
132
 
@@ -194,20 +189,28 @@ async function worker(config, options) {
194
189
 
195
190
  }
196
191
  };
197
- const mocha = new _mocha.default(mochaOptions); // @ts-expect-error: @types/mocha has out-dated types
198
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call
199
-
192
+ const mocha = new _mocha.default(mochaOptions);
200
193
  mocha.cleanReferencesAfterRun(false);
201
194
 
202
195
  _chai.default.use((0, _chaiImage.default)(getExpected, config.diffOptions));
203
196
 
197
+ if ((await (0, _selenium.getBrowser)(config, options.browser)) == null) return;
204
198
  await (0, _helpers.addTestsFromStories)(mocha.suite, config, {
205
199
  browser: options.browser,
206
200
  watch: options.ui,
207
- debug: options.debug
201
+ debug: options.debug,
202
+ port: options.port
208
203
  });
209
- const browserConfig = config.browsers[options.browser];
210
- const browser = await (0, _selenium.getBrowser)(config, browserConfig);
204
+
205
+ try {
206
+ var _await$getBrowser;
207
+
208
+ await ((_await$getBrowser = await (0, _selenium.getBrowser)(config, options.browser)) === null || _await$getBrowser === void 0 ? void 0 : _await$getBrowser.getCurrentUrl());
209
+ } catch (_) {
210
+ await (0, _selenium.closeBrowser)();
211
+ }
212
+
213
+ const browser = await (0, _selenium.getBrowser)(config, options.browser);
211
214
  const sessionId = (_await$browser$getSes = await (browser === null || browser === void 0 ? void 0 : browser.getSession())) === null || _await$browser$getSes === void 0 ? void 0 : _await$browser$getSes.getId();
212
215
  if (browser == null) return;
213
216
  const interval = setInterval(() => void browser.getCurrentUrl().then(url => {
@@ -222,6 +225,7 @@ async function worker(config, options) {
222
225
  this.expect = _chai.default.expect;
223
226
  this.browserName = options.browser;
224
227
  this.testScope = testScope;
228
+ this.screenshots = screenshots;
225
229
  });
226
230
  mocha.suite.beforeEach(_selenium.switchStory);
227
231
  (0, _messages.subscribeOn)('test', message => {
@@ -238,9 +242,7 @@ async function worker(config, options) {
238
242
  if (!(reason instanceof Error)) {
239
243
  error = reason;
240
244
  } else if (!(0, _types.isImageError)(reason)) {
241
- var _reason$stack;
242
-
243
- error = (_reason$stack = reason.stack) !== null && _reason$stack !== void 0 ? _reason$stack : reason.message;
245
+ error = reason.stack ?? reason.message;
244
246
  } else if (typeof reason.images == 'string') {
245
247
  const image = images[testScope.slice(-1)[0]];
246
248
  if (image) image.error = reason.images;
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.serializeRawStories = exports.deserializeStory = exports.deserializeRawStories = exports.denormalizeStoryParameters = exports.combineParameters = void 0;
7
+
8
+ var _lodash = require("lodash");
9
+
10
+ var _serializeRegExp = require("./serializeRegExp");
11
+
12
+ // NOTE: Copy-paste from storybook/api
13
+ const combineParameters = function () {
14
+ for (var _len = arguments.length, parameterSets = new Array(_len), _key = 0; _key < _len; _key++) {
15
+ parameterSets[_key] = arguments[_key];
16
+ }
17
+
18
+ return (// eslint-disable-next-line @typescript-eslint/no-unsafe-return
19
+ (0, _lodash.mergeWith)({}, ...parameterSets, (_, srcValue) => {
20
+ // Treat arrays as scalars:
21
+ if (Array.isArray(srcValue)) return srcValue;
22
+ return undefined;
23
+ })
24
+ );
25
+ }; // NOTE: Copy-paste from storybook/api
26
+
27
+
28
+ exports.combineParameters = combineParameters;
29
+
30
+ const denormalizeStoryParameters = _ref => {
31
+ let {
32
+ globalParameters,
33
+ kindParameters,
34
+ stories
35
+ } = _ref;
36
+ return (0, _lodash.mapValues)(stories, storyData => {
37
+ var _kindParameters$story;
38
+
39
+ return { ...storyData,
40
+ parameters: combineParameters(globalParameters, (_kindParameters$story = kindParameters[storyData.kind]) !== null && _kindParameters$story !== void 0 ? _kindParameters$story : {}, storyData.parameters)
41
+ };
42
+ });
43
+ };
44
+
45
+ exports.denormalizeStoryParameters = denormalizeStoryParameters;
46
+
47
+ const serializeRawStories = stories => {
48
+ return (0, _lodash.mapValues)(stories, storyData => {
49
+ const creevey = storyData.parameters.creevey;
50
+
51
+ if (creevey !== null && creevey !== void 0 && creevey.skip) {
52
+ return { ...storyData,
53
+ parameters: { ...storyData.parameters,
54
+ creevey: { ...creevey,
55
+ skip: (0, _lodash.cloneDeepWith)(creevey.skip, value => {
56
+ if ((0, _serializeRegExp.isRegExp)(value)) {
57
+ return (0, _serializeRegExp.serializeRegExp)(value);
58
+ }
59
+
60
+ return undefined;
61
+ })
62
+ }
63
+ }
64
+ };
65
+ }
66
+
67
+ return storyData;
68
+ });
69
+ };
70
+
71
+ exports.serializeRawStories = serializeRawStories;
72
+
73
+ const deserializeRawStories = stories => {
74
+ return (0, _lodash.mapValues)(stories, deserializeStory);
75
+ };
76
+
77
+ exports.deserializeRawStories = deserializeRawStories;
78
+
79
+ const deserializeStory = story => {
80
+ const creevey = story.parameters.creevey;
81
+
82
+ if (creevey !== null && creevey !== void 0 && creevey.skip) {
83
+ return { ...story,
84
+ parameters: { ...story.parameters,
85
+ creevey: { ...creevey,
86
+ skip: (0, _lodash.cloneDeepWith)(creevey.skip, value => {
87
+ if ((0, _serializeRegExp.isSerializedRegExp)(value)) {
88
+ return (0, _serializeRegExp.deserializeRegExp)(value);
89
+ }
90
+
91
+ return undefined;
92
+ })
93
+ }
94
+ }
95
+ };
96
+ }
97
+
98
+ return story;
99
+ };
100
+
101
+ exports.deserializeStory = deserializeStory;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.serializeRegExp = exports.isSerializedRegExp = exports.isRegExp = exports.deserializeRegExp = void 0;
7
+
8
+ const isRegExp = exp => {
9
+ return exp instanceof RegExp;
10
+ };
11
+
12
+ exports.isRegExp = isRegExp;
13
+
14
+ const isSerializedRegExp = exp => {
15
+ return typeof exp === 'object' && exp !== null && Reflect.get(exp, '__regexp') === true;
16
+ };
17
+
18
+ exports.isSerializedRegExp = isSerializedRegExp;
19
+
20
+ const serializeRegExp = exp => {
21
+ const {
22
+ source,
23
+ flags
24
+ } = exp;
25
+ return {
26
+ __regexp: true,
27
+ source,
28
+ flags
29
+ };
30
+ };
31
+
32
+ exports.serializeRegExp = serializeRegExp;
33
+
34
+ const deserializeRegExp = _ref => {
35
+ let {
36
+ source,
37
+ flags
38
+ } = _ref;
39
+ return new RegExp(source, flags);
40
+ };
41
+
42
+ exports.deserializeRegExp = deserializeRegExp;
package/lib/cjs/types.js CHANGED
@@ -3,18 +3,19 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.noop = noop;
7
6
  exports.isDefined = isDefined;
8
- exports.isTest = isTest;
9
- exports.isObject = isObject;
10
- exports.isString = isString;
7
+ exports.isDockerMessage = isDockerMessage;
11
8
  exports.isFunction = isFunction;
12
9
  exports.isImageError = isImageError;
10
+ exports.isObject = isObject;
13
11
  exports.isProcessMessage = isProcessMessage;
14
- exports.isWorkerMessage = isWorkerMessage;
12
+ exports.isStoriesMessage = isStoriesMessage;
13
+ exports.isString = isString;
14
+ exports.isTest = isTest;
15
15
  exports.isTestMessage = isTestMessage;
16
16
  exports.isWebpackMessage = isWebpackMessage;
17
- exports.isDockerMessage = isDockerMessage;
17
+ exports.isWorkerMessage = isWorkerMessage;
18
+ exports.noop = noop;
18
19
 
19
20
  /* eslint-disable @typescript-eslint/no-explicit-any */
20
21
 
@@ -56,6 +57,10 @@ function isWorkerMessage(message) {
56
57
  return isProcessMessage(message) && message.scope == 'worker';
57
58
  }
58
59
 
60
+ function isStoriesMessage(message) {
61
+ return isProcessMessage(message) && message.scope == 'stories';
62
+ }
63
+
59
64
  function isTestMessage(message) {
60
65
  return isProcessMessage(message) && message.scope == 'test';
61
66
  }