creevey 0.10.0-beta.2 → 0.10.0-beta.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/dist/client/addon/components/Addon.js +17 -7
  2. package/dist/client/addon/components/Addon.js.map +1 -1
  3. package/dist/client/addon/components/Panel.js +2 -2
  4. package/dist/client/addon/components/Panel.js.map +1 -1
  5. package/dist/client/addon/components/Tools.js +17 -7
  6. package/dist/client/addon/components/Tools.js.map +1 -1
  7. package/dist/client/addon/controller.js +4 -5
  8. package/dist/client/addon/controller.js.map +1 -1
  9. package/dist/client/addon/withCreevey.d.ts +1 -0
  10. package/dist/client/addon/withCreevey.js +19 -34
  11. package/dist/client/addon/withCreevey.js.map +1 -1
  12. package/dist/client/shared/components/ImagesView/BlendView.js +17 -7
  13. package/dist/client/shared/components/ImagesView/BlendView.js.map +1 -1
  14. package/dist/client/shared/components/ImagesView/SideBySideView.js +17 -7
  15. package/dist/client/shared/components/ImagesView/SideBySideView.js.map +1 -1
  16. package/dist/client/shared/components/ImagesView/SlideView.js +17 -7
  17. package/dist/client/shared/components/ImagesView/SlideView.js.map +1 -1
  18. package/dist/client/shared/components/ImagesView/SwapView.js +29 -7
  19. package/dist/client/shared/components/ImagesView/SwapView.js.map +1 -1
  20. package/dist/client/shared/components/PageHeader/ImagePreview.js +1 -0
  21. package/dist/client/shared/components/PageHeader/ImagePreview.js.map +1 -1
  22. package/dist/client/shared/components/PageHeader/PageHeader.js +17 -7
  23. package/dist/client/shared/components/PageHeader/PageHeader.js.map +1 -1
  24. package/dist/client/shared/components/ResultsPage.js +40 -12
  25. package/dist/client/shared/components/ResultsPage.js.map +1 -1
  26. package/dist/client/shared/helpers.d.ts +0 -2
  27. package/dist/client/shared/helpers.js +0 -17
  28. package/dist/client/shared/helpers.js.map +1 -1
  29. package/dist/client/web/CreeveyApp.js +41 -14
  30. package/dist/client/web/CreeveyApp.js.map +1 -1
  31. package/dist/client/web/CreeveyContext.d.ts +5 -0
  32. package/dist/client/web/CreeveyContext.js +20 -7
  33. package/dist/client/web/CreeveyContext.js.map +1 -1
  34. package/dist/client/web/CreeveyLoader.js +2 -2
  35. package/dist/client/web/CreeveyLoader.js.map +1 -1
  36. package/dist/client/web/CreeveyView/SideBar/Search.js +19 -9
  37. package/dist/client/web/CreeveyView/SideBar/Search.js.map +1 -1
  38. package/dist/client/web/CreeveyView/SideBar/SideBar.js +18 -7
  39. package/dist/client/web/CreeveyView/SideBar/SideBar.js.map +1 -1
  40. package/dist/client/web/CreeveyView/SideBar/SideBarFooter.js +60 -7
  41. package/dist/client/web/CreeveyView/SideBar/SideBarFooter.js.map +1 -1
  42. package/dist/client/web/CreeveyView/SideBar/SideBarHeader.js +17 -7
  43. package/dist/client/web/CreeveyView/SideBar/SideBarHeader.js.map +1 -1
  44. package/dist/client/web/CreeveyView/SideBar/SuiteLink.js +18 -10
  45. package/dist/client/web/CreeveyView/SideBar/SuiteLink.js.map +1 -1
  46. package/dist/client/web/CreeveyView/SideBar/TestLink.js +18 -10
  47. package/dist/client/web/CreeveyView/SideBar/TestLink.js.map +1 -1
  48. package/dist/client/web/KeyboardEventsContext.d.ts +1 -8
  49. package/dist/client/web/KeyboardEventsContext.js +79 -64
  50. package/dist/client/web/KeyboardEventsContext.js.map +1 -1
  51. package/dist/client/web/assets/{index-DkmZfG9C.js → index-BZNmck5a.js} +104 -104
  52. package/dist/client/web/index.html +1 -1
  53. package/dist/client/web/index.js +17 -7
  54. package/dist/client/web/index.js.map +1 -1
  55. package/dist/client/web/themes.d.ts +2 -0
  56. package/dist/client/web/themes.js +22 -0
  57. package/dist/client/web/themes.js.map +1 -0
  58. package/dist/creevey.js +13 -5
  59. package/dist/creevey.js.map +1 -1
  60. package/dist/index.d.ts +1 -0
  61. package/dist/server/config.js +5 -4
  62. package/dist/server/config.js.map +1 -1
  63. package/dist/server/docker.js +37 -20
  64. package/dist/server/docker.js.map +1 -1
  65. package/dist/server/index.js +33 -7
  66. package/dist/server/index.js.map +1 -1
  67. package/dist/server/logger.d.ts +2 -1
  68. package/dist/server/logger.js +7 -3
  69. package/dist/server/logger.js.map +1 -1
  70. package/dist/server/master/api.js +1 -1
  71. package/dist/server/master/api.js.map +1 -1
  72. package/dist/server/master/pool.d.ts +3 -3
  73. package/dist/server/master/pool.js +10 -63
  74. package/dist/server/master/pool.js.map +1 -1
  75. package/dist/server/master/queue.d.ts +13 -0
  76. package/dist/server/master/queue.js +64 -0
  77. package/dist/server/master/queue.js.map +1 -0
  78. package/dist/server/master/runner.d.ts +1 -0
  79. package/dist/server/master/runner.js +4 -1
  80. package/dist/server/master/runner.js.map +1 -1
  81. package/dist/server/master/server.js +1 -1
  82. package/dist/server/master/server.js.map +1 -1
  83. package/dist/server/master/start.js +10 -9
  84. package/dist/server/master/start.js.map +1 -1
  85. package/dist/server/playwright/docker-file.d.ts +2 -1
  86. package/dist/server/playwright/docker-file.js +17 -4
  87. package/dist/server/playwright/docker-file.js.map +1 -1
  88. package/dist/server/playwright/internal.d.ts +2 -2
  89. package/dist/server/playwright/internal.js +57 -44
  90. package/dist/server/playwright/internal.js.map +1 -1
  91. package/dist/server/playwright/webdriver.d.ts +1 -1
  92. package/dist/server/playwright/webdriver.js +1 -1
  93. package/dist/server/playwright/webdriver.js.map +1 -1
  94. package/dist/server/providers/browser.js +6 -4
  95. package/dist/server/providers/browser.js.map +1 -1
  96. package/dist/server/providers/hybrid.js +1 -1
  97. package/dist/server/providers/hybrid.js.map +1 -1
  98. package/dist/server/reporter.js +13 -9
  99. package/dist/server/reporter.js.map +1 -1
  100. package/dist/server/selenium/internal.d.ts +3 -4
  101. package/dist/server/selenium/internal.js +127 -91
  102. package/dist/server/selenium/internal.js.map +1 -1
  103. package/dist/server/selenium/selenoid.js +2 -2
  104. package/dist/server/selenium/selenoid.js.map +1 -1
  105. package/dist/server/selenium/webdriver.d.ts +1 -1
  106. package/dist/server/selenium/webdriver.js +1 -1
  107. package/dist/server/selenium/webdriver.js.map +1 -1
  108. package/dist/server/telemetry.js +7 -3
  109. package/dist/server/telemetry.js.map +1 -1
  110. package/dist/server/utils.d.ts +2 -1
  111. package/dist/server/utils.js +13 -3
  112. package/dist/server/utils.js.map +1 -1
  113. package/dist/server/webdriver.d.ts +3 -4
  114. package/dist/server/webdriver.js +10 -9
  115. package/dist/server/webdriver.js.map +1 -1
  116. package/dist/server/worker/chai-image.d.ts +1 -2
  117. package/dist/server/worker/chai-image.js +4 -3
  118. package/dist/server/worker/chai-image.js.map +1 -1
  119. package/dist/server/worker/match-image.d.ts +4 -4
  120. package/dist/server/worker/match-image.js +7 -4
  121. package/dist/server/worker/match-image.js.map +1 -1
  122. package/dist/server/worker/start.js +24 -14
  123. package/dist/server/worker/start.js.map +1 -1
  124. package/dist/shared/index.d.ts +1 -1
  125. package/dist/types.d.ts +32 -13
  126. package/dist/types.js +13 -1
  127. package/dist/types.js.map +1 -1
  128. package/package.json +55 -59
  129. package/src/client/addon/components/Panel.tsx +2 -2
  130. package/src/client/addon/controller.ts +13 -6
  131. package/src/client/addon/withCreevey.ts +27 -13
  132. package/src/client/shared/components/ImagesView/SwapView.tsx +18 -0
  133. package/src/client/shared/components/PageHeader/ImagePreview.tsx +1 -0
  134. package/src/client/shared/components/ResultsPage.tsx +28 -7
  135. package/src/client/shared/helpers.ts +0 -22
  136. package/src/client/web/CreeveyApp.tsx +26 -8
  137. package/src/client/web/CreeveyContext.tsx +9 -0
  138. package/src/client/web/CreeveyLoader.tsx +1 -1
  139. package/src/client/web/CreeveyView/SideBar/Search.tsx +3 -3
  140. package/src/client/web/CreeveyView/SideBar/SideBar.tsx +1 -0
  141. package/src/client/web/CreeveyView/SideBar/SideBarFooter.tsx +37 -6
  142. package/src/client/web/CreeveyView/SideBar/SuiteLink.tsx +3 -5
  143. package/src/client/web/CreeveyView/SideBar/TestLink.tsx +2 -4
  144. package/src/client/web/KeyboardEventsContext.tsx +61 -73
  145. package/src/client/web/themes.ts +24 -0
  146. package/src/creevey.ts +13 -6
  147. package/src/server/config.ts +5 -4
  148. package/src/server/docker.ts +41 -23
  149. package/src/server/index.ts +35 -9
  150. package/src/server/logger.ts +6 -2
  151. package/src/server/master/api.ts +1 -1
  152. package/src/server/master/pool.ts +18 -56
  153. package/src/server/master/queue.ts +64 -0
  154. package/src/server/master/runner.ts +4 -1
  155. package/src/server/master/server.ts +1 -1
  156. package/src/server/master/start.ts +13 -9
  157. package/src/server/playwright/docker-file.ts +19 -4
  158. package/src/server/playwright/internal.ts +77 -49
  159. package/src/server/playwright/webdriver.ts +2 -2
  160. package/src/server/providers/browser.ts +6 -4
  161. package/src/server/providers/hybrid.ts +1 -1
  162. package/src/server/reporter.ts +15 -9
  163. package/src/server/selenium/internal.ts +133 -96
  164. package/src/server/selenium/selenoid.ts +2 -2
  165. package/src/server/selenium/webdriver.ts +2 -2
  166. package/src/server/telemetry.ts +7 -3
  167. package/src/server/utils.ts +14 -4
  168. package/src/server/webdriver.ts +11 -16
  169. package/src/server/worker/chai-image.ts +4 -4
  170. package/src/server/worker/match-image.ts +12 -8
  171. package/src/server/worker/start.ts +25 -16
  172. package/src/shared/index.ts +1 -1
  173. package/src/types.ts +35 -15
  174. package/types/global.d.ts +1 -0
  175. package/.yarnrc.yml +0 -1
  176. package/chromatic.config.json +0 -5
package/dist/types.d.ts CHANGED
@@ -4,7 +4,7 @@ import type Pixelmatch from 'pixelmatch';
4
4
  import type { ODiffOptions } from 'odiff-bin';
5
5
  import type { expect } from 'chai';
6
6
  import type EventEmitter from 'events';
7
- import type Logger from 'loglevel';
7
+ import { LaunchOptions } from 'playwright-core';
8
8
  export type DiffOptions = typeof Pixelmatch extends (x1: any, x2: any, x3: any, x4: any, x5: any, options?: infer T) => void ? T : never;
9
9
  export interface SetStoriesData {
10
10
  v?: number;
@@ -28,6 +28,17 @@ export interface StoryMeta {
28
28
  [name: string]: unknown;
29
29
  };
30
30
  }
31
+ export declare enum StorybookEvents {
32
+ SET_STORIES = "setStories",
33
+ SET_CURRENT_STORY = "setCurrentStory",
34
+ FORCE_REMOUNT = "forceRemount",
35
+ STORY_RENDERED = "storyRendered",
36
+ STORY_ERRORED = "storyErrored",
37
+ STORY_THREW_EXCEPTION = "storyThrewException",
38
+ UPDATE_STORY_ARGS = "updateStoryArgs",
39
+ SET_GLOBALS = "setGlobals",
40
+ UPDATE_GLOBALS = "updateGlobals"
41
+ }
31
42
  export interface CreeveyMeta {
32
43
  parameters?: {
33
44
  creevey?: CreeveyStoryParams;
@@ -66,14 +77,6 @@ export interface CreeveyStory {
66
77
  }
67
78
  export interface BrowserConfigObject {
68
79
  browserName: string;
69
- /**
70
- * Browser version. Ignored with Playwright webdriver
71
- */
72
- browserVersion?: string;
73
- /**
74
- * Operation system name. Ignored with Playwright webdriver
75
- */
76
- platformName?: string;
77
80
  limit?: number;
78
81
  /**
79
82
  * Selenium grid url
@@ -100,7 +103,18 @@ export interface BrowserConfigObject {
100
103
  width: number;
101
104
  height: number;
102
105
  };
103
- [name: string]: unknown;
106
+ seleniumCapabilities?: {
107
+ /**
108
+ * Browser version. Ignored with Playwright webdriver
109
+ */
110
+ browserVersion?: string;
111
+ /**
112
+ * Operation system name. Ignored with Playwright webdriver
113
+ */
114
+ platformName?: string;
115
+ [name: string]: unknown;
116
+ };
117
+ playwrightOptions?: Omit<LaunchOptions, 'logger'>;
104
118
  }
105
119
  export type StorybookGlobals = Record<string, unknown>;
106
120
  export type BrowserConfig = boolean | string | BrowserConfigObject;
@@ -110,7 +124,7 @@ export interface CreeveyWebdriver {
110
124
  openBrowser(fresh?: boolean): Promise<CreeveyWebdriver | null>;
111
125
  closeBrowser(): Promise<void>;
112
126
  loadStoriesFromBrowser(): Promise<StoriesRaw>;
113
- switchStory(story: StoryInput, context: BaseCreeveyTestContext, logger: Logger.Logger): Promise<CreeveyTestContext>;
127
+ switchStory(story: StoryInput, context: BaseCreeveyTestContext): Promise<CreeveyTestContext>;
114
128
  afterTest(test: ServerTest): Promise<void>;
115
129
  }
116
130
  export interface HookConfig {
@@ -249,6 +263,11 @@ export interface Config {
249
263
  * The `--ui` CLI option ignores this option
250
264
  */
251
265
  failFast: boolean;
266
+ /**
267
+ * Start workers in sequential queue
268
+ * @default false
269
+ */
270
+ useWorkerQueue: boolean;
252
271
  /**
253
272
  * Specify platform for docker images
254
273
  */
@@ -391,8 +410,8 @@ export interface BaseCreeveyTestContext {
391
410
  imageName?: string;
392
411
  screenshot: Buffer;
393
412
  }[];
394
- matchImage: (image: Buffer, imageName?: string) => Promise<void>;
395
- matchImages: (images: Record<string, Buffer>) => Promise<void>;
413
+ matchImage: (image: Buffer | string, imageName?: string) => Promise<void>;
414
+ matchImages: (images: Record<string, Buffer | string>) => Promise<void>;
396
415
  }
397
416
  export interface CreeveyTestContext extends BaseCreeveyTestContext {
398
417
  takeScreenshot: () => Promise<Buffer>;
package/dist/types.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TEST_EVENTS = exports.ImagesError = void 0;
3
+ exports.TEST_EVENTS = exports.ImagesError = exports.StorybookEvents = void 0;
4
4
  exports.noop = noop;
5
5
  exports.isDefined = isDefined;
6
6
  exports.isTest = isTest;
@@ -12,6 +12,18 @@ exports.isProcessMessage = isProcessMessage;
12
12
  exports.isWorkerMessage = isWorkerMessage;
13
13
  exports.isStoriesMessage = isStoriesMessage;
14
14
  exports.isTestMessage = isTestMessage;
15
+ var StorybookEvents;
16
+ (function (StorybookEvents) {
17
+ StorybookEvents["SET_STORIES"] = "setStories";
18
+ StorybookEvents["SET_CURRENT_STORY"] = "setCurrentStory";
19
+ StorybookEvents["FORCE_REMOUNT"] = "forceRemount";
20
+ StorybookEvents["STORY_RENDERED"] = "storyRendered";
21
+ StorybookEvents["STORY_ERRORED"] = "storyErrored";
22
+ StorybookEvents["STORY_THREW_EXCEPTION"] = "storyThrewException";
23
+ StorybookEvents["UPDATE_STORY_ARGS"] = "updateStoryArgs";
24
+ StorybookEvents["SET_GLOBALS"] = "setGlobals";
25
+ StorybookEvents["UPDATE_GLOBALS"] = "updateGlobals";
26
+ })(StorybookEvents || (exports.StorybookEvents = StorybookEvents = {}));
15
27
  class ImagesError extends Error {
16
28
  images;
17
29
  }
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAiiBA,oBAEC;AAED,8BAEC;AAED,wBASC;AAED,4BAEC;AAED,4BAEC;AAGD,gCAEC;AAED,oCAEC;AAED,4CAEC;AAED,0CAEC;AAED,4CAEC;AAED,sCAEC;AA3MD,MAAa,WAAY,SAAQ,KAAK;IACpC,MAAM,CAA4C;CACnD;AAFD,kCAEC;AAwCD,IAAY,WAOX;AAPD,WAAY,WAAW;IACrB,kCAAmB,CAAA;IACnB,8BAAe,CAAA;IACf,kCAAmB,CAAA;IACnB,oCAAqB,CAAA;IACrB,iCAAkB,CAAA;IAClB,iCAAkB,CAAA;AACpB,CAAC,EAPW,WAAW,2BAAX,WAAW,QAOtB;AAwGD,SAAgB,IAAI;IAClB,UAAU;AACZ,CAAC;AAED,SAAgB,SAAS,CAAI,KAA2B;IACtD,OAAO,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC;AAC/C,CAAC;AAED,SAAgB,MAAM,CAAC,CAA8B;IACnD,OAAO,CACL,SAAS,CAAC,CAAC,CAAC;QACZ,QAAQ,CAAC,CAAC,CAAC;QACX,IAAI,IAAI,CAAC;QACT,SAAS,IAAI,CAAC;QACd,OAAO,CAAC,CAAC,EAAE,IAAI,QAAQ;QACvB,OAAO,CAAC,CAAC,OAAO,IAAI,QAAQ,CAC7B,CAAC;AACJ,CAAC;AAED,SAAgB,QAAQ,CAAC,CAAU;IACjC,OAAO,OAAO,CAAC,IAAI,QAAQ,IAAI,CAAC,IAAI,IAAI,CAAC;AAC3C,CAAC;AAED,SAAgB,QAAQ,CAAC,CAAU;IACjC,OAAO,OAAO,CAAC,IAAI,QAAQ,CAAC;AAC9B,CAAC;AAED,8DAA8D;AAC9D,SAAgB,UAAU,CAAC,CAAU;IACnC,OAAO,OAAO,CAAC,IAAI,UAAU,CAAC;AAChC,CAAC;AAED,SAAgB,YAAY,CAAC,KAAc;IACzC,OAAO,KAAK,YAAY,WAAW,IAAI,QAAQ,IAAI,KAAK,CAAC;AAC3D,CAAC;AAED,SAAgB,gBAAgB,CAAC,OAAgB;IAC/C,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,OAAO,CAAC;AACjD,CAAC;AAED,SAAgB,eAAe,CAAC,OAAgB;IAC9C,OAAO,gBAAgB,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC;AAChE,CAAC;AAED,SAAgB,gBAAgB,CAAC,OAAgB;IAC/C,OAAO,gBAAgB,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,IAAI,SAAS,CAAC;AACjE,CAAC;AAED,SAAgB,aAAa,CAAC,OAAgB;IAC5C,OAAO,gBAAgB,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC;AAC9D,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAqjBA,oBAEC;AAED,8BAEC;AAED,wBASC;AAED,4BAEC;AAED,4BAEC;AAGD,gCAEC;AAED,oCAEC;AAED,4CAEC;AAED,0CAEC;AAED,4CAEC;AAED,sCAEC;AA5jBD,IAAY,eAUX;AAVD,WAAY,eAAe;IACzB,6CAA0B,CAAA;IAC1B,wDAAqC,CAAA;IACrC,iDAA8B,CAAA;IAC9B,mDAAgC,CAAA;IAChC,iDAA8B,CAAA;IAC9B,gEAA6C,CAAA;IAC7C,wDAAqC,CAAA;IACrC,6CAA0B,CAAA;IAC1B,mDAAgC,CAAA;AAClC,CAAC,EAVW,eAAe,+BAAf,eAAe,QAU1B;AAuWD,MAAa,WAAY,SAAQ,KAAK;IACpC,MAAM,CAA4C;CACnD;AAFD,kCAEC;AAwCD,IAAY,WAOX;AAPD,WAAY,WAAW;IACrB,kCAAmB,CAAA;IACnB,8BAAe,CAAA;IACf,kCAAmB,CAAA;IACnB,oCAAqB,CAAA;IACrB,iCAAkB,CAAA;IAClB,iCAAkB,CAAA;AACpB,CAAC,EAPW,WAAW,2BAAX,WAAW,QAOtB;AAwGD,SAAgB,IAAI;IAClB,UAAU;AACZ,CAAC;AAED,SAAgB,SAAS,CAAI,KAA2B;IACtD,OAAO,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC;AAC/C,CAAC;AAED,SAAgB,MAAM,CAAC,CAA8B;IACnD,OAAO,CACL,SAAS,CAAC,CAAC,CAAC;QACZ,QAAQ,CAAC,CAAC,CAAC;QACX,IAAI,IAAI,CAAC;QACT,SAAS,IAAI,CAAC;QACd,OAAO,CAAC,CAAC,EAAE,IAAI,QAAQ;QACvB,OAAO,CAAC,CAAC,OAAO,IAAI,QAAQ,CAC7B,CAAC;AACJ,CAAC;AAED,SAAgB,QAAQ,CAAC,CAAU;IACjC,OAAO,OAAO,CAAC,IAAI,QAAQ,IAAI,CAAC,IAAI,IAAI,CAAC;AAC3C,CAAC;AAED,SAAgB,QAAQ,CAAC,CAAU;IACjC,OAAO,OAAO,CAAC,IAAI,QAAQ,CAAC;AAC9B,CAAC;AAED,8DAA8D;AAC9D,SAAgB,UAAU,CAAC,CAAU;IACnC,OAAO,OAAO,CAAC,IAAI,UAAU,CAAC;AAChC,CAAC;AAED,SAAgB,YAAY,CAAC,KAAc;IACzC,OAAO,KAAK,YAAY,WAAW,IAAI,QAAQ,IAAI,KAAK,CAAC;AAC3D,CAAC;AAED,SAAgB,gBAAgB,CAAC,OAAgB;IAC/C,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,OAAO,CAAC;AACjD,CAAC;AAED,SAAgB,eAAe,CAAC,OAAgB;IAC9C,OAAO,gBAAgB,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC;AAChE,CAAC;AAED,SAAgB,gBAAgB,CAAC,OAAgB;IAC/C,OAAO,gBAAgB,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,IAAI,SAAS,CAAC;AACjE,CAAC;AAED,SAAgB,aAAa,CAAC,OAAgB;IAC5C,OAAO,gBAAgB,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC;AAC9D,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "creevey",
3
3
  "description": "Cross-browser screenshot testing tool for Storybook with fancy UI Runner",
4
- "version": "0.10.0-beta.2",
4
+ "version": "0.10.0-beta.20",
5
5
  "type": "commonjs",
6
6
  "bin": "dist/cli.js",
7
7
  "main": "./dist/index.js",
@@ -9,12 +9,12 @@
9
9
  "exports": {
10
10
  ".": "./dist/index.js",
11
11
  "./playwright": {
12
- "default": "./dist/playwright.js",
13
- "types": "./dist/playwright.d.ts"
12
+ "types": "./dist/playwright.d.ts",
13
+ "default": "./dist/playwright.js"
14
14
  },
15
15
  "./selenium": {
16
- "default": "./dist/selenium.js",
17
- "types": "./dist/selenium.d.ts"
16
+ "types": "./dist/selenium.d.ts",
17
+ "default": "./dist/selenium.js"
18
18
  },
19
19
  "./manager": "./dist/client/addon/manager.js",
20
20
  "./preview": "./dist/client/addon/preview.js",
@@ -87,29 +87,30 @@
87
87
  },
88
88
  "dependencies": {
89
89
  "@koa/cors": "^5.0.0",
90
- "@octokit/core": "^6.1.2",
90
+ "@octokit/core": "^6.1.3",
91
+ "@storybook/icons": "^1.3.0",
91
92
  "@types/chai": "^4.3.20",
92
- "@types/dockerode": "^3.3.31",
93
+ "@types/dockerode": "^3.3.34",
93
94
  "@types/koa": "^2.15.0",
94
95
  "@types/koa-bodyparser": "^4.3.12",
95
96
  "@types/koa-mount": "^4.0.5",
96
97
  "@types/koa-static": "^4.0.4",
97
98
  "@types/koa__cors": "^5.0.0",
98
- "@types/lodash": "^4.17.13",
99
+ "@types/lodash": "^4.17.14",
99
100
  "@types/micromatch": "^4.0.9",
100
101
  "@types/minimist": "^1.2.5",
101
102
  "@types/pixelmatch": "^5.2.6",
102
103
  "@types/pngjs": "^6.0.5",
103
- "@types/qs": "^6.9.16",
104
- "@types/react": "^18.3.12",
105
- "@types/react-dom": "^18.3.1",
106
- "@types/selenium-webdriver": "^4.1.27",
104
+ "@types/qs": "^6.9.17",
105
+ "@types/react": "^18.3.18",
106
+ "@types/react-dom": "^18.3.5",
107
+ "@types/selenium-webdriver": "^4.1.28",
107
108
  "@types/shelljs": "^0.8.15",
108
109
  "@types/ws": "^8.5.13",
109
110
  "chai": "^4.5.0",
110
111
  "chalk": "^4.1.2",
111
- "chokidar": "^4.0.1",
112
- "dockerode": "^4.0.2",
112
+ "chokidar": "^4.0.3",
113
+ "dockerode": "^4.0.3",
113
114
  "find-cache-dir": "^5.0.0",
114
115
  "get-port": "^7.1.0",
115
116
  "koa": "^2.15.3",
@@ -121,77 +122,72 @@
121
122
  "loglevel-plugin-prefix": "^0.8.4",
122
123
  "micromatch": "^4.0.8",
123
124
  "minimist": "^1.2.8",
124
- "odiff-bin": "^3.1.2",
125
+ "odiff-bin": "^3.2.0",
125
126
  "pixelmatch": "^6.0.0",
126
127
  "pngjs": "^7.0.0",
127
128
  "polished": "^4.3.1",
128
- "qs": "^6.13.0",
129
+ "qs": "^6.13.1",
129
130
  "semver": "^7.6.3",
130
131
  "shelljs": "^0.8.5",
131
132
  "tar-stream": "^3.1.7",
132
133
  "tsx": "^4.19.2",
133
- "uuid": "^11.0.2",
134
+ "uuid": "^11.0.5",
134
135
  "ws": "^8.18.0",
135
- "yocto-spinner": "^0.1.1"
136
+ "yocto-spinner": "^0.1.2"
136
137
  },
137
138
  "devDependencies": {
138
- "@chromatic-com/storybook": "^3.2.2",
139
- "@eslint/js": "^9.14.0",
140
- "@storybook/addon-essentials": "^8.4.1",
141
- "@storybook/addon-interactions": "^8.4.1",
142
- "@storybook/blocks": "^8.4.1",
143
- "@storybook/channels": "^8.4.1",
144
- "@storybook/client-logger": "^8.4.1",
145
- "@storybook/components": "^8.4.1",
146
- "@storybook/core-common": "^8.4.1",
147
- "@storybook/core-events": "^8.4.1",
148
- "@storybook/core-server": "^8.4.1",
149
- "@storybook/csf": "^0.1.11",
150
- "@storybook/icons": "^1.2.12",
151
- "@storybook/manager-api": "^8.4.1",
152
- "@storybook/preview-api": "^8.4.1",
153
- "@storybook/react": "^8.4.1",
154
- "@storybook/react-vite": "^8.4.1",
155
- "@storybook/test": "^8.4.1",
156
- "@storybook/theming": "^8.4.1",
157
- "@storybook/types": "^8.4.1",
139
+ "@chromatic-com/storybook": "^3.2.3",
140
+ "@eslint/js": "^9.18.0",
141
+ "@storybook/addon-essentials": "^8.4.7",
142
+ "@storybook/addon-interactions": "^8.4.7",
143
+ "@storybook/blocks": "^8.4.7",
144
+ "@storybook/channels": "^8.4.7",
145
+ "@storybook/components": "^8.4.7",
146
+ "@storybook/csf": "^0.1.13",
147
+ "@storybook/manager-api": "^8.4.7",
148
+ "@storybook/preview-api": "^8.4.7",
149
+ "@storybook/react": "^8.4.7",
150
+ "@storybook/react-vite": "^8.4.7",
151
+ "@storybook/test": "^8.4.7",
152
+ "@storybook/theming": "^8.4.7",
153
+ "@storybook/types": "^8.4.7",
158
154
  "@types/eslint": "^9.6.1",
159
155
  "@types/eslint__js": "^8.42.3",
160
156
  "@types/node": "^18.19.64",
161
157
  "@types/resize-observer-browser": "^0.1.11",
162
- "@types/semver": "^7",
158
+ "@types/semver": "^7.5.8",
163
159
  "@types/tar-stream": "^3.1.3",
164
160
  "@types/tmp": "^0.2.6",
165
- "@vitejs/plugin-react-swc": "^3.7.1",
166
- "browserstack-local": "^1.5.5",
167
- "chromatic": "^11.16.3",
168
- "concurrently": "^9.0.1",
161
+ "@vitejs/plugin-react-swc": "^3.7.2",
162
+ "browserstack-local": "^1.5.6",
163
+ "chromatic": "^11.22.2",
164
+ "concurrently": "^9.1.2",
169
165
  "conventional-changelog-cli": "^5.0.0",
170
- "dotenv": "^16.4.5",
171
- "eslint": "^9.14.0",
166
+ "dotenv": "^16.4.7",
167
+ "eslint": "^9.18.0",
172
168
  "eslint-config-prettier": "^9.1.0",
173
169
  "eslint-plugin-prettier": "^5.2.1",
174
- "eslint-plugin-react": "^7.37.2",
175
- "eslint-plugin-react-hooks": "^5.0.0",
170
+ "eslint-plugin-react": "^7.37.4",
171
+ "eslint-plugin-react-hooks": "^5.1.0",
176
172
  "git-cz": "^4.9.0",
177
- "globals": "^15.11.0",
178
- "husky": "^9.1.6",
173
+ "globals": "^15.14.0",
174
+ "husky": "^9.1.7",
179
175
  "immer": "^10.1.1",
180
- "lint-staged": "^15.2.10",
176
+ "lint-staged": "^15.3.0",
181
177
  "pinst": "^3.0.0",
182
- "playwright-core": "^1.48.0",
183
- "prettier": "^3.3.3",
178
+ "playwright-core": "^1.49.1",
179
+ "prettier": "^3.4.2",
184
180
  "react": "^18.3.1",
185
181
  "react-dom": "^18.3.1",
186
182
  "react-is": "^18.3.1",
187
- "selenium-webdriver": "^4.26.0",
188
- "storybook": "^8.4.1",
183
+ "selenium-webdriver": "^4.27.0",
184
+ "storybook": "^8.4.7",
189
185
  "tmp": "^0.2.3",
190
- "typescript": "^5.6.3",
191
- "typescript-eslint": "^8.12.2",
192
- "use-immer": "^0.10.0",
193
- "vite": "^5.4.10",
194
- "vitest": "^2.1.4"
186
+ "typescript": "^5.7.3",
187
+ "typescript-eslint": "^8.19.1",
188
+ "use-immer": "^0.11.0",
189
+ "vite": "^5.4.11",
190
+ "vitest": "^2.1.8"
195
191
  },
196
192
  "config": {
197
193
  "commitizen": {
@@ -1,11 +1,11 @@
1
1
  import React, { JSX } from 'react';
2
2
  import { Loader } from '@storybook/components';
3
3
  import { styled } from '@storybook/theming';
4
- import { TestData } from '../../../types.js';
4
+ import { noop, TestData } from '../../../types.js';
5
5
  import { ResultsPage } from '../../shared/components/ResultsPage.js';
6
6
  import { getTestPath } from '../../shared/helpers.js';
7
7
  import TestSelect from './TestSelect.js';
8
- import { noop } from 'lodash';
8
+
9
9
  interface PanelProps {
10
10
  tests: TestData[];
11
11
  selectedTestId: string;
@@ -1,7 +1,14 @@
1
1
  import { Addon_TypesEnum } from '@storybook/types';
2
- import { SET_STORIES, STORY_RENDERED } from '@storybook/core-events';
3
2
  import { denormalizeStoryParameters } from '../../shared/index.js';
4
- import { CreeveyStatus, CreeveyUpdate, isDefined, TestData, TestStatus, StoriesRaw } from '../../types.js';
3
+ import {
4
+ CreeveyStatus,
5
+ CreeveyUpdate,
6
+ isDefined,
7
+ TestData,
8
+ TestStatus,
9
+ StoriesRaw,
10
+ StorybookEvents,
11
+ } from '../../types.js';
5
12
  import { initCreeveyClientApi, CreeveyClientApi } from '../shared/creeveyClientApi.js';
6
13
  import { calcStatus } from '../shared/helpers.js';
7
14
  import { getEmojiByTestStatus } from './utils.js';
@@ -25,8 +32,8 @@ export class CreeveyController {
25
32
  this.storybookApi = storybookApi;
26
33
  }
27
34
  initAll = async (): Promise<void> => {
28
- this.storybookApi.on(STORY_RENDERED, this.onStoryRendered);
29
- this.storybookApi.on(SET_STORIES, this.onSetStories);
35
+ this.storybookApi.on(StorybookEvents.STORY_RENDERED, this.onStoryRendered);
36
+ this.storybookApi.on(StorybookEvents.SET_STORIES, this.onSetStories);
30
37
  this.creeveyApi = await initCreeveyClientApi();
31
38
  this.creeveyApi.onUpdate(this.handleCreeveyUpdate);
32
39
  this.status = await this.creeveyApi.status;
@@ -93,7 +100,7 @@ export class CreeveyController {
93
100
  this.stories = prevStories;
94
101
  this.setPanelsTitle();
95
102
  // TODO Check setStories method in 6.x and migrate properly
96
- this.storybookApi.emit(SET_STORIES, this.stories);
103
+ this.storybookApi.emit(StorybookEvents.SET_STORIES, this.stories);
97
104
  }
98
105
  this.updateStatusListeners.forEach((x) => {
99
106
  x(update);
@@ -213,7 +220,7 @@ export class CreeveyController {
213
220
  });
214
221
 
215
222
  // TODO Check setStories method in 6.x and migrate properly
216
- this.storybookApi.emit(SET_STORIES, this.stories);
223
+ this.storybookApi.emit(StorybookEvents.SET_STORIES, this.stories);
217
224
  }
218
225
 
219
226
  addStatusToStoryName(name: string, status: TestStatus | undefined, skip: string | boolean): string {
@@ -1,13 +1,22 @@
1
- import * as Events from '@storybook/core-events';
2
1
  import type { Renderer, StoryContextForEnhancers } from '@storybook/csf';
3
2
  import { makeDecorator, PreviewWeb, StoryStore } from '@storybook/preview-api';
4
3
  import { Channel } from '@storybook/channels';
5
- import { CaptureOptions, CreeveyStoryParams, isObject, noop, StoriesRaw, StorybookGlobals } from '../../types.js';
4
+ import {
5
+ CaptureOptions,
6
+ CreeveyStoryParams,
7
+ isObject,
8
+ noop,
9
+ StoriesRaw,
10
+ StorybookEvents,
11
+ StorybookGlobals,
12
+ } from '../../types.js';
6
13
  import { serializeRawStories } from '../../shared/index.js';
7
14
  import { getConnectionUrl } from '../shared/helpers.js';
15
+ import isEqual from 'lodash/isEqual.js';
8
16
 
9
17
  declare global {
10
18
  interface Window {
19
+ __CREEVEY_ENV__: boolean;
11
20
  __CREEVEY_SERVER_HOST__: string;
12
21
  __CREEVEY_SERVER_PORT__: number;
13
22
  __CREEVEY_WORKER_ID__: number;
@@ -62,12 +71,12 @@ function catchRenderError(channel: Channel): Promise<void> & { cancel: () => voi
62
71
  rejectCallback(exception);
63
72
  }
64
73
  function removeHandlers(): void {
65
- channel.off(Events.STORY_ERRORED, errorHandler);
66
- channel.off(Events.STORY_THREW_EXCEPTION, errorHandler);
74
+ channel.off(StorybookEvents.STORY_ERRORED, errorHandler);
75
+ channel.off(StorybookEvents.STORY_THREW_EXCEPTION, errorHandler);
67
76
  }
68
77
 
69
- channel.once(Events.STORY_ERRORED, errorHandler);
70
- channel.once(Events.STORY_THREW_EXCEPTION, exceptionHandler);
78
+ channel.once(StorybookEvents.STORY_ERRORED, errorHandler);
79
+ channel.once(StorybookEvents.STORY_THREW_EXCEPTION, exceptionHandler);
71
80
 
72
81
  return Object.assign(promise, { cancel: removeHandlers });
73
82
  }
@@ -79,10 +88,10 @@ function waitForStoryRendered(channel: Channel): Promise<void> & { cancel: () =>
79
88
  resolveCallback();
80
89
  }
81
90
  function removeHandlers(): void {
82
- channel.off(Events.STORY_RENDERED, renderHandler);
91
+ channel.off(StorybookEvents.STORY_RENDERED, renderHandler);
83
92
  }
84
93
 
85
- channel.once(Events.STORY_RENDERED, renderHandler);
94
+ channel.once(StorybookEvents.STORY_RENDERED, renderHandler);
86
95
 
87
96
  return Object.assign(promise, { cancel: removeHandlers });
88
97
  }
@@ -132,6 +141,7 @@ let captureResolver: () => void;
132
141
  let waitForCreevey: Promise<void>;
133
142
  let creeveyReady: () => void;
134
143
  let setStoriesCounter = 0;
144
+ let globals = {};
135
145
 
136
146
  export function withCreevey(): ReturnType<typeof makeDecorator> {
137
147
  const addonsChannel = (): Channel => window.__STORYBOOK_ADDONS_CHANNEL__;
@@ -166,7 +176,7 @@ export function withCreevey(): ReturnType<typeof makeDecorator> {
166
176
  return stories;
167
177
  }
168
178
 
169
- // TODO Use Events.STORY_RENDER_PHASE_CHANGED: `loading/rendering/completed` with storyId
179
+ // TODO Use StorybookEvents.STORY_RENDER_PHASE_CHANGED: `loading/rendering/completed` with storyId
170
180
  // TODO Check other statuses and statuses with play function
171
181
  async function selectStory(
172
182
  storyId: string,
@@ -188,8 +198,8 @@ export function withCreevey(): ReturnType<typeof makeDecorator> {
188
198
  const capturePromise = waitForCaptureCall().then(() => (isCaptureCalled = true));
189
199
 
190
200
  setTimeout(() => {
191
- if (storyId == currentStory) channel.emit(Events.FORCE_REMOUNT, { storyId });
192
- else channel.emit(Events.SET_CURRENT_STORY, { storyId });
201
+ if (storyId == currentStory) channel.emit(StorybookEvents.FORCE_REMOUNT, { storyId });
202
+ else channel.emit(StorybookEvents.SET_CURRENT_STORY, { storyId });
193
203
  }, 0);
194
204
 
195
205
  try {
@@ -218,8 +228,11 @@ export function withCreevey(): ReturnType<typeof makeDecorator> {
218
228
  }
219
229
  }
220
230
 
221
- function updateGlobals(globals: StorybookGlobals): void {
222
- addonsChannel().emit(Events.UPDATE_GLOBALS, { globals });
231
+ function updateGlobals(newGlobals: StorybookGlobals): void {
232
+ if (isEqual(globals, newGlobals)) return;
233
+
234
+ globals = newGlobals;
235
+ addonsChannel().emit(StorybookEvents.UPDATE_GLOBALS, { globals });
223
236
  }
224
237
 
225
238
  function insertIgnoreStyles(ignoreSelectors: string[]): HTMLStyleElement {
@@ -267,6 +280,7 @@ export function withCreevey(): ReturnType<typeof makeDecorator> {
267
280
  });
268
281
  }
269
282
 
283
+ window.__CREEVEY_ENV__ = false;
270
284
  window.__CREEVEY_GET_STORIES__ = getStories;
271
285
  window.__CREEVEY_SELECT_STORY__ = selectStory;
272
286
  window.__CREEVEY_UPDATE_GLOBALS__ = updateGlobals;
@@ -46,6 +46,24 @@ export const SwapView = withTheme(({ theme, expect, actual, diff }: ViewPropsWit
46
46
  setImage((prevImage) => (prevImage == 'actual' ? 'expect' : 'actual'));
47
47
  }, []);
48
48
 
49
+ const handleKeyDown = useCallback(
50
+ (e: KeyboardEvent) => {
51
+ if (e.code === 'Space' && e.altKey) {
52
+ e.preventDefault();
53
+ handleChangeView();
54
+ }
55
+ },
56
+ [handleChangeView],
57
+ );
58
+
59
+ useEffect(() => {
60
+ document.addEventListener('keydown', handleKeyDown, false);
61
+
62
+ return () => {
63
+ document.removeEventListener('keydown', handleKeyDown, false);
64
+ };
65
+ }, [handleKeyDown]);
66
+
49
67
  useEffect(() => {
50
68
  if (loaded) readyForCapture();
51
69
  }, [loaded]);
@@ -70,6 +70,7 @@ export const ImagePreview = withTheme(
70
70
  onClick(imageName);
71
71
  };
72
72
 
73
+ // TODO Add image name as a title
73
74
  return (
74
75
  <Button
75
76
  onClick={handleClick}
@@ -1,11 +1,11 @@
1
- import React, { JSX, useState } from 'react';
1
+ import React, { JSX, useCallback, useEffect, useState } from 'react';
2
2
  import { Placeholder, ScrollArea } from '@storybook/components';
3
3
  import { styled, withTheme, Theme } from '@storybook/theming';
4
4
  import { ImagesView } from './ImagesView/ImagesView.js';
5
5
  import { PageHeader } from './PageHeader/PageHeader.js';
6
6
  import { PageFooter } from './PageFooter/PageFooter.js';
7
7
  import { getImageUrl } from '../helpers.js';
8
- import { getViewMode, VIEW_MODE_KEY } from '../viewMode.js';
8
+ import { getViewMode, VIEW_MODE_KEY, viewModes } from '../viewMode.js';
9
9
  import { ImagesViewMode, TestResult } from '../../../types.js';
10
10
 
11
11
  interface ResultsPageProps {
@@ -77,10 +77,31 @@ export function ResultsPageInternal({
77
77
  )
78
78
  : [];
79
79
 
80
- const handleChangeViewMode = (mode: ImagesViewMode): void => {
81
- localStorage.setItem(VIEW_MODE_KEY, mode);
82
- setViewMode(mode);
83
- };
80
+ const handleKeyDown = useCallback(
81
+ (e: KeyboardEvent) => {
82
+ if (!canApprove) return;
83
+ if (e.code === 'Tab') {
84
+ e.preventDefault();
85
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
86
+ if (e.shiftKey) setViewMode((mode) => viewModes.at((viewModes.indexOf(mode) - 1) % viewModes.length)!);
87
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
88
+ else setViewMode((mode) => viewModes.at((viewModes.indexOf(mode) + 1) % viewModes.length)!);
89
+ }
90
+ },
91
+ [canApprove],
92
+ );
93
+
94
+ useEffect(() => {
95
+ localStorage.setItem(VIEW_MODE_KEY, viewMode);
96
+ }, [viewMode]);
97
+
98
+ useEffect(() => {
99
+ document.addEventListener('keydown', handleKeyDown, false);
100
+
101
+ return () => {
102
+ document.removeEventListener('keydown', handleKeyDown, false);
103
+ };
104
+ }, [handleKeyDown]);
84
105
 
85
106
  return (
86
107
  <Container height={height}>
@@ -92,7 +113,7 @@ export function ResultsPageInternal({
92
113
  errorMessage={result.error}
93
114
  showViewModes={hasDiffAndExpect}
94
115
  viewMode={viewMode}
95
- onViewModeChange={handleChangeViewMode}
116
+ onViewModeChange={setViewMode}
96
117
  onImageChange={onImageChange}
97
118
  imagesWithError={imagesWithError}
98
119
  />
@@ -1,4 +1,3 @@
1
- import { themes, ThemeVars } from '@storybook/theming';
2
1
  import { parse, stringify } from 'qs';
3
2
  import { RefObject, useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
4
3
  import { TestData, isTest, isDefined, TestStatus, CreeveySuite, CreeveyTest, CreeveyStatus } from '../../types.js';
@@ -393,27 +392,6 @@ export function useCalcScale(diffImageRef: RefObject<HTMLImageElement>, loaded:
393
392
  return scale;
394
393
  }
395
394
 
396
- const CREEVEY_THEME = 'Creevey_theme';
397
-
398
- function isTheme(theme?: string | null): theme is ThemeVars['base'] {
399
- return isDefined(theme) && Object.prototype.hasOwnProperty.call(themes, theme);
400
- }
401
-
402
- function initialTheme(): ThemeVars['base'] {
403
- const theme = localStorage.getItem(CREEVEY_THEME);
404
- return isTheme(theme) ? theme : 'light';
405
- }
406
-
407
- export function useTheme(): [ThemeVars['base'], (theme: ThemeVars['base']) => void] {
408
- const [theme, setTheme] = useState<ThemeVars['base']>(initialTheme());
409
-
410
- useEffect(() => {
411
- localStorage.setItem(CREEVEY_THEME, theme);
412
- }, [theme]);
413
-
414
- return [theme, setTheme];
415
- }
416
-
417
395
  export function setSearchParams(testPath: string[]): void {
418
396
  const pageUrl = `?${stringify({ testPath })}`;
419
397
  window.history.pushState({ testPath }, '', pageUrl);