creevey 0.9.0-beta.1 → 0.9.0-beta.10.timeouts.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 (221) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.md +9 -1
  3. package/addon/README.md +3 -0
  4. package/addon/package.json +5 -0
  5. package/docs/config.md +29 -26
  6. package/jest.config.js +6 -0
  7. package/lib/cjs/cli.js +5 -0
  8. package/lib/cjs/client/addon/Manager.js +264 -0
  9. package/lib/cjs/client/addon/components/Addon.js +55 -0
  10. package/lib/cjs/client/addon/components/Icons.js +46 -0
  11. package/lib/cjs/client/addon/components/Panel.js +72 -0
  12. package/lib/cjs/client/addon/components/TestSelect.js +65 -0
  13. package/lib/cjs/client/addon/components/Tools.js +95 -0
  14. package/lib/cjs/client/addon/decorator.js +11 -0
  15. package/lib/cjs/client/addon/index.js +31 -0
  16. package/lib/cjs/client/addon/preset.ie11.js +74 -0
  17. package/lib/cjs/client/addon/preset.js +17 -0
  18. package/lib/cjs/client/addon/preset.sb7.js +19 -0
  19. package/lib/cjs/client/addon/preview.js +14 -0
  20. package/lib/cjs/client/addon/readyForCapture.js +12 -0
  21. package/lib/cjs/client/addon/register.js +72 -0
  22. package/lib/cjs/client/addon/utils.js +42 -0
  23. package/lib/cjs/client/addon/withCreevey.js +351 -0
  24. package/lib/cjs/client/shared/components/ImagesView/BlendView.js +87 -0
  25. package/lib/cjs/client/shared/components/ImagesView/ImagesView.js +92 -0
  26. package/lib/cjs/client/shared/components/ImagesView/SideBySideView.js +154 -0
  27. package/lib/cjs/client/shared/components/ImagesView/SlideView.js +166 -0
  28. package/lib/cjs/client/shared/components/ImagesView/SwapView.js +91 -0
  29. package/lib/cjs/client/shared/components/ImagesView/index.js +45 -0
  30. package/lib/cjs/client/shared/components/PageFooter/PageFooter.js +50 -0
  31. package/lib/cjs/client/shared/components/PageFooter/Paging.js +94 -0
  32. package/lib/cjs/client/shared/components/PageHeader/ImagePreview.js +82 -0
  33. package/lib/cjs/client/shared/components/PageHeader/PageHeader.js +119 -0
  34. package/lib/cjs/client/shared/components/ResultsPage.js +143 -0
  35. package/lib/cjs/client/shared/creeveyClientApi.js +76 -0
  36. package/lib/cjs/client/shared/helpers.js +411 -0
  37. package/lib/cjs/client/shared/viewMode.js +17 -0
  38. package/lib/cjs/client/web/142.js +2 -0
  39. package/lib/cjs/client/web/142.js.LICENSE.txt +12 -0
  40. package/lib/cjs/client/web/32.js +1 -0
  41. package/lib/cjs/client/web/551.js +1 -0
  42. package/lib/cjs/client/web/566.js +2 -0
  43. package/lib/cjs/client/web/566.js.LICENSE.txt +31 -0
  44. package/lib/cjs/client/web/691.js +2 -0
  45. package/lib/cjs/client/web/691.js.LICENSE.txt +8 -0
  46. package/lib/cjs/client/web/725.js +1 -0
  47. package/lib/cjs/client/web/index.html +19 -0
  48. package/lib/cjs/client/web/main.js +2 -38
  49. package/lib/cjs/client/web/main.js.LICENSE.txt +49 -0
  50. package/lib/cjs/creevey.js +69 -0
  51. package/lib/cjs/index.js +62 -0
  52. package/lib/cjs/server/config.js +94 -0
  53. package/lib/cjs/server/docker.js +146 -0
  54. package/lib/cjs/server/extract.js +46 -0
  55. package/lib/cjs/server/index.js +83 -0
  56. package/lib/cjs/server/loaders/babel/creevey-plugin.js +86 -0
  57. package/lib/cjs/server/loaders/babel/helpers.js +469 -0
  58. package/lib/cjs/server/loaders/babel/register.js +124 -0
  59. package/lib/cjs/server/loaders/hooks/mdx.js +30 -0
  60. package/lib/cjs/server/loaders/hooks/svelte.js +65 -0
  61. package/lib/cjs/server/loaders/webpack/compile.js +269 -0
  62. package/lib/cjs/server/loaders/webpack/creevey-loader.js +172 -0
  63. package/lib/cjs/server/loaders/webpack/dummy-hmr.js +39 -0
  64. package/lib/cjs/server/loaders/webpack/mdx-loader.js +72 -0
  65. package/lib/cjs/server/loaders/webpack/start.js +41 -0
  66. package/lib/cjs/server/logger.js +48 -0
  67. package/lib/cjs/server/master/api.js +71 -0
  68. package/lib/cjs/server/master/index.js +146 -0
  69. package/lib/cjs/server/master/master.js +57 -0
  70. package/lib/cjs/server/master/pool.js +197 -0
  71. package/lib/cjs/server/master/runner.js +281 -0
  72. package/lib/cjs/server/master/server.js +131 -0
  73. package/lib/cjs/server/messages.js +264 -0
  74. package/lib/cjs/server/selenium/browser.js +671 -0
  75. package/lib/cjs/server/selenium/index.js +31 -0
  76. package/lib/cjs/server/selenium/selenoid.js +172 -0
  77. package/lib/cjs/server/stories.js +153 -0
  78. package/lib/cjs/server/storybook/entry.js +53 -0
  79. package/lib/cjs/server/storybook/helpers.js +158 -0
  80. package/lib/cjs/server/storybook/providers/browser.js +74 -0
  81. package/lib/cjs/server/storybook/providers/hybrid.js +82 -0
  82. package/lib/cjs/server/storybook/providers/nodejs.js +239 -0
  83. package/lib/cjs/server/testsFiles/parser.js +72 -0
  84. package/lib/cjs/server/testsFiles/register.js +44 -0
  85. package/lib/cjs/server/update.js +79 -0
  86. package/lib/cjs/server/utils.js +176 -0
  87. package/lib/cjs/server/worker/chai-image.js +142 -0
  88. package/lib/cjs/server/worker/helpers.js +69 -0
  89. package/lib/cjs/server/worker/index.js +15 -0
  90. package/lib/cjs/server/worker/reporter.js +108 -0
  91. package/lib/cjs/server/worker/worker.js +268 -0
  92. package/lib/cjs/shared/index.js +101 -0
  93. package/lib/cjs/shared/serializeRegExp.js +42 -0
  94. package/lib/cjs/types.js +75 -0
  95. package/lib/esm/cli.js +4 -0
  96. package/lib/esm/client/addon/Manager.js +248 -0
  97. package/lib/esm/client/addon/components/Addon.js +39 -0
  98. package/lib/esm/client/addon/components/Icons.js +31 -0
  99. package/lib/esm/client/addon/components/Panel.js +53 -0
  100. package/lib/esm/client/addon/components/TestSelect.js +51 -0
  101. package/lib/esm/client/addon/components/Tools.js +74 -0
  102. package/lib/esm/client/addon/decorator.js +2 -0
  103. package/lib/esm/client/addon/index.js +2 -0
  104. package/lib/esm/client/addon/preset.ie11.js +59 -0
  105. package/lib/esm/client/addon/preset.js +8 -0
  106. package/lib/esm/client/addon/preset.sb7.js +8 -0
  107. package/lib/esm/client/addon/preview.js +5 -0
  108. package/lib/esm/client/addon/readyForCapture.js +5 -0
  109. package/lib/esm/client/addon/register.js +51 -0
  110. package/lib/esm/client/addon/utils.js +32 -0
  111. package/lib/esm/client/addon/withCreevey.js +325 -0
  112. package/lib/esm/client/shared/components/ImagesView/BlendView.js +67 -0
  113. package/lib/esm/client/shared/components/ImagesView/ImagesView.js +69 -0
  114. package/lib/esm/client/shared/components/ImagesView/SideBySideView.js +131 -0
  115. package/lib/esm/client/shared/components/ImagesView/SlideView.js +143 -0
  116. package/lib/esm/client/shared/components/ImagesView/SwapView.js +71 -0
  117. package/lib/esm/client/shared/components/ImagesView/index.js +5 -0
  118. package/lib/esm/client/shared/components/PageFooter/PageFooter.js +36 -0
  119. package/lib/esm/client/shared/components/PageFooter/Paging.js +80 -0
  120. package/lib/esm/client/shared/components/PageHeader/ImagePreview.js +68 -0
  121. package/lib/esm/client/shared/components/PageHeader/PageHeader.js +97 -0
  122. package/lib/esm/client/shared/components/ResultsPage.js +115 -0
  123. package/lib/esm/client/shared/creeveyClientApi.js +67 -0
  124. package/lib/esm/client/shared/helpers.js +353 -0
  125. package/lib/esm/client/shared/viewMode.js +6 -0
  126. package/lib/esm/creevey.js +54 -0
  127. package/lib/esm/index.js +5 -0
  128. package/lib/esm/server/config.js +71 -0
  129. package/lib/esm/server/docker.js +123 -0
  130. package/lib/esm/server/extract.js +32 -0
  131. package/lib/esm/server/index.js +64 -0
  132. package/lib/esm/server/loaders/babel/creevey-plugin.js +72 -0
  133. package/lib/esm/server/loaders/babel/helpers.js +452 -0
  134. package/lib/esm/server/loaders/babel/register.js +103 -0
  135. package/lib/esm/server/loaders/hooks/mdx.js +15 -0
  136. package/lib/esm/server/loaders/hooks/svelte.js +49 -0
  137. package/lib/esm/server/loaders/webpack/compile.js +246 -0
  138. package/lib/esm/server/loaders/webpack/creevey-loader.js +152 -0
  139. package/lib/esm/server/loaders/webpack/dummy-hmr.js +32 -0
  140. package/lib/esm/server/loaders/webpack/mdx-loader.js +58 -0
  141. package/lib/esm/server/loaders/webpack/start.js +27 -0
  142. package/lib/esm/server/logger.js +20 -0
  143. package/lib/esm/server/master/api.js +60 -0
  144. package/lib/esm/server/master/index.js +125 -0
  145. package/lib/esm/server/master/master.js +38 -0
  146. package/lib/esm/server/master/pool.js +176 -0
  147. package/lib/esm/server/master/runner.js +259 -0
  148. package/lib/esm/server/master/server.js +107 -0
  149. package/lib/esm/server/messages.js +232 -0
  150. package/lib/esm/server/selenium/browser.js +638 -0
  151. package/lib/esm/server/selenium/index.js +2 -0
  152. package/lib/esm/server/selenium/selenoid.js +149 -0
  153. package/lib/esm/server/stories.js +135 -0
  154. package/lib/esm/server/storybook/entry.js +27 -0
  155. package/lib/esm/server/storybook/helpers.js +97 -0
  156. package/lib/esm/server/storybook/providers/browser.js +58 -0
  157. package/lib/esm/server/storybook/providers/hybrid.js +60 -0
  158. package/lib/esm/server/storybook/providers/nodejs.js +216 -0
  159. package/lib/esm/server/testsFiles/parser.js +50 -0
  160. package/lib/esm/server/testsFiles/register.js +31 -0
  161. package/lib/esm/server/update.js +61 -0
  162. package/lib/esm/server/utils.js +133 -0
  163. package/lib/esm/server/worker/chai-image.js +130 -0
  164. package/lib/esm/server/worker/helpers.js +60 -0
  165. package/lib/esm/server/worker/index.js +1 -0
  166. package/lib/esm/server/worker/reporter.js +86 -0
  167. package/lib/esm/server/worker/worker.js +238 -0
  168. package/lib/esm/shared/index.js +78 -0
  169. package/lib/esm/shared/serializeRegExp.js +24 -0
  170. package/lib/esm/types.js +44 -0
  171. package/lib/types/client/addon/Manager.d.ts +2 -2
  172. package/lib/types/client/addon/components/TestSelect.d.ts +0 -1
  173. package/lib/types/client/addon/index.d.ts +2 -0
  174. package/lib/types/client/addon/preset.d.ts +0 -22
  175. package/lib/types/client/addon/preset.ie11.d.ts +10 -0
  176. package/lib/types/client/addon/preset.sb7.d.ts +2 -0
  177. package/lib/types/client/addon/preview.d.ts +4 -0
  178. package/lib/types/client/addon/utils.d.ts +1 -0
  179. package/lib/types/client/addon/withCreevey.d.ts +1 -1
  180. package/lib/types/client/shared/components/ImagesView/BlendView.d.ts +1 -1
  181. package/lib/types/client/shared/components/ImagesView/ImagesView.d.ts +0 -1
  182. package/lib/types/client/shared/components/ImagesView/SideBySideView.d.ts +1 -1
  183. package/lib/types/client/shared/components/ImagesView/SlideView.d.ts +1 -1
  184. package/lib/types/client/shared/components/ImagesView/SwapView.d.ts +1 -1
  185. package/lib/types/client/shared/components/PageFooter/PageFooter.d.ts +0 -1
  186. package/lib/types/client/shared/components/PageFooter/Paging.d.ts +0 -1
  187. package/lib/types/client/shared/components/PageHeader/ImagePreview.d.ts +1 -1
  188. package/lib/types/client/shared/components/PageHeader/PageHeader.d.ts +0 -1
  189. package/lib/types/client/shared/components/ResultsPage.d.ts +1 -1
  190. package/lib/types/client/web/CreeveyApp.d.ts +0 -1
  191. package/lib/types/client/web/CreeveyLoader.d.ts +1 -2
  192. package/lib/types/client/web/CreeveyView/SideBar/Checkbox.d.ts +1 -1
  193. package/lib/types/client/web/CreeveyView/SideBar/SideBarHeader.d.ts +0 -1
  194. package/lib/types/client/web/CreeveyView/SideBar/SuiteLink.d.ts +4 -4
  195. package/lib/types/client/web/CreeveyView/SideBar/TestLink.d.ts +0 -1
  196. package/lib/types/client/web/CreeveyView/SideBar/TestStatusIcon.d.ts +1 -1
  197. package/lib/types/client/web/CreeveyView/SideBar/TestsStatus.d.ts +1 -1
  198. package/lib/types/index.d.ts +1 -0
  199. package/lib/types/server/loaders/babel/register.d.ts +1 -1
  200. package/lib/types/server/loaders/webpack/creevey-loader.d.ts +4 -2
  201. package/lib/types/server/logger.d.ts +6 -2
  202. package/lib/types/server/messages.d.ts +14 -12
  203. package/lib/types/server/selenium/browser.d.ts +5 -3
  204. package/lib/types/server/storybook/entry.d.ts +2 -3
  205. package/lib/types/server/storybook/helpers.d.ts +1 -1
  206. package/lib/types/server/storybook/providers/browser.d.ts +2 -4
  207. package/lib/types/server/storybook/providers/hybrid.d.ts +2 -4
  208. package/lib/types/server/storybook/providers/nodejs.d.ts +3 -3
  209. package/lib/types/server/utils.d.ts +5 -1
  210. package/lib/types/{shared.d.ts → shared/index.d.ts} +1 -10
  211. package/lib/types/shared/serializeRegExp.d.ts +9 -0
  212. package/lib/types/types.d.ts +4 -7
  213. package/package.json +117 -103
  214. package/preset/ie11.js +5 -0
  215. package/{preset.js → preset/index.js} +2 -2
  216. package/preset/sb7.js +5 -0
  217. package/types/global.d.ts +5 -0
  218. package/types/mdx.d.ts +3 -2
  219. package/lib/cjs/client/web/1.js +0 -13
  220. package/lib/cjs/client/web/2.js +0 -1
  221. package/storybook-static/stories.json +0 -21
@@ -0,0 +1,143 @@
1
+ import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
2
+ import { styled, withTheme } from '@storybook/theming';
3
+ import { getBorderColor, themeBorderColors } from './ImagesView';
4
+ import { useApplyScale, useCalcScale, useLoadImages } from '../../helpers';
5
+ import { Loader } from '@storybook/components';
6
+ import { readyForCapture } from '../../../addon/readyForCapture';
7
+ const Container = styled.div({
8
+ position: 'relative',
9
+ display: 'flex'
10
+ });
11
+ const Input = styled.input({
12
+ position: 'absolute',
13
+ cursor: 'ew-resize',
14
+ appearance: 'none',
15
+ background: 'none',
16
+ boxShadow: 'none',
17
+ outline: 'none',
18
+ height: '100%',
19
+ width: '100%',
20
+ margin: '0',
21
+ zIndex: 1,
22
+ '&::-webkit-slider-runnable-track': {
23
+ height: '100%'
24
+ },
25
+ '&::-webkit-slider-thumb': {
26
+ boxShadow: '0 0 0 0.5px #888',
27
+ height: '100%',
28
+ width: '0px',
29
+ appearance: 'none'
30
+ },
31
+ '&::-moz-focus-outer': {
32
+ border: '0'
33
+ },
34
+ '&::-moz-range-track': {
35
+ height: '0'
36
+ },
37
+ '&::-moz-range-thumb': {
38
+ border: 'none',
39
+ boxShadow: '0 0 0 0.5px #888',
40
+ height: '100%',
41
+ width: '0px'
42
+ }
43
+ });
44
+ const ImageContainer = styled.div({
45
+ position: 'absolute',
46
+ width: '100%',
47
+ height: '100%',
48
+ overflow: 'hidden'
49
+ });
50
+ const ImageWrapper = withTheme(styled.div(_ref => {
51
+ let {
52
+ theme
53
+ } = _ref;
54
+ return {
55
+ background: theme.base == 'light' ? theme.color.mediumlight : theme.color.darker,
56
+ position: 'relative',
57
+ width: '100%',
58
+ height: '100%',
59
+ display: 'flex'
60
+ };
61
+ }));
62
+ const BaseImage = styled.img(_ref2 => {
63
+ let {
64
+ borderColor
65
+ } = _ref2;
66
+ return {
67
+ boxSizing: 'border-box',
68
+ border: "1px solid ".concat(borderColor),
69
+ maxWidth: '100%'
70
+ };
71
+ });
72
+ const Image = styled(BaseImage)({
73
+ position: 'absolute'
74
+ });
75
+ const DiffImage = styled(BaseImage)({
76
+ opacity: '0'
77
+ });
78
+ export const SlideView = withTheme(_ref3 => {
79
+ let {
80
+ actual,
81
+ diff,
82
+ expect,
83
+ theme
84
+ } = _ref3;
85
+ const [step, setStep] = useState(0);
86
+ const expectedImageContainerRef = useRef(null);
87
+ const expectedImageWrapperRef = useRef(null);
88
+ const expectImageRef = useRef(null);
89
+ const diffImageRef = useRef(null);
90
+ const actualImageRef = useRef(null);
91
+ const loaded = useLoadImages(expect, diff, actual);
92
+ const scale = useCalcScale(diffImageRef, loaded);
93
+ useApplyScale(expectImageRef, scale);
94
+ useApplyScale(actualImageRef, scale);
95
+ const handleSlide = useCallback(event => {
96
+ if (!expectedImageContainerRef.current || !expectedImageWrapperRef.current) return;
97
+ const offset = Number(event.target.value);
98
+ expectedImageContainerRef.current.style.right = "".concat(100 - offset, "%");
99
+ expectedImageWrapperRef.current.style.left = "".concat(100 - offset, "%");
100
+ }, []);
101
+ useLayoutEffect(() => {
102
+ if (loaded && diffImageRef.current) setStep(100 / diffImageRef.current.getBoundingClientRect().width);
103
+ }, [loaded, scale]);
104
+ useLayoutEffect(() => {
105
+ if (loaded && expectedImageContainerRef.current && expectedImageWrapperRef.current) {
106
+ expectedImageContainerRef.current.style.right = '100%';
107
+ expectedImageWrapperRef.current.style.left = '100%';
108
+ }
109
+ }, [loaded]);
110
+ useEffect(() => {
111
+ if (loaded) readyForCapture();
112
+ }, [loaded]);
113
+ return loaded ? /*#__PURE__*/React.createElement(Container, null, /*#__PURE__*/React.createElement(Input, {
114
+ "data-testid": "slider",
115
+ type: "range",
116
+ min: 0,
117
+ max: 100,
118
+ defaultValue: 0,
119
+ step: step,
120
+ onChange: handleSlide
121
+ }), /*#__PURE__*/React.createElement(ImageContainer, null, /*#__PURE__*/React.createElement(ImageWrapper, null, /*#__PURE__*/React.createElement(Image, {
122
+ ref: actualImageRef,
123
+ borderColor: getBorderColor(theme, themeBorderColors.actual),
124
+ alt: "actual",
125
+ src: actual
126
+ }))), /*#__PURE__*/React.createElement(ImageContainer, {
127
+ ref: expectedImageContainerRef
128
+ }, /*#__PURE__*/React.createElement(ImageWrapper, {
129
+ ref: expectedImageWrapperRef
130
+ }, /*#__PURE__*/React.createElement(Image, {
131
+ ref: expectImageRef,
132
+ borderColor: getBorderColor(theme, themeBorderColors.expect),
133
+ alt: "expect",
134
+ src: expect
135
+ }))), /*#__PURE__*/React.createElement(DiffImage, {
136
+ ref: diffImageRef,
137
+ borderColor: 'transparent',
138
+ alt: "diff",
139
+ src: diff
140
+ })) : /*#__PURE__*/React.createElement(Loader, {
141
+ size: 64
142
+ });
143
+ });
@@ -0,0 +1,71 @@
1
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
2
+ import { getBorderColor, themeBorderColors } from './ImagesView';
3
+ import { styled, withTheme } from '@storybook/theming';
4
+ import { useApplyScale, useCalcScale, useLoadImages } from '../../helpers';
5
+ import { Loader } from '@storybook/components';
6
+ import { readyForCapture } from '../../../addon/readyForCapture';
7
+ const Container = styled.div({
8
+ position: 'relative',
9
+ display: 'flex'
10
+ });
11
+ const BaseImage = styled.img(_ref => {
12
+ let {
13
+ borderColor
14
+ } = _ref;
15
+ return {
16
+ boxSizing: 'border-box',
17
+ border: "1px solid ".concat(borderColor),
18
+ maxWidth: '100%'
19
+ };
20
+ });
21
+ const Image = styled(BaseImage)({
22
+ position: 'absolute'
23
+ });
24
+ const DiffImage = styled(BaseImage)({
25
+ cursor: 'pointer',
26
+ outline: 'none',
27
+ opacity: 0,
28
+ zIndex: 1
29
+ });
30
+ export const SwapView = withTheme(_ref2 => {
31
+ let {
32
+ theme,
33
+ expect,
34
+ actual,
35
+ diff
36
+ } = _ref2;
37
+ const [image, setImage] = useState('actual');
38
+ const expectImageRef = useRef(null);
39
+ const diffImageRef = useRef(null);
40
+ const actualImageRef = useRef(null);
41
+ const loaded = useLoadImages(expect, diff, actual);
42
+ const scale = useCalcScale(diffImageRef, loaded);
43
+ useApplyScale(expectImageRef, scale, image);
44
+ useApplyScale(actualImageRef, scale, image);
45
+ const handleChangeView = useCallback(() => setImage(prevImage => prevImage == 'actual' ? 'expect' : 'actual'), []);
46
+ useEffect(() => {
47
+ if (loaded) readyForCapture();
48
+ }, [loaded]);
49
+ return loaded ? /*#__PURE__*/React.createElement(Container, null, /*#__PURE__*/React.createElement(Image, {
50
+ ref: expectImageRef,
51
+ borderColor: getBorderColor(theme, themeBorderColors.expect),
52
+ alt: 'expect',
53
+ src: expect,
54
+ hidden: image != 'expect'
55
+ }), /*#__PURE__*/React.createElement(DiffImage, {
56
+ ref: diffImageRef,
57
+ borderColor: 'transparent',
58
+ tabIndex: 0,
59
+ alt: "diff",
60
+ src: diff,
61
+ onClick: handleChangeView
62
+ }), /*#__PURE__*/React.createElement(Image, {
63
+ ref: actualImageRef,
64
+ borderColor: getBorderColor(theme, themeBorderColors.actual),
65
+ alt: 'actual',
66
+ src: actual,
67
+ hidden: image != 'actual'
68
+ })) : /*#__PURE__*/React.createElement(Loader, {
69
+ size: 64
70
+ });
71
+ });
@@ -0,0 +1,5 @@
1
+ export { ImagesView } from './ImagesView';
2
+ export { BlendView } from './BlendView';
3
+ export { SideBySideView } from './SideBySideView';
4
+ export { SlideView } from './SlideView';
5
+ export { SwapView } from './SwapView';
@@ -0,0 +1,36 @@
1
+ import React from 'react';
2
+ import { Paging } from './Paging';
3
+ import { styled, withTheme } from '@storybook/theming';
4
+ import { Button } from '@storybook/components';
5
+ const Container = withTheme(styled.div(_ref => {
6
+ let {
7
+ theme
8
+ } = _ref;
9
+ return {
10
+ display: 'flex',
11
+ padding: '20px',
12
+ justifyContent: 'space-between',
13
+ background: theme.background.content
14
+ };
15
+ }));
16
+ const StyledButton = styled(Button)({
17
+ transform: 'none'
18
+ });
19
+ export function PageFooter(_ref2) {
20
+ let {
21
+ canApprove,
22
+ retriesCount,
23
+ retry,
24
+ onRetryChange,
25
+ onApprove
26
+ } = _ref2;
27
+ return /*#__PURE__*/React.createElement(Container, null, /*#__PURE__*/React.createElement(Paging, {
28
+ activePage: retry,
29
+ onPageChange: onRetryChange,
30
+ pagesCount: retriesCount
31
+ }), canApprove ? /*#__PURE__*/React.createElement(StyledButton, {
32
+ secondary: true,
33
+ outline: true,
34
+ onClick: onApprove
35
+ }, 'Approve') : null);
36
+ }
@@ -0,0 +1,80 @@
1
+ import React from 'react';
2
+ import { Button, Icons } from '@storybook/components';
3
+ import { noop } from '../../../../types';
4
+ import { styled } from '@storybook/theming';
5
+ const StyledButton = styled(Button)({
6
+ transform: 'none',
7
+ marginLeft: '8px'
8
+ });
9
+ export function Paging(props) {
10
+ const renderItem = (item, index) => {
11
+ switch (item) {
12
+ case '.':
13
+ {
14
+ return /*#__PURE__*/React.createElement(StyledButton, {
15
+ disabled: true,
16
+ key: "dots".concat(index < 5 ? 'Left' : 'Right')
17
+ }, '...');
18
+ }
19
+
20
+ case 'forward':
21
+ {
22
+ const disabled = props.activePage === props.pagesCount;
23
+ return /*#__PURE__*/React.createElement(StyledButton, {
24
+ outline: true,
25
+ disabled: disabled,
26
+ onClick: disabled ? noop : () => goToPage(props.activePage + 1),
27
+ key: "forward"
28
+ }, /*#__PURE__*/React.createElement("span", null, "Next ", /*#__PURE__*/React.createElement(Icons, {
29
+ icon: "arrowright"
30
+ })));
31
+ }
32
+
33
+ default:
34
+ {
35
+ return /*#__PURE__*/React.createElement(StyledButton, {
36
+ outline: true,
37
+ secondary: props.activePage === item,
38
+ key: item,
39
+ onClick: () => goToPage(item)
40
+ }, item);
41
+ }
42
+ }
43
+ };
44
+
45
+ const goToPage = pageNumber => {
46
+ if (1 <= pageNumber && pageNumber !== props.activePage && pageNumber <= props.pagesCount) {
47
+ props.onPageChange(pageNumber);
48
+ }
49
+ };
50
+
51
+ return /*#__PURE__*/React.createElement("div", null, getItems(props.activePage, props.pagesCount).map(renderItem));
52
+ }
53
+
54
+ function getItems(active, total) {
55
+ const result = [];
56
+ const left = Math.max(Math.min(active - 2, total - 4), 1);
57
+ const right = Math.min(Math.max(5, active + 2), total);
58
+ const hasLeftDots = left > 3;
59
+ const from = hasLeftDots ? left : 1;
60
+ const hasRightDots = right < total - 2;
61
+ const to = hasRightDots ? right : total;
62
+
63
+ if (hasLeftDots) {
64
+ result.push(1, '.');
65
+ }
66
+
67
+ for (let i = from; i <= to; ++i) {
68
+ result.push(i);
69
+ }
70
+
71
+ if (hasRightDots) {
72
+ result.push('.');
73
+ }
74
+
75
+ if (hasRightDots && isFinite(total)) {
76
+ result.push(total);
77
+ }
78
+
79
+ return result.concat('forward');
80
+ }
@@ -0,0 +1,68 @@
1
+ import React from 'react';
2
+ import { styled, withTheme } from '@storybook/theming';
3
+ const IMG_SIZE = 64;
4
+ const DIAG_LENGTH = (2 * (IMG_SIZE - 8) ** 2) ** (1 / 2);
5
+ const Button = styled.button(_ref => {
6
+ let {
7
+ borderColor
8
+ } = _ref;
9
+ return {
10
+ appearance: 'none',
11
+ background: 'none',
12
+ color: 'inherit',
13
+ font: 'inherit',
14
+ cursor: 'pointer',
15
+ outline: 'none',
16
+ zIndex: 1,
17
+ margin: '0 10px',
18
+ border: '2px solid transparent',
19
+ borderColor: borderColor || 'transparent',
20
+ '&:first-of-type': {
21
+ marginLeft: 0
22
+ }
23
+ };
24
+ });
25
+ const Image = withTheme(styled.img(_ref2 => {
26
+ let {
27
+ hasBorder,
28
+ backgroundColor,
29
+ theme
30
+ } = _ref2;
31
+ return {
32
+ maxHeight: "".concat(IMG_SIZE, "px"),
33
+ width: "".concat(IMG_SIZE, "px"),
34
+ overflow: 'hidden',
35
+ transform: hasBorder ? 'translateY(2px)' : undefined,
36
+ '&::before': {
37
+ content: "' '",
38
+ display: 'block',
39
+ height: "".concat(IMG_SIZE - 8, "px"),
40
+ width: "".concat(IMG_SIZE - 8, "px"),
41
+ margin: '4px',
42
+ backgroundColor: backgroundColor,
43
+ backgroundImage: "linear-gradient(\n 45deg,\n rgba(0, 0, 0, 0) ".concat(DIAG_LENGTH / 2 - 0.5, "px,\n ").concat(theme.color.medium, " ").concat(DIAG_LENGTH / 2 - 0.5, "px,\n ").concat(theme.color.medium, " ").concat(DIAG_LENGTH / 2 + 0.5, "px,\n rgba(0, 0, 0, 0) ").concat(DIAG_LENGTH / 2 + 0.5, "px\n ),\n linear-gradient(\n 315deg,\n rgba(0, 0, 0, 0) ").concat(DIAG_LENGTH / 2 + 0.2, "px,\n ").concat(theme.color.medium, " ").concat(DIAG_LENGTH / 2 + 0.2, "px,\n ").concat(theme.color.medium, " ").concat(DIAG_LENGTH / 2 + 1.2, "px,\n rgba(0, 0, 0, 0) ").concat(DIAG_LENGTH / 2 + 1.2, "px\n )")
44
+ }
45
+ };
46
+ }));
47
+ export const ImagePreview = withTheme(_ref3 => {
48
+ let {
49
+ isActive,
50
+ onClick,
51
+ imageName,
52
+ url,
53
+ theme,
54
+ error
55
+ } = _ref3;
56
+
57
+ const handleClick = () => onClick(imageName);
58
+
59
+ return /*#__PURE__*/React.createElement(Button, {
60
+ onClick: handleClick,
61
+ borderColor: isActive ? theme.barSelectedColor : error ? theme.color.negative : undefined
62
+ }, /*#__PURE__*/React.createElement(Image, {
63
+ hasBorder: isActive || error,
64
+ src: url,
65
+ alt: imageName,
66
+ backgroundColor: theme.background.content
67
+ }));
68
+ });
@@ -0,0 +1,97 @@
1
+ import React, { useState } from 'react';
2
+ import { getImageUrl } from '../../helpers';
3
+ import { Icons, Tabs } from '@storybook/components';
4
+ import { styled, withTheme } from '@storybook/theming';
5
+ import { ImagePreview } from './ImagePreview';
6
+ import { viewModes } from '../../viewMode';
7
+ const Container = styled.div({
8
+ margin: '24px 44px 0'
9
+ });
10
+ const ErrorContainer = withTheme(styled.div(_ref => {
11
+ let {
12
+ theme
13
+ } = _ref;
14
+ return {
15
+ marginTop: '8px',
16
+ padding: '8px',
17
+ background: theme.background.negative,
18
+ color: theme.color.negative,
19
+ borderRadius: '2px',
20
+ display: 'flex',
21
+ alignItems: 'baseline',
22
+ '& svg': {
23
+ margin: '0 5px',
24
+ width: 8,
25
+ height: 8
26
+ },
27
+ '& pre': {
28
+ margin: '0 4px',
29
+ padding: 0,
30
+ lineHeight: '22px'
31
+ }
32
+ };
33
+ }));
34
+ const H1 = styled.h1({
35
+ margin: 0,
36
+ marginBottom: '8px'
37
+ });
38
+ const HeaderDivider = withTheme(styled.span(_ref2 => {
39
+ let {
40
+ theme
41
+ } = _ref2;
42
+ return {
43
+ padding: '0 8px',
44
+ color: theme.color.mediumdark
45
+ };
46
+ }));
47
+ const ImagesEntriesContainer = styled.div({
48
+ display: 'flex',
49
+ margin: '16px 0 8px'
50
+ });
51
+ export function PageHeader(_ref3) {
52
+ var _, _imageEntires$, _images$imageName;
53
+
54
+ let {
55
+ title,
56
+ images = {},
57
+ errorMessage,
58
+ showViewModes,
59
+ showTitle,
60
+ viewMode,
61
+ imagesWithError = [],
62
+ onImageChange,
63
+ onViewModeChange
64
+ } = _ref3;
65
+ const imageEntires = Object.entries(images);
66
+ const [imageName, setImageName] = useState((_ = ((_imageEntires$ = imageEntires[0]) !== null && _imageEntires$ !== void 0 ? _imageEntires$ : [])[0]) !== null && _ !== void 0 ? _ : '');
67
+
68
+ const handleImageChange = name => (setImageName(name), onImageChange(name));
69
+
70
+ const handleViewModeChange = mode => onViewModeChange(mode);
71
+
72
+ const error = errorMessage || imagesWithError.includes(imageName) ? ((_images$imageName = images[imageName]) === null || _images$imageName === void 0 ? void 0 : _images$imageName.error) || errorMessage : null;
73
+ return showTitle || error || imageEntires.length > 1 || showViewModes ? /*#__PURE__*/React.createElement(Container, null, showTitle && /*#__PURE__*/React.createElement(H1, null, title.flatMap(token => [token, /*#__PURE__*/React.createElement(HeaderDivider, {
74
+ key: token
75
+ }, "/")]).slice(0, -1)), error && /*#__PURE__*/React.createElement(ErrorContainer, null, /*#__PURE__*/React.createElement(Icons, {
76
+ icon: "closeAlt"
77
+ }), /*#__PURE__*/React.createElement("pre", null, error)), imageEntires.length > 1 ? /*#__PURE__*/React.createElement(ImagesEntriesContainer, null, imageEntires.map(_ref4 => {
78
+ let [name, image] = _ref4;
79
+ return /*#__PURE__*/React.createElement(ImagePreview, {
80
+ key: name,
81
+ imageName: name,
82
+ url: "".concat(getImageUrl(title, name), "/").concat(image.actual),
83
+ isActive: name === imageName,
84
+ onClick: handleImageChange,
85
+ error: imagesWithError.includes(name)
86
+ });
87
+ })) : null, showViewModes && /*#__PURE__*/React.createElement(Tabs, {
88
+ selected: viewMode,
89
+ actions: {
90
+ onSelect: handleViewModeChange
91
+ }
92
+ }, viewModes.map(x => /*#__PURE__*/React.createElement("div", {
93
+ key: x,
94
+ id: x,
95
+ title: x
96
+ })))) : null;
97
+ }
@@ -0,0 +1,115 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { ImagesView } from './ImagesView/ImagesView';
3
+ import { PageHeader } from './PageHeader/PageHeader';
4
+ import { PageFooter } from './PageFooter/PageFooter';
5
+ import { getImageUrl } from '../helpers';
6
+ import { styled, withTheme } from '@storybook/theming';
7
+ import { Placeholder, ScrollArea } from '@storybook/components';
8
+ import { getViewMode, VIEW_MODE_KEY } from '../viewMode';
9
+ const Wrapper = styled.div({
10
+ width: '100%',
11
+ height: '100%',
12
+ boxSizing: 'border-box',
13
+ display: 'flex',
14
+ flexDirection: 'column'
15
+ });
16
+ const ImagesViewContainer = styled.div(_ref => {
17
+ let {
18
+ theme
19
+ } = _ref;
20
+ return {
21
+ background: theme.base == 'light' ? theme.color.mediumlight : theme.color.darker,
22
+ flexGrow: 1,
23
+ padding: '20px 0'
24
+ };
25
+ });
26
+ const HeaderContainer = styled.div({
27
+ position: 'sticky',
28
+ top: 0,
29
+ zIndex: 1
30
+ });
31
+ const BodyContainer = styled.div({
32
+ flexGrow: 1
33
+ });
34
+ const FooterContainer = styled.div({
35
+ position: 'sticky',
36
+ bottom: 0,
37
+ zIndex: 1
38
+ });
39
+ const Container = styled.div(_ref2 => {
40
+ let {
41
+ height = '100vh'
42
+ } = _ref2;
43
+ return {
44
+ height,
45
+ width: '100%',
46
+ overflowY: 'hidden',
47
+ display: 'flex',
48
+ flexDirection: 'column'
49
+ };
50
+ });
51
+ export function ResultsPageInternal(_ref3) {
52
+ var _results, _Object$keys$, _result$images, _result$images2;
53
+
54
+ let {
55
+ id,
56
+ path,
57
+ results = [],
58
+ approved = {},
59
+ theme,
60
+ onImageApprove,
61
+ showTitle = false,
62
+ height
63
+ } = _ref3;
64
+ const [retry, setRetry] = useState(results.length);
65
+ const result = (_results = results[retry - 1]) !== null && _results !== void 0 ? _results : {};
66
+ const [imageName, setImageName] = useState((_Object$keys$ = Object.keys((_result$images = result.images) !== null && _result$images !== void 0 ? _result$images : {})[0]) !== null && _Object$keys$ !== void 0 ? _Object$keys$ : '');
67
+ const [viewMode, setViewMode] = useState(getViewMode());
68
+ useEffect(() => setRetry(results.length), [results.length]);
69
+ const url = getImageUrl(path, imageName);
70
+ const image = (_result$images2 = result.images) === null || _result$images2 === void 0 ? void 0 : _result$images2[imageName];
71
+ const canApprove = Boolean(image && approved[imageName] != retry - 1 && result.status != 'success');
72
+ const hasDiffAndExpect = canApprove && Boolean((image === null || image === void 0 ? void 0 : image.diff) && image.expect);
73
+ const imagesWithError = result.images ? Object.keys(result.images).filter(imageName => {
74
+ var _imageName;
75
+
76
+ return result.status != 'success' && approved[imageName] != retry - 1 && ((_imageName = (result.images || {})[imageName]) === null || _imageName === void 0 ? void 0 : _imageName.error) != null;
77
+ }) : [];
78
+
79
+ const handleApprove = () => onImageApprove(id, retry - 1, imageName);
80
+
81
+ const handleChangeViewMode = mode => {
82
+ localStorage.setItem(VIEW_MODE_KEY, mode);
83
+ setViewMode(mode);
84
+ };
85
+
86
+ return /*#__PURE__*/React.createElement(Container, {
87
+ height: height
88
+ }, /*#__PURE__*/React.createElement(HeaderContainer, null, /*#__PURE__*/React.createElement(PageHeader, {
89
+ title: path,
90
+ images: result.images,
91
+ errorMessage: result.error,
92
+ showViewModes: hasDiffAndExpect,
93
+ viewMode: viewMode,
94
+ onViewModeChange: handleChangeViewMode,
95
+ onImageChange: setImageName,
96
+ showTitle: showTitle,
97
+ imagesWithError: imagesWithError
98
+ })), /*#__PURE__*/React.createElement(BodyContainer, null, /*#__PURE__*/React.createElement(ScrollArea, {
99
+ vertical: true
100
+ }, /*#__PURE__*/React.createElement(Wrapper, null, /*#__PURE__*/React.createElement(ImagesViewContainer, {
101
+ theme: theme
102
+ }, image ? /*#__PURE__*/React.createElement(ImagesView, {
103
+ url: url,
104
+ image: image,
105
+ canApprove: canApprove,
106
+ mode: viewMode
107
+ }) : /*#__PURE__*/React.createElement(Placeholder, null, "Image ".concat(imageName, " not found")))))), results.length ? /*#__PURE__*/React.createElement(FooterContainer, null, /*#__PURE__*/React.createElement(PageFooter, {
108
+ canApprove: canApprove,
109
+ retry: retry,
110
+ retriesCount: results.length,
111
+ onRetryChange: setRetry,
112
+ onApprove: handleApprove
113
+ })) : null);
114
+ }
115
+ export const ResultsPage = withTheme(ResultsPageInternal);
@@ -0,0 +1,67 @@
1
+ import { noop } from '../../types';
2
+ import { getConnectionUrl } from './helpers';
3
+ export async function initCreeveyClientApi() {
4
+ let clientApiResolver = noop;
5
+ const updateListeners = new Set();
6
+ let statusRequest = null;
7
+ let statusResolver = noop;
8
+ const ws = new WebSocket("ws://".concat(getConnectionUrl()));
9
+
10
+ function send(request) {
11
+ ws.send(JSON.stringify(request));
12
+ }
13
+
14
+ ws.addEventListener('open', () => {
15
+ clientApiResolver({
16
+ start(ids) {
17
+ send({
18
+ type: 'start',
19
+ payload: ids
20
+ });
21
+ },
22
+
23
+ stop() {
24
+ send({
25
+ type: 'stop'
26
+ });
27
+ },
28
+
29
+ approve(id, retry, image) {
30
+ send({
31
+ type: 'approve',
32
+ payload: {
33
+ id,
34
+ retry,
35
+ image
36
+ }
37
+ });
38
+ },
39
+
40
+ onUpdate(fn) {
41
+ updateListeners.add(fn);
42
+ return () => updateListeners.delete(fn);
43
+ },
44
+
45
+ get status() {
46
+ if (statusRequest) return statusRequest;
47
+ send({
48
+ type: 'status'
49
+ });
50
+ return statusRequest = new Promise(resolve => statusResolver = resolve);
51
+ }
52
+
53
+ });
54
+ });
55
+ ws.addEventListener('message', message => {
56
+ const data = JSON.parse(message.data);
57
+ if (data.type == 'update') updateListeners.forEach(fn => fn(data.payload));
58
+
59
+ if (data.type == 'status') {
60
+ statusResolver(data.payload);
61
+ statusResolver = noop;
62
+ statusRequest = null;
63
+ }
64
+ }); // TODO Reconnect
65
+
66
+ return new Promise(resolve => clientApiResolver = resolve);
67
+ }