creevey 0.9.2 → 0.10.0-beta.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 (259) hide show
  1. package/chromatic.config.json +5 -0
  2. package/dist/client/addon/components/Addon.d.ts +1 -0
  3. package/dist/client/addon/components/Addon.js.map +1 -1
  4. package/dist/client/addon/components/Icons.d.ts +1 -0
  5. package/dist/client/addon/components/Icons.js.map +1 -1
  6. package/dist/client/addon/components/Panel.d.ts +1 -0
  7. package/dist/client/addon/components/Panel.js.map +1 -1
  8. package/dist/client/addon/components/TestSelect.d.ts +1 -0
  9. package/dist/client/addon/components/TestSelect.js +4 -3
  10. package/dist/client/addon/components/TestSelect.js.map +1 -1
  11. package/dist/client/addon/components/Tools.d.ts +1 -0
  12. package/dist/client/addon/components/Tools.js +7 -8
  13. package/dist/client/addon/components/Tools.js.map +1 -1
  14. package/dist/client/addon/controller.d.ts +1 -1
  15. package/dist/client/addon/controller.js.map +1 -1
  16. package/dist/client/addon/decorator.d.ts +1 -1
  17. package/dist/client/addon/manager.js +3 -2
  18. package/dist/client/addon/manager.js.map +1 -1
  19. package/dist/client/addon/preview.d.ts +1 -1
  20. package/dist/client/addon/withCreevey.d.ts +6 -8
  21. package/dist/client/addon/withCreevey.js +21 -19
  22. package/dist/client/addon/withCreevey.js.map +1 -1
  23. package/dist/client/shared/components/ImagesView/BlendView.d.ts +1 -1
  24. package/dist/client/shared/components/ImagesView/BlendView.js.map +1 -1
  25. package/dist/client/shared/components/ImagesView/ImagesView.d.ts +1 -0
  26. package/dist/client/shared/components/ImagesView/ImagesView.js.map +1 -1
  27. package/dist/client/shared/components/ImagesView/SideBySideView.d.ts +1 -1
  28. package/dist/client/shared/components/ImagesView/SideBySideView.js.map +1 -1
  29. package/dist/client/shared/components/ImagesView/SlideView.d.ts +1 -1
  30. package/dist/client/shared/components/ImagesView/SlideView.js.map +1 -1
  31. package/dist/client/shared/components/ImagesView/SwapView.d.ts +1 -1
  32. package/dist/client/shared/components/ImagesView/SwapView.js.map +1 -1
  33. package/dist/client/shared/components/PageFooter/PageFooter.d.ts +1 -0
  34. package/dist/client/shared/components/PageFooter/PageFooter.js +1 -1
  35. package/dist/client/shared/components/PageFooter/PageFooter.js.map +1 -1
  36. package/dist/client/shared/components/PageFooter/Paging.d.ts +2 -2
  37. package/dist/client/shared/components/PageFooter/Paging.js +8 -6
  38. package/dist/client/shared/components/PageFooter/Paging.js.map +1 -1
  39. package/dist/client/shared/components/PageHeader/ImagePreview.js.map +1 -1
  40. package/dist/client/shared/components/PageHeader/PageHeader.d.ts +1 -0
  41. package/dist/client/shared/components/PageHeader/PageHeader.js +2 -1
  42. package/dist/client/shared/components/PageHeader/PageHeader.js.map +1 -1
  43. package/dist/client/shared/components/ResultsPage.d.ts +2 -2
  44. package/dist/client/shared/components/ResultsPage.js.map +1 -1
  45. package/dist/client/web/CreeveyApp.d.ts +1 -0
  46. package/dist/client/web/CreeveyApp.js.map +1 -1
  47. package/dist/client/web/CreeveyLoader.d.ts +1 -0
  48. package/dist/client/web/CreeveyLoader.js.map +1 -1
  49. package/dist/client/web/CreeveyView/SideBar/Checkbox.d.ts +1 -1
  50. package/dist/client/web/CreeveyView/SideBar/Checkbox.js +4 -4
  51. package/dist/client/web/CreeveyView/SideBar/Checkbox.js.map +1 -1
  52. package/dist/client/web/CreeveyView/SideBar/Search.d.ts +1 -0
  53. package/dist/client/web/CreeveyView/SideBar/Search.js +4 -4
  54. package/dist/client/web/CreeveyView/SideBar/Search.js.map +1 -1
  55. package/dist/client/web/CreeveyView/SideBar/SideBar.d.ts +1 -1
  56. package/dist/client/web/CreeveyView/SideBar/SideBar.js +1 -7
  57. package/dist/client/web/CreeveyView/SideBar/SideBar.js.map +1 -1
  58. package/dist/client/web/CreeveyView/SideBar/SideBarFooter.d.ts +1 -0
  59. package/dist/client/web/CreeveyView/SideBar/SideBarFooter.js +5 -4
  60. package/dist/client/web/CreeveyView/SideBar/SideBarFooter.js.map +1 -1
  61. package/dist/client/web/CreeveyView/SideBar/SideBarHeader.d.ts +1 -0
  62. package/dist/client/web/CreeveyView/SideBar/SideBarHeader.js +4 -3
  63. package/dist/client/web/CreeveyView/SideBar/SideBarHeader.js.map +1 -1
  64. package/dist/client/web/CreeveyView/SideBar/SuiteLink.d.ts +3 -7
  65. package/dist/client/web/CreeveyView/SideBar/SuiteLink.js +6 -5
  66. package/dist/client/web/CreeveyView/SideBar/SuiteLink.js.map +1 -1
  67. package/dist/client/web/CreeveyView/SideBar/TestLink.d.ts +1 -0
  68. package/dist/client/web/CreeveyView/SideBar/TestLink.js +5 -1
  69. package/dist/client/web/CreeveyView/SideBar/TestLink.js.map +1 -1
  70. package/dist/client/web/CreeveyView/SideBar/TestStatusIcon.js +15 -8
  71. package/dist/client/web/CreeveyView/SideBar/TestStatusIcon.js.map +1 -1
  72. package/dist/client/web/CreeveyView/SideBar/TestsStatus.js +5 -4
  73. package/dist/client/web/CreeveyView/SideBar/TestsStatus.js.map +1 -1
  74. package/dist/client/web/CreeveyView/SideBar/Toggle.d.ts +1 -0
  75. package/dist/client/web/CreeveyView/SideBar/Toggle.js.map +1 -1
  76. package/dist/client/web/KeyboardEventsContext.d.ts +3 -4
  77. package/dist/client/web/KeyboardEventsContext.js.map +1 -1
  78. package/dist/client/web/assets/index-DkmZfG9C.js +591 -0
  79. package/dist/client/web/index.html +1 -1
  80. package/dist/client/web/index.js +5 -6
  81. package/dist/client/web/index.js.map +1 -1
  82. package/dist/creevey.js +21 -9
  83. package/dist/creevey.js.map +1 -1
  84. package/dist/index.js +7 -3
  85. package/dist/index.js.map +1 -1
  86. package/dist/server/config.d.ts +1 -1
  87. package/dist/server/config.js +9 -5
  88. package/dist/server/config.js.map +1 -1
  89. package/dist/server/docker.d.ts +2 -2
  90. package/dist/server/docker.js +46 -40
  91. package/dist/server/docker.js.map +1 -1
  92. package/dist/server/index.js +54 -15
  93. package/dist/server/index.js.map +1 -1
  94. package/dist/server/master/master.d.ts +1 -5
  95. package/dist/server/master/master.js +3 -3
  96. package/dist/server/master/master.js.map +1 -1
  97. package/dist/server/master/pool.d.ts +2 -1
  98. package/dist/server/master/pool.js +9 -5
  99. package/dist/server/master/pool.js.map +1 -1
  100. package/dist/server/master/runner.d.ts +1 -1
  101. package/dist/server/master/runner.js +2 -2
  102. package/dist/server/master/runner.js.map +1 -1
  103. package/dist/server/master/server.js +1 -0
  104. package/dist/server/master/server.js.map +1 -1
  105. package/dist/server/master/start.d.ts +3 -0
  106. package/dist/server/master/{index.js → start.js} +6 -9
  107. package/dist/server/master/start.js.map +1 -0
  108. package/dist/server/messages.d.ts +4 -10
  109. package/dist/server/messages.js +4 -58
  110. package/dist/server/messages.js.map +1 -1
  111. package/dist/server/playwright/docker-file.d.ts +1 -0
  112. package/dist/server/playwright/docker-file.js +26 -0
  113. package/dist/server/playwright/docker-file.js.map +1 -0
  114. package/dist/server/playwright/docker.d.ts +1 -0
  115. package/dist/server/playwright/docker.js +31 -0
  116. package/dist/server/playwright/docker.js.map +1 -0
  117. package/dist/server/playwright/internal.d.ts +25 -0
  118. package/dist/server/playwright/internal.js +319 -0
  119. package/dist/server/playwright/internal.js.map +1 -0
  120. package/dist/server/playwright/webdriver.d.ts +16 -0
  121. package/dist/server/playwright/webdriver.js +105 -0
  122. package/dist/server/playwright/webdriver.js.map +1 -0
  123. package/dist/server/providers/browser.d.ts +2 -0
  124. package/dist/server/{storybook/providers → providers}/browser.js +6 -7
  125. package/dist/server/providers/browser.js.map +1 -0
  126. package/dist/server/providers/hybrid.d.ts +2 -0
  127. package/dist/server/{storybook/providers → providers}/hybrid.js +8 -8
  128. package/dist/server/providers/hybrid.js.map +1 -0
  129. package/dist/server/reporter.d.ts +26 -0
  130. package/dist/server/{worker/reporter.js → reporter.js} +34 -56
  131. package/dist/server/reporter.js.map +1 -0
  132. package/dist/server/selenium/internal.d.ts +31 -0
  133. package/dist/server/selenium/internal.js +606 -0
  134. package/dist/server/selenium/internal.js.map +1 -0
  135. package/dist/server/selenium/selenoid.js +6 -13
  136. package/dist/server/selenium/selenoid.js.map +1 -1
  137. package/dist/server/selenium/webdriver.d.ts +24 -0
  138. package/dist/server/selenium/webdriver.js +106 -0
  139. package/dist/server/selenium/webdriver.js.map +1 -0
  140. package/dist/server/stories.js +16 -9
  141. package/dist/server/stories.js.map +1 -1
  142. package/dist/server/telemetry.d.ts +1 -1
  143. package/dist/server/telemetry.js +4 -4
  144. package/dist/server/telemetry.js.map +1 -1
  145. package/dist/server/utils.d.ts +3 -4
  146. package/dist/server/utils.js +10 -9
  147. package/dist/server/utils.js.map +1 -1
  148. package/dist/server/webdriver.d.ts +19 -0
  149. package/dist/server/webdriver.js +79 -0
  150. package/dist/server/webdriver.js.map +1 -0
  151. package/dist/server/worker/chai-image.d.ts +2 -5
  152. package/dist/server/worker/chai-image.js +14 -102
  153. package/dist/server/worker/chai-image.js.map +1 -1
  154. package/dist/server/worker/match-image.d.ts +14 -0
  155. package/dist/server/worker/match-image.js +231 -0
  156. package/dist/server/worker/match-image.js.map +1 -0
  157. package/dist/server/worker/start.d.ts +2 -0
  158. package/dist/server/worker/start.js +258 -0
  159. package/dist/server/worker/start.js.map +1 -0
  160. package/dist/types.d.ts +126 -64
  161. package/dist/types.js +15 -9
  162. package/dist/types.js.map +1 -1
  163. package/package.json +108 -110
  164. package/src/client/addon/components/Addon.tsx +1 -1
  165. package/src/client/addon/components/Icons.tsx +1 -1
  166. package/src/client/addon/components/Panel.tsx +1 -1
  167. package/src/client/addon/components/TestSelect.tsx +5 -5
  168. package/src/client/addon/components/Tools.tsx +9 -9
  169. package/src/client/addon/controller.ts +1 -1
  170. package/src/client/addon/manager.ts +4 -4
  171. package/src/client/addon/withCreevey.ts +26 -28
  172. package/src/client/shared/components/ImagesView/BlendView.tsx +1 -1
  173. package/src/client/shared/components/ImagesView/ImagesView.tsx +2 -2
  174. package/src/client/shared/components/ImagesView/SideBySideView.tsx +1 -1
  175. package/src/client/shared/components/ImagesView/SlideView.tsx +1 -1
  176. package/src/client/shared/components/ImagesView/SwapView.tsx +1 -1
  177. package/src/client/shared/components/PageFooter/PageFooter.tsx +2 -2
  178. package/src/client/shared/components/PageFooter/Paging.tsx +13 -13
  179. package/src/client/shared/components/PageHeader/ImagePreview.tsx +1 -1
  180. package/src/client/shared/components/PageHeader/PageHeader.tsx +4 -3
  181. package/src/client/shared/components/ResultsPage.tsx +1 -1
  182. package/src/client/web/CreeveyApp.tsx +1 -1
  183. package/src/client/web/CreeveyLoader.tsx +1 -1
  184. package/src/client/web/CreeveyView/SideBar/Checkbox.tsx +6 -7
  185. package/src/client/web/CreeveyView/SideBar/Search.tsx +4 -4
  186. package/src/client/web/CreeveyView/SideBar/SideBar.tsx +3 -10
  187. package/src/client/web/CreeveyView/SideBar/SideBarFooter.tsx +7 -6
  188. package/src/client/web/CreeveyView/SideBar/SideBarHeader.tsx +7 -6
  189. package/src/client/web/CreeveyView/SideBar/SuiteLink.tsx +8 -6
  190. package/src/client/web/CreeveyView/SideBar/TestLink.tsx +8 -3
  191. package/src/client/web/CreeveyView/SideBar/TestStatusIcon.tsx +18 -10
  192. package/src/client/web/CreeveyView/SideBar/TestsStatus.tsx +7 -10
  193. package/src/client/web/CreeveyView/SideBar/Toggle.tsx +1 -2
  194. package/src/client/web/KeyboardEventsContext.tsx +3 -4
  195. package/src/client/web/index.html +1 -1
  196. package/src/client/web/index.tsx +4 -3
  197. package/src/creevey.ts +25 -8
  198. package/src/index.ts +4 -2
  199. package/src/server/config.ts +12 -8
  200. package/src/server/docker.ts +58 -44
  201. package/src/server/index.ts +57 -18
  202. package/src/server/master/master.ts +3 -6
  203. package/src/server/master/pool.ts +20 -7
  204. package/src/server/master/runner.ts +2 -2
  205. package/src/server/master/server.ts +1 -0
  206. package/src/server/master/{index.ts → start.ts} +13 -11
  207. package/src/server/messages.ts +11 -75
  208. package/src/server/playwright/docker-file.ts +21 -0
  209. package/src/server/playwright/docker.ts +41 -0
  210. package/src/server/playwright/internal.ts +387 -0
  211. package/src/server/playwright/webdriver.ts +126 -0
  212. package/src/server/{storybook/providers → providers}/browser.ts +7 -8
  213. package/src/server/{storybook/providers → providers}/hybrid.ts +19 -19
  214. package/src/server/{worker/reporter.ts → reporter.ts} +40 -72
  215. package/src/server/selenium/internal.ts +785 -0
  216. package/src/server/selenium/selenoid.ts +12 -17
  217. package/src/server/selenium/webdriver.ts +136 -0
  218. package/src/server/stories.ts +18 -11
  219. package/src/server/telemetry.ts +2 -2
  220. package/src/server/utils.ts +9 -9
  221. package/src/server/webdriver.ts +127 -0
  222. package/src/server/worker/chai-image.ts +21 -133
  223. package/src/server/worker/match-image.ts +303 -0
  224. package/src/server/worker/start.ts +303 -0
  225. package/src/types.ts +161 -60
  226. package/dist/client/web/202.js +0 -1
  227. package/dist/client/web/270.js +0 -43
  228. package/dist/client/web/752.js +0 -1
  229. package/dist/client/web/main.js +0 -79
  230. package/dist/client/web/main.js.LICENSE.txt +0 -34
  231. package/dist/server/master/index.d.ts +0 -3
  232. package/dist/server/master/index.js.map +0 -1
  233. package/dist/server/selenium/browser.d.ts +0 -19
  234. package/dist/server/selenium/browser.js +0 -640
  235. package/dist/server/selenium/browser.js.map +0 -1
  236. package/dist/server/selenium/index.d.ts +0 -2
  237. package/dist/server/selenium/index.js +0 -19
  238. package/dist/server/selenium/index.js.map +0 -1
  239. package/dist/server/storybook/providers/browser.d.ts +0 -2
  240. package/dist/server/storybook/providers/browser.js.map +0 -1
  241. package/dist/server/storybook/providers/hybrid.d.ts +0 -2
  242. package/dist/server/storybook/providers/hybrid.js.map +0 -1
  243. package/dist/server/worker/helpers.d.ts +0 -8
  244. package/dist/server/worker/helpers.js +0 -57
  245. package/dist/server/worker/helpers.js.map +0 -1
  246. package/dist/server/worker/index.d.ts +0 -1
  247. package/dist/server/worker/index.js +0 -6
  248. package/dist/server/worker/index.js.map +0 -1
  249. package/dist/server/worker/reporter.d.ts +0 -8
  250. package/dist/server/worker/reporter.js.map +0 -1
  251. package/dist/server/worker/worker.d.ts +0 -4
  252. package/dist/server/worker/worker.js +0 -217
  253. package/dist/server/worker/worker.js.map +0 -1
  254. package/src/server/selenium/browser.ts +0 -840
  255. package/src/server/selenium/index.ts +0 -2
  256. package/src/server/worker/helpers.ts +0 -61
  257. package/src/server/worker/index.ts +0 -1
  258. package/src/server/worker/worker.ts +0 -245
  259. package/types/mocha.d.ts +0 -20
@@ -1,2 +0,0 @@
1
- export * from './browser.js';
2
- export * from './selenoid.js';
@@ -1,61 +0,0 @@
1
- import { Suite, Context, Test } from 'mocha';
2
- import { Config, isDefined, ServerTest } from '../../types.js';
3
- import { loadTestsFromStories } from '../stories.js';
4
-
5
- function findOrCreateSuite(name: string, parent: Suite): Suite {
6
- const suite = parent.suites.find(({ title }) => title == name) ?? new Suite(name, parent.ctx);
7
- if (!suite.parent) {
8
- suite.parent = parent;
9
- parent.addSuite(suite);
10
- }
11
- return suite;
12
- }
13
-
14
- function createTest(name: string, fn: (this: Context) => Promise<void>, skip: string | boolean = false): Test {
15
- const test = new Test(name, skip ? undefined : fn);
16
- test.pending = Boolean(skip);
17
- // NOTE Can't define skip reason in mocha https://github.com/mochajs/mocha/issues/2026
18
- test.skipReason = skip;
19
- return test;
20
- }
21
-
22
- function addTest(rootSuite: Suite, test: ServerTest): Test {
23
- const [testName, ...suitePath] = [...test.storyPath, test.testName].reverse().filter(isDefined);
24
- const suite = suitePath.reduceRight((subSuite, suiteName) => findOrCreateSuite(suiteName, subSuite), rootSuite);
25
- const mochaTest = createTest(testName, test.fn, test.skip);
26
- suite.addTest(mochaTest);
27
- mochaTest.ctx = Object.setPrototypeOf({ id: test.id, story: test.story }, suite.ctx) as Context;
28
- return mochaTest;
29
- }
30
-
31
- function removeTestOrSuite(testOrSuite: Test | Suite): void {
32
- const { parent } = testOrSuite;
33
- if (!parent) return;
34
- if (testOrSuite instanceof Test) parent.tests = parent.tests.filter((test) => test != testOrSuite);
35
- if (testOrSuite instanceof Suite) parent.suites = parent.suites.filter((suite) => suite != testOrSuite);
36
- if (parent.tests.length == 0 && parent.suites.length == 0) removeTestOrSuite(parent);
37
- }
38
-
39
- export async function addTestsFromStories(
40
- rootSuite: Suite,
41
- config: Config,
42
- { browser, ...options }: { browser: string; watch: boolean; debug: boolean; port: number },
43
- ): Promise<void> {
44
- const mochaTestsById = new Map<string, Test>();
45
- const tests = await loadTestsFromStories(
46
- [browser],
47
- (listener) => config.storiesProvider(config, options, listener),
48
- (testsDiff) => {
49
- Object.entries(testsDiff).forEach(([id, newTest]) => {
50
- const oldTest = mochaTestsById.get(id);
51
- mochaTestsById.delete(id);
52
- if (oldTest) removeTestOrSuite(oldTest);
53
- if (newTest) mochaTestsById.set(id, addTest(rootSuite, newTest));
54
- });
55
- },
56
- );
57
-
58
- Object.values(tests)
59
- .filter(isDefined)
60
- .forEach((test) => mochaTestsById.set(test.id, addTest(rootSuite, test)));
61
- }
@@ -1 +0,0 @@
1
- export { start } from './worker.js';
@@ -1,245 +0,0 @@
1
- import path from 'path';
2
- import chai from 'chai';
3
- import chalk from 'chalk';
4
- import { Stats } from 'fs';
5
- import assert from 'assert';
6
- import { stat, readdir, readFile, writeFile, mkdir } from 'fs/promises';
7
- import Mocha, { Context, MochaOptions } from 'mocha';
8
- import { Key, until } from 'selenium-webdriver';
9
- import { Config, Images, Options, TestMessage, isImageError } from '../../types.js';
10
- import { subscribeOn, emitTestMessage, emitWorkerMessage } from '../messages.js';
11
- import chaiImage from './chai-image.js';
12
- import { getBrowser, switchStory } from '../selenium/index.js';
13
- import { CreeveyReporter, TeamcityReporter } from './reporter.js';
14
- import { addTestsFromStories } from './helpers.js';
15
- import { logger } from '../logger.js';
16
-
17
- async function getStat(filePath: string): Promise<Stats | null> {
18
- try {
19
- return await stat(filePath);
20
- } catch (error) {
21
- if (typeof error == 'object' && error && (error as { code?: unknown }).code === 'ENOENT') {
22
- return null;
23
- }
24
- throw error;
25
- }
26
- }
27
-
28
- async function getLastImageNumber(imageDir: string, imageName: string): Promise<number> {
29
- const actualImagesRegexp = new RegExp(`${imageName}-actual-(\\d+)\\.png`);
30
-
31
- try {
32
- return (
33
- (await readdir(imageDir))
34
- .map((filename) => filename.replace(actualImagesRegexp, '$1'))
35
- .map(Number)
36
- .filter((x) => !isNaN(x))
37
- .sort((a, b) => b - a)[0] ?? 0
38
- );
39
- } catch (_error) {
40
- return 0;
41
- }
42
- }
43
-
44
- // FIXME browser options hotfix
45
- export async function start(config: Config, options: Options & { browser: string }): Promise<void> {
46
- let retries = 0;
47
- let images: Partial<Record<string, Images>> = {};
48
- let error: string | undefined = undefined;
49
- const screenshots: { imageName?: string; screenshot: string }[] = [];
50
- const testScope: string[] = [];
51
-
52
- function runHandler(failures: number): void {
53
- if (failures > 0 && (error || Object.values(images).some((image) => image?.error != null))) {
54
- const isTimeout = hasTimeout(error) || Object.values(images).some((image) => hasTimeout(image?.error));
55
- const payload: { status: 'failed'; images: typeof images; error?: string } = {
56
- status: 'failed',
57
- images,
58
- error,
59
- };
60
- if (isTimeout) emitWorkerMessage({ type: 'error', payload: { error: error ?? 'Unknown error' } });
61
- else emitTestMessage({ type: 'end', payload });
62
- } else {
63
- emitTestMessage({ type: 'end', payload: { status: 'success', images } });
64
- }
65
- }
66
-
67
- async function saveImages(imageDir: string, images: { name: string; data: Buffer }[]): Promise<void> {
68
- await mkdir(imageDir, { recursive: true });
69
- for (const { name, data } of images) {
70
- await writeFile(path.join(imageDir, name), data);
71
- }
72
- }
73
-
74
- async function getExpected(
75
- assertImageName?: string,
76
- ): Promise<
77
- | { expected: Buffer | null; onCompare: (actual: Buffer, expect?: Buffer, diff?: Buffer) => Promise<void> }
78
- | Buffer
79
- | null
80
- > {
81
- // context => [title, name, test, browser]
82
- // rootSuite -> kindSuite -> storyTest -> [browsers.png]
83
- // rootSuite -> kindSuite -> storySuite -> test -> [browsers.png]
84
- const testPath = [...testScope];
85
- const imageName = assertImageName ?? testPath.pop();
86
-
87
- assert(typeof imageName === 'string', `Can't get image name from empty test scope`);
88
-
89
- const imagesMeta: { name: string; data: Buffer }[] = [];
90
- const reportImageDir = path.join(config.reportDir, ...testPath);
91
- const imageNumber = (await getLastImageNumber(reportImageDir, imageName)) + 1;
92
- const actualImageName = `${imageName}-actual-${imageNumber}.png`;
93
- const image = (images[imageName] = images[imageName] ?? { actual: actualImageName });
94
- const onCompare = async (actual: Buffer, expect?: Buffer, diff?: Buffer): Promise<void> => {
95
- imagesMeta.push({ name: image.actual, data: actual });
96
-
97
- if (diff && expect) {
98
- image.expect = `${imageName}-expect-${imageNumber}.png`;
99
- image.diff = `${imageName}-diff-${imageNumber}.png`;
100
- imagesMeta.push({ name: image.expect, data: expect });
101
- imagesMeta.push({ name: image.diff, data: diff });
102
- }
103
- if (options.saveReport) {
104
- await saveImages(reportImageDir, imagesMeta);
105
- }
106
- };
107
-
108
- const expectImageDir = path.join(config.screenDir, ...testPath);
109
- const expectImageStat = await getStat(path.join(expectImageDir, `${imageName}.png`));
110
- if (!expectImageStat) return { expected: null, onCompare };
111
-
112
- const expected = await readFile(path.join(expectImageDir, `${imageName}.png`));
113
-
114
- return { expected, onCompare };
115
- }
116
-
117
- const mochaOptions: MochaOptions = {
118
- timeout: 30000,
119
- reporter: process.env.TEAMCITY_VERSION ? TeamcityReporter : (options.reporter ?? CreeveyReporter),
120
- reporterOptions: {
121
- reportDir: config.reportDir,
122
- topLevelSuite: options.browser,
123
- get willRetry() {
124
- return retries < config.maxRetries;
125
- },
126
- get images() {
127
- return images;
128
- },
129
- get sessionId() {
130
- return sessionId;
131
- },
132
- },
133
- };
134
- const mocha = new Mocha(mochaOptions);
135
- mocha.cleanReferencesAfterRun(false);
136
-
137
- chai.use(chaiImage(getExpected, config.diffOptions));
138
-
139
- const browser = await (async () => {
140
- try {
141
- return await getBrowser(config, options);
142
- } catch (error) {
143
- emitWorkerMessage({
144
- type: 'error',
145
- payload: { error: error instanceof Error ? error.message : ((error ?? 'Unknown error') as string) },
146
- });
147
- return null;
148
- }
149
- })();
150
-
151
- if (browser == null) return;
152
-
153
- await addTestsFromStories(mocha.suite, config, {
154
- browser: options.browser,
155
- watch: options.ui,
156
- debug: options.debug,
157
- port: options.port,
158
- });
159
-
160
- const sessionId = (await browser.getSession()).getId();
161
-
162
- const interval = setInterval(
163
- () =>
164
- // NOTE Simple way to keep session alive
165
- void browser.getCurrentUrl().then((url) => {
166
- logger.debug(`${options.browser}:${chalk.gray(sessionId)}`, 'current url', chalk.magenta(url));
167
- }),
168
- 10 * 1000,
169
- );
170
-
171
- subscribeOn('shutdown', () => {
172
- clearInterval(interval);
173
- });
174
-
175
- mocha.suite.beforeAll(function (this: Context) {
176
- this.config = config;
177
- this.browser = browser;
178
- this.until = until;
179
- this.keys = Key;
180
- this.expect = chai.expect;
181
- this.browserName = options.browser;
182
- this.testScope = testScope;
183
- this.screenshots = screenshots;
184
- });
185
- mocha.suite.beforeEach(switchStory);
186
- if (options.trace) {
187
- mocha.suite.afterEach(async function (this: Context) {
188
- const output: string[] = [];
189
- const types = await browser.manage().logs().getAvailableLogTypes();
190
- for (const type of types) {
191
- const logs = await browser.manage().logs().get(type);
192
- output.push(logs.map((log) => JSON.stringify(log.toJSON(), null, 2)).join('\n'));
193
- }
194
- logger.debug(
195
- '----------',
196
- sessionId,
197
- this.currentTest?.titlePath().join('/'),
198
- '----------\n',
199
- output.join('\n'),
200
- '\n----------------------------------------------------------------------------------------------------',
201
- );
202
- });
203
- }
204
-
205
- subscribeOn('test', (message: TestMessage) => {
206
- if (message.type != 'start') return;
207
-
208
- const test = message.payload;
209
- const testPath = test.path.join(' ').replace(/[|\\{}()[\]^$+*?.-]/g, '\\$&');
210
-
211
- images = {};
212
- error = undefined;
213
- retries = test.retries;
214
-
215
- mocha.grep(new RegExp(`^${testPath}$`));
216
- mocha.unloadFiles();
217
- const runner = mocha.run(runHandler);
218
-
219
- // TODO How handle browser corruption?
220
- runner.on('fail', (_test, reason: unknown) => {
221
- if (!(reason instanceof Error)) {
222
- error = reason as string;
223
- } else if (!isImageError(reason)) {
224
- error = reason.stack ?? reason.message;
225
- } else if (typeof reason.images == 'string') {
226
- const image = images[testScope.slice(-1)[0]];
227
- if (image) image.error = reason.images;
228
- } else {
229
- const imageErrors = reason.images;
230
- Object.keys(imageErrors).forEach((imageName) => {
231
- const image = images[imageName];
232
- if (image) image.error = imageErrors[imageName];
233
- });
234
- }
235
- });
236
- });
237
-
238
- logger.info(`${options.browser}:${chalk.gray(sessionId)} is ready`);
239
-
240
- emitWorkerMessage({ type: 'ready' });
241
- }
242
-
243
- function hasTimeout(str: string | null | undefined): boolean {
244
- return str?.toLowerCase().includes('timeout') ?? false;
245
- }
package/types/mocha.d.ts DELETED
@@ -1,20 +0,0 @@
1
- /// <reference types="mocha" />
2
- declare namespace Mocha {
3
- interface Context {
4
- config: import('creevey').Config;
5
- browser: import('selenium-webdriver').WebDriver;
6
- until: import('selenium-webdriver/lib/until');
7
- keys: import('selenium-webdriver/lib/input').IKey;
8
- expect: Chai.ExpectStatic;
9
- takeScreenshot: () => Promise<string>;
10
- updateStoryArgs: (updatedArgs: Record<string, unknown>) => Promise<void>;
11
- readonly captureElement?: import('selenium-webdriver').WebElementPromise;
12
- browserName: string;
13
- testScope: string[];
14
- screenshots: { imageName?: string; screenshot: string }[];
15
- }
16
-
17
- interface Test {
18
- skipReason: string | boolean;
19
- }
20
- }