@wdio/visual-service 4.0.1 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @wdio/visual-service
2
2
 
3
+ ## 4.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c9fab82: change console.log to wdio logger
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [c9fab82]
12
+ - webdriver-image-comparison@5.1.0
13
+
14
+ ## 4.0.2
15
+
16
+ ### Patch Changes
17
+
18
+ - f878cab: # 🚀 Feature
19
+
20
+ - Add device support for Storybook, it can be used like this
21
+
22
+ ```sh
23
+ npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --devices="iPhone 14 Pro Max","Pixel 3 XL"
24
+ ```
25
+
26
+ #### Committers: 1
27
+
28
+ - Wim Selles ([@wswebcreation](https://github.com/wswebcreation))
29
+
30
+ - Updated dependencies [f878cab]
31
+ - webdriver-image-comparison@5.0.1
32
+
3
33
  ## 4.0.1
4
34
 
5
35
  ### Patch Changes
@@ -1,4 +1,3 @@
1
- import type { Logger } from '@wdio/logger';
2
1
  import type { RemoteCapability } from 'node_modules/@wdio/types/build/Capabilities.js';
3
2
  import type { Folders } from 'webdriver-image-comparison';
4
3
  export interface StorybookData {
@@ -39,7 +38,6 @@ export type CreateTestFileOptions = {
39
38
  folders: Folders;
40
39
  framework: string;
41
40
  numShards: number;
42
- log: Logger;
43
41
  skipStories: string[] | RegExp;
44
42
  storiesJson: Stories;
45
43
  storybookUrl: string;
@@ -77,4 +75,13 @@ export type ScanStorybookReturnData = {
77
75
  storybookUrl: string;
78
76
  tempDir: string;
79
77
  };
78
+ export type EmulatedDeviceType = {
79
+ name: string;
80
+ screen: {
81
+ dpr: number;
82
+ width: number;
83
+ height: number;
84
+ };
85
+ userAgent: string;
86
+ };
80
87
  //# sourceMappingURL=Types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Types.d.ts","sourceRoot":"","sources":["../../src/storybook/Types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAA;AACtF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAEzD,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,OAAO,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;KACpB,CAAC;CACL;AAED,MAAM,WAAW,QAAQ;IACrB,CAAC,EAAE,MAAM,CAAC;IACV,OAAO,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAA;KAAE,CAAC;CAC7C;AAED,MAAM,WAAW,UAAU;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,OAAO,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAA;KAAE,CAAC;CAC7C;AAED,MAAM,MAAM,OAAO,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAA;CAAE,CAAC;AAEvD,MAAM,MAAM,qBAAqB,GAAG;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAC,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC/B,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACxB,CAAA;AAED,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,MAAM,EAAE,gBAAgB,CAAC;IACzB,IAAI,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC/B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACxB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC/B,SAAS,EAAE,aAAa,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACxB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvE,MAAM,MAAM,uBAAuB,GAAG;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAAA"}
1
+ {"version":3,"file":"Types.d.ts","sourceRoot":"","sources":["../../src/storybook/Types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAA;AACtF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAEzD,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,OAAO,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;KACpB,CAAC;CACL;AAED,MAAM,WAAW,QAAQ;IACrB,CAAC,EAAE,MAAM,CAAC;IACV,OAAO,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAA;KAAE,CAAC;CAC7C;AAED,MAAM,WAAW,UAAU;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,OAAO,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAA;KAAE,CAAC;CAC7C;AAED,MAAM,MAAM,OAAO,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAA;CAAE,CAAC;AAEvD,MAAM,MAAM,qBAAqB,GAAG;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAC,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC/B,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACxB,CAAA;AAED,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,MAAM,EAAE,gBAAgB,CAAC;IACzB,IAAI,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC/B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACxB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC/B,SAAS,EAAE,aAAa,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACxB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvE,MAAM,MAAM,uBAAuB,GAAG;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAAA;AAEpG,MAAM,MAAM,kBAAkB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QACJ,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAA;KACjB,CAAC;IACF,SAAS,EAAE,MAAM,CAAA;CACpB,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { EmulatedDeviceType } from './Types.js';
2
+ export declare const deviceDescriptors: EmulatedDeviceType[];
3
+ //# sourceMappingURL=deviceDescriptors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deviceDescriptors.d.ts","sourceRoot":"","sources":["../../src/storybook/deviceDescriptors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAIpD,eAAO,MAAM,iBAAiB,EAAE,kBAAkB,EAyNjD,CAAA"}
@@ -0,0 +1,220 @@
1
+ // This is a reflection of what the Chromium Devtools provides for device emulation
2
+ // https://source.chromium.org/chromium/chromium/src/+/main:out/fuchsia-Debug/gen/third_party/devtools-frontend/src/front_end/models/emulation/emulation.js?q=%22iPhone%204%22&ss=chromium
3
+ export const deviceDescriptors = [
4
+ {
5
+ 'name': 'iPad Mini',
6
+ 'screen': {
7
+ 'dpr': 2,
8
+ 'width': 1024,
9
+ 'height': 768
10
+ },
11
+ 'userAgent': 'Mozilla/5.0 (iPad; CPU OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1'
12
+ },
13
+ {
14
+ 'name': 'iPad',
15
+ 'screen': {
16
+ 'dpr': 2,
17
+ 'width': 1024,
18
+ 'height': 768
19
+ },
20
+ 'userAgent': 'Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1'
21
+ },
22
+ {
23
+ 'name': 'iPad Pro',
24
+ 'screen': {
25
+ 'dpr': 2,
26
+ 'width': 1366,
27
+ 'height': 1024
28
+ },
29
+ 'userAgent': 'Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1'
30
+ },
31
+ {
32
+ 'name': 'iPhone SE',
33
+ 'screen': {
34
+ 'dpr': 2,
35
+ 'width': 320,
36
+ 'height': 568
37
+ },
38
+ 'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/17.4 Mobile/14E304 Safari/602.1'
39
+ },
40
+ {
41
+ 'name': 'iPhone X',
42
+ 'screen': {
43
+ 'dpr': 3,
44
+ 'width': 375,
45
+ 'height': 812
46
+ },
47
+ 'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/17.4 Mobile/15A372 Safari/604.1'
48
+ },
49
+ {
50
+ 'name': 'iPhone XR',
51
+ 'screen': {
52
+ 'dpr': 3,
53
+ 'width': 414,
54
+ 'height': 896
55
+ },
56
+ 'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1'
57
+ },
58
+ {
59
+ 'name': 'iPhone 13',
60
+ 'screen': {
61
+ 'dpr': 3,
62
+ 'width': 390,
63
+ 'height': 844
64
+ },
65
+ 'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1'
66
+ },
67
+ {
68
+ 'name': 'iPhone 14 Plus',
69
+ 'screen': {
70
+ 'dpr': 3,
71
+ 'width': 428,
72
+ 'height': 926
73
+ },
74
+ 'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1'
75
+ },
76
+ {
77
+ 'name': 'iPhone 14 Pro',
78
+ 'screen': {
79
+ 'dpr': 3,
80
+ 'width': 393,
81
+ 'height': 852
82
+ },
83
+ 'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1'
84
+ },
85
+ {
86
+ 'name': 'iPhone 14 Pro Max',
87
+ 'screen': {
88
+ 'dpr': 3,
89
+ 'width': 430,
90
+ 'height': 932
91
+ },
92
+ 'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1'
93
+ },
94
+ {
95
+ 'name': 'Pixel 2',
96
+ 'screen': {
97
+ 'dpr': 2.625,
98
+ 'width': 411,
99
+ 'height': 731,
100
+ },
101
+ 'userAgent': 'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Mobile Safari/537.36'
102
+ },
103
+ {
104
+ 'name': 'Pixel 2 XL',
105
+ 'screen': {
106
+ 'dpr': 3.5,
107
+ 'width': 411,
108
+ 'height': 823,
109
+ },
110
+ 'userAgent': 'Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Mobile Safari/537.36'
111
+ },
112
+ {
113
+ 'name': 'Pixel 3',
114
+ 'screen': {
115
+ 'dpr': 2.75,
116
+ 'width': 393,
117
+ 'height': 786,
118
+ },
119
+ 'userAgent': 'Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.158 Mobile Safari/537.36'
120
+ },
121
+ {
122
+ 'name': 'Pixel 4',
123
+ 'screen': {
124
+ 'dpr': 3,
125
+ 'width': 353,
126
+ 'height': 745,
127
+ },
128
+ 'userAgent': 'Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36'
129
+ },
130
+ {
131
+ 'name': 'Pixel 3 XL',
132
+ 'screen': {
133
+ 'dpr': 2.75,
134
+ 'width': 393,
135
+ 'height': 786,
136
+ },
137
+ 'userAgent': 'Mozilla/5.0 (Linux; Android 11; Pixel 3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.181 Mobile Safari/537.36'
138
+ },
139
+ {
140
+ 'name': 'Pixel 7',
141
+ 'screen': {
142
+ 'dpr': 2.625,
143
+ 'width': 412,
144
+ 'height': 915,
145
+ },
146
+ 'userAgent': 'Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36'
147
+ },
148
+ {
149
+ 'name': 'Samsung Galaxy A51/71',
150
+ 'screen': {
151
+ 'dpr': 2.625,
152
+ 'width': 412,
153
+ 'height': 914,
154
+ },
155
+ 'userAgent': 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36'
156
+ },
157
+ {
158
+ 'name': 'Samsung Galaxy S8+',
159
+ 'screen': {
160
+ 'dpr': 4,
161
+ 'width': 360,
162
+ 'height': 740,
163
+ },
164
+ 'userAgent': 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36'
165
+ },
166
+ {
167
+ 'name': 'Galaxy Z Fold 5',
168
+ 'screen': {
169
+ 'dpr': 2.625,
170
+ 'width': 344,
171
+ 'height': 882,
172
+ },
173
+ 'userAgent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Mobile Safari/537.36'
174
+ },
175
+ {
176
+ 'name': 'Galaxy S8',
177
+ 'screen': {
178
+ 'dpr': 3,
179
+ 'width': 360,
180
+ 'height': 740,
181
+ },
182
+ 'userAgent': 'Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36'
183
+ },
184
+ {
185
+ 'name': 'Galaxy S9+',
186
+ 'screen': {
187
+ 'dpr': 4.5,
188
+ 'width': 320,
189
+ 'height': 658,
190
+ },
191
+ 'userAgent': 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36'
192
+ },
193
+ {
194
+ 'name': 'Galaxy Tab S4',
195
+ 'screen': {
196
+ 'dpr': 2.25,
197
+ 'width': 712,
198
+ 'height': 1138,
199
+ },
200
+ 'userAgent': 'Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Safari/537.36',
201
+ },
202
+ {
203
+ 'name': 'Surface Pro 7',
204
+ 'screen': {
205
+ 'dpr': 2,
206
+ 'height': 912,
207
+ 'width': 1368,
208
+ },
209
+ 'userAgent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36'
210
+ },
211
+ {
212
+ 'name': 'Surface Duo',
213
+ 'screen': {
214
+ 'dpr': 2.5,
215
+ 'height': 540,
216
+ 'width': 720,
217
+ },
218
+ 'userAgent': 'Mozilla/5.0 (Linux; Android 11.0; Surface Duo) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Mobile Safari/537.36'
219
+ },
220
+ ];
@@ -1 +1 @@
1
- {"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../../src/storybook/launcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AActD,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,SAAS;;gBAGrC,OAAO,EAAE,YAAY;IAK3B,SAAS,CAAE,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE,YAAY,EAAE,YAAY,CAAC,kBAAkB;IA0DpF,UAAU;CAenB"}
1
+ {"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../../src/storybook/launcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AActD,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,SAAS;;gBAGrC,OAAO,EAAE,YAAY;IAK3B,SAAS,CAAE,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE,YAAY,EAAE,YAAY,CAAC,kBAAkB;IAmEpF,UAAU;CAenB"}
@@ -20,9 +20,17 @@ export default class VisualLauncher extends BaseClass {
20
20
  }
21
21
  else if (isStorybook) {
22
22
  log.info('Running `@wdio/visual-service` in Storybook mode.');
23
- const { storiesJson, storybookUrl, tempDir } = await scanStorybook(config, log, this.#options);
23
+ const { storiesJson, storybookUrl, tempDir } = await scanStorybook(config, this.#options);
24
24
  // Set an environment variable so it can be used in the onComplete hook
25
25
  process.env.VISUAL_STORYBOOK_TEMP_SPEC_FOLDER = tempDir;
26
+ // Check the capabilities
27
+ // Multiremote capabilities are not supported
28
+ if (typeof capabilities === 'object' && !Array.isArray(capabilities)) {
29
+ throw new SevereServiceError('\n\nRunning Storybook in combination with Multiremote is not supported.\nRemove your `capabilities` property from your config or assign an empty array to it like `capabilities: [],`.\n\n');
30
+ }
31
+ // Clear the capabilities
32
+ capabilities.length = 0;
33
+ log.info('Clearing the current capabilities.');
26
34
  // Determine some run options
27
35
  // --version
28
36
  const versionOption = this.#options?.storybook?.version;
@@ -46,7 +54,7 @@ export default class VisualLauncher extends BaseClass {
46
54
  const skipStoriesOption = this.#options?.storybook?.skipStories;
47
55
  const skipStoriesArgv = getArgvValue('--skipStories', value => value);
48
56
  const skipStories = skipStoriesOption ?? skipStoriesArgv ?? [];
49
- const parsedSkipStories = parseSkipStories(skipStories, log);
57
+ const parsedSkipStories = parseSkipStories(skipStories);
50
58
  // Create the test files
51
59
  createTestFiles({
52
60
  clip,
@@ -54,14 +62,13 @@ export default class VisualLauncher extends BaseClass {
54
62
  directoryPath: tempDir,
55
63
  folders: this.folders,
56
64
  framework,
57
- log,
58
65
  numShards,
59
66
  skipStories: parsedSkipStories,
60
67
  storiesJson,
61
68
  storybookUrl,
62
69
  });
63
70
  // Create the capabilities
64
- createStorybookCapabilities(capabilities, log);
71
+ createStorybookCapabilities(capabilities);
65
72
  }
66
73
  }
67
74
  async onComplete() {
@@ -1,7 +1,6 @@
1
- import type { Logger } from '@wdio/logger';
2
- import type { Capabilities, Options } from '@wdio/types';
1
+ import type { Options } from '@wdio/types';
3
2
  import type { ClassOptions } from 'webdriver-image-comparison';
4
- import type { CategoryComponent, CreateItContent, CreateTestContent, CreateTestFileOptions, ScanStorybookReturnData, Stories } from './Types.js';
3
+ import type { CategoryComponent, CreateItContent, CreateTestContent, CreateTestFileOptions, ScanStorybookReturnData, Stories, EmulatedDeviceType, CapabilityMap } from './Types.js';
5
4
  /**
6
5
  * Check if we run for Storybook
7
6
  */
@@ -46,7 +45,7 @@ export declare function itFunction({ clip, clipSelector, folders: { baselineFold
46
45
  /**
47
46
  * Write the test file
48
47
  */
49
- export declare function writeTestFile(directoryPath: string, fileID: string, log: Logger, testContent: string): void;
48
+ export declare function writeTestFile(directoryPath: string, fileID: string, testContent: string): void;
50
49
  /**
51
50
  * Create the test content
52
51
  */
@@ -58,17 +57,22 @@ export declare function createFileData(describeTitle: string, testContent: strin
58
57
  /**
59
58
  * Create the test files
60
59
  */
61
- export declare function createTestFiles({ clip, clipSelector, directoryPath, folders, framework, log, numShards, skipStories, storiesJson, storybookUrl }: CreateTestFileOptions, createTestCont?: typeof createTestContent, createFileD?: typeof createFileData, writeTestF?: typeof writeTestFile): void;
60
+ export declare function createTestFiles({ clip, clipSelector, directoryPath, folders, framework, numShards, skipStories, storiesJson, storybookUrl }: CreateTestFileOptions, createTestCont?: typeof createTestContent, createFileD?: typeof createFileData, writeTestF?: typeof writeTestFile): void;
61
+ export declare function createChromeCapabilityWithEmulation({ screen: { width, height, dpr }, name, userAgent }: EmulatedDeviceType, isHeadless: boolean): WebdriverIO.Capabilities;
62
+ /**
63
+ * Throw an error message if the capabilities are not set up correctly
64
+ */
65
+ export declare function capabilitiesErrorMessage(browsers: string[], capabilityMap: CapabilityMap, devices: string[], deviceDescriptors: EmulatedDeviceType[], isMobileEmulation: boolean): void;
62
66
  /**
63
67
  * Create the storybook capabilities based on the specified browsers
64
68
  */
65
- export declare function createStorybookCapabilities(capabilities: Capabilities.RemoteCapabilities, log: Logger): void;
69
+ export declare function createStorybookCapabilities(capabilities: WebdriverIO.Capabilities[], createChromeCapabilityWithEmulationFunc?: typeof createChromeCapabilityWithEmulation, capabilitiesErrorMessageFunc?: typeof capabilitiesErrorMessage): void;
66
70
  /**
67
71
  * Scan the storybook instance
68
72
  */
69
- export declare function scanStorybook(config: Options.Testrunner, log: Logger, options: ClassOptions, getArgvVal?: typeof getArgvValue, checkStorybookIsRun?: typeof checkStorybookIsRunning, sanitizeURLFunc?: typeof sanitizeURL, getStoriesJsonFunc?: typeof getStoriesJson): Promise<ScanStorybookReturnData>;
73
+ export declare function scanStorybook(config: Options.Testrunner, options: ClassOptions, getArgvVal?: typeof getArgvValue, checkStorybookIsRun?: typeof checkStorybookIsRunning, sanitizeURLFunc?: typeof sanitizeURL, getStoriesJsonFunc?: typeof getStoriesJson): Promise<ScanStorybookReturnData>;
70
74
  /**
71
75
  * Parse the stories to skip
72
76
  */
73
- export declare function parseSkipStories(skipStories: string | string[], log: Logger): RegExp | string[];
77
+ export declare function parseSkipStories(skipStories: string | string[]): RegExp | string[];
74
78
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/storybook/utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/storybook/utils.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,10 @@
1
+ import logger from '@wdio/logger';
1
2
  import fetch from 'node-fetch';
2
3
  import { mkdirSync, writeFileSync } from 'node:fs';
3
4
  import { tmpdir } from 'node:os';
4
5
  import { join, resolve } from 'node:path';
6
+ import { deviceDescriptors } from './deviceDescriptors.js';
7
+ const log = logger('@wdio/visual-service:storybook-utils');
5
8
  /**
6
9
  * Check if we run for Storybook
7
10
  */
@@ -37,7 +40,7 @@ export async function checkStorybookIsRunning(url) {
37
40
  }
38
41
  }
39
42
  catch (e) {
40
- console.error(`It seems that the Storybook instance is not running at: ${url}. Are you sure it's running?`);
43
+ log.error(`It seems that the Storybook instance is not running at: ${url}. Are you sure it's running?`);
41
44
  process.exit(1);
42
45
  }
43
46
  }
@@ -82,8 +85,8 @@ export async function getStoriesJson(url) {
82
85
  }
83
86
  }
84
87
  }
85
- catch (err) {
86
- console.error(err);
88
+ catch (ign) {
89
+ // Ignore the error
87
90
  }
88
91
  throw new Error(`Failed to fetch index data from the project. Ensure URLs are available with valid data: ${storiesJsonUrl}, ${indexJsonUrl}.`);
89
92
  }
@@ -145,7 +148,7 @@ export function itFunction({ clip, clipSelector, folders: { baselineFolder }, fr
145
148
  /**
146
149
  * Write the test file
147
150
  */
148
- export function writeTestFile(directoryPath, fileID, log, testContent) {
151
+ export function writeTestFile(directoryPath, fileID, testContent) {
149
152
  const filePath = join(directoryPath, `${fileID}.test.js`);
150
153
  try {
151
154
  writeFileSync(filePath, testContent);
@@ -226,7 +229,7 @@ ${waitForAllImagesLoaded}
226
229
  /**
227
230
  * Create the test files
228
231
  */
229
- export function createTestFiles({ clip, clipSelector, directoryPath, folders, framework, log, numShards, skipStories, storiesJson, storybookUrl },
232
+ export function createTestFiles({ clip, clipSelector, directoryPath, folders, framework, numShards, skipStories, storiesJson, storybookUrl },
230
233
  // For testing purposes only
231
234
  createTestCont = createTestContent, createFileD = createFileData, writeTestF = writeTestFile) {
232
235
  const storiesArray = Object.values(storiesJson)
@@ -238,7 +241,7 @@ createTestCont = createTestContent, createFileD = createFileData, writeTestF = w
238
241
  if (numShards === 1) {
239
242
  const testContent = createTestCont(createTestContentData);
240
243
  const fileData = createFileD('All stories', testContent);
241
- writeTestF(directoryPath, `${fileNamePrefix}-1-1`, log, fileData);
244
+ writeTestF(directoryPath, `${fileNamePrefix}-1-1`, fileData);
242
245
  }
243
246
  else {
244
247
  const totalStories = storiesArray.length;
@@ -251,74 +254,137 @@ createTestCont = createTestContent, createFileD = createFileData, writeTestF = w
251
254
  const fileId = `${fileNamePrefix}-${shard + 1}-${numShards}`;
252
255
  const describeTitle = `Shard ${shard + 1} of ${numShards}`;
253
256
  const fileData = createFileD(describeTitle, testContent);
254
- writeTestF(directoryPath, fileId, log, fileData);
257
+ writeTestF(directoryPath, fileId, fileData);
255
258
  }
256
259
  }
257
260
  }
261
+ export function createChromeCapabilityWithEmulation({ screen: { width, height, dpr }, name, userAgent }, isHeadless) {
262
+ return {
263
+ browserName: 'chrome',
264
+ 'goog:chromeOptions': {
265
+ args: [
266
+ 'disable-infobars',
267
+ ...(isHeadless ? ['--headless'] : []),
268
+ ],
269
+ mobileEmulation: {
270
+ deviceMetrics: {
271
+ width,
272
+ height,
273
+ pixelRatio: dpr,
274
+ },
275
+ userAgent,
276
+ },
277
+ },
278
+ 'wdio-ics:options': {
279
+ logName: `local-chrome-${name.replace(/\s+/g, '-')}`,
280
+ },
281
+ };
282
+ }
283
+ /**
284
+ * Throw an error message if the capabilities are not set up correctly
285
+ */
286
+ export function capabilitiesErrorMessage(browsers, capabilityMap, devices, deviceDescriptors, isMobileEmulation) {
287
+ let errorMessage = 'No capabilities were added. Please ensure that ';
288
+ const browserIssues = browsers.some((browser) => !(browser in capabilityMap));
289
+ const deviceIssues = isMobileEmulation && devices.some((deviceName) => !deviceDescriptors.some(device => device.name === deviceName));
290
+ if (browserIssues && deviceIssues) {
291
+ errorMessage += `the browsers '${browsers.join(',')}' and devices '${devices.join(',')}' are supported.`;
292
+ }
293
+ else if (browserIssues) {
294
+ errorMessage += `the browsers '${browsers.join(',')}' are supported.`;
295
+ }
296
+ else if (deviceIssues) {
297
+ errorMessage += `the devices '${devices.join(',')}' are supported.`;
298
+ }
299
+ else {
300
+ errorMessage += 'the specified configuration is correct.';
301
+ }
302
+ throw new Error(errorMessage);
303
+ }
258
304
  /**
259
305
  * Create the storybook capabilities based on the specified browsers
260
306
  */
261
- export function createStorybookCapabilities(capabilities, log) {
307
+ export function createStorybookCapabilities(capabilities,
308
+ // For testing purposes only
309
+ createChromeCapabilityWithEmulationFunc = createChromeCapabilityWithEmulation, capabilitiesErrorMessageFunc = capabilitiesErrorMessage) {
310
+ if (!Array.isArray(capabilities)) {
311
+ log.error('The capabilities are not an array');
312
+ return;
313
+ }
262
314
  const isHeadless = getArgvValue('--headless', value => value !== 'false') ?? true;
263
315
  const browsers = getArgvValue('--browsers', (value) => value.split(',')) ?? ['chrome'];
264
- if (Array.isArray(capabilities)) {
265
- const chromeCapability = {
266
- browserName: 'chrome',
267
- 'goog:chromeOptions': {
268
- args: [
269
- 'disable-infobars',
270
- ...(isHeadless ? ['--headless'] : []),
271
- ],
272
- },
273
- 'wdio-ics:options': {
274
- logName: 'local-chrome',
275
- },
276
- };
277
- const firefoxCapability = {
278
- browserName: 'firefox',
279
- 'moz:firefoxOptions': {
280
- args: [...(isHeadless ? ['-headless'] : []),]
281
- },
282
- 'wdio-ics:options': {
283
- logName: 'local-firefox',
284
- },
285
- };
286
- const safariCapability = {
287
- browserName: 'safari',
288
- 'wdio-ics:options': {
289
- logName: 'local-safari',
290
- },
291
- };
292
- const edgeCapability = {
293
- browserName: 'MicrosoftEdge',
294
- 'ms:edgeOptions': {
295
- args: [...(isHeadless ? ['--headless'] : [])]
296
- },
297
- 'wdio-ics:options': {
298
- logName: 'local-edge',
299
- },
300
- };
301
- const capabilityMap = {
302
- chrome: chromeCapability,
303
- firefox: firefoxCapability,
304
- safari: safariCapability,
305
- edge: edgeCapability,
306
- };
307
- const newCapabilities = browsers
308
- .filter((browser) => browser in capabilityMap)
309
- .map((browser) => capabilityMap[browser]);
310
- capabilities.length = 0;
311
- // Add the new capability to the capabilities array
312
- capabilities.push(...newCapabilities);
316
+ const devices = getArgvValue('--devices', (value) => value.split(',')) ?? [];
317
+ const isMobileEmulation = devices.length > 0;
318
+ const chromeCapability = {
319
+ browserName: 'chrome',
320
+ 'goog:chromeOptions': {
321
+ args: [
322
+ 'disable-infobars',
323
+ ...(isHeadless ? ['--headless'] : []),
324
+ ],
325
+ },
326
+ 'wdio-ics:options': {
327
+ logName: 'local-chrome',
328
+ },
329
+ };
330
+ const edgeCapability = {
331
+ browserName: 'MicrosoftEdge',
332
+ 'ms:edgeOptions': {
333
+ args: [...(isHeadless ? ['--headless'] : [])],
334
+ },
335
+ 'wdio-ics:options': {
336
+ logName: 'local-edge',
337
+ },
338
+ };
339
+ const firefoxCapability = {
340
+ browserName: 'firefox',
341
+ 'moz:firefoxOptions': {
342
+ args: [...(isHeadless ? ['-headless'] : []),]
343
+ },
344
+ 'wdio-ics:options': {
345
+ logName: 'local-firefox',
346
+ },
347
+ };
348
+ const safariCapability = {
349
+ browserName: 'safari',
350
+ 'wdio-ics:options': {
351
+ logName: 'local-safari',
352
+ },
353
+ };
354
+ const capabilityMap = {
355
+ chrome: chromeCapability,
356
+ edge: edgeCapability,
357
+ firefox: firefoxCapability,
358
+ safari: safariCapability,
359
+ };
360
+ const standardCapabilities = browsers
361
+ .filter((browser) => browser in capabilityMap && browser.toLowerCase() !== 'chrome')
362
+ .map((browser) => capabilityMap[browser]);
363
+ capabilities.push(...standardCapabilities);
364
+ if (isMobileEmulation) {
365
+ devices.forEach((deviceName) => {
366
+ const foundDevice = deviceDescriptors.find((device) => device.name === deviceName);
367
+ if (foundDevice) {
368
+ const chromeMobileCapability = createChromeCapabilityWithEmulationFunc(foundDevice, isHeadless);
369
+ capabilities.push(chromeMobileCapability);
370
+ }
371
+ else {
372
+ log.error(`The device ${deviceName} is not supported. Please choose from the following devices: ${deviceDescriptors.map(device => device.name).join(', ')}`);
373
+ }
374
+ });
313
375
  }
314
- else {
315
- log.error('The capabilities are not an array');
376
+ else if (browsers.includes('chrome')) {
377
+ capabilities.push(chromeCapability);
378
+ }
379
+ if (capabilities.length === 0) {
380
+ capabilitiesErrorMessageFunc(browsers, capabilityMap, devices, deviceDescriptors, isMobileEmulation);
316
381
  }
382
+ log.info('Added new storybook capabilities:', JSON.stringify(capabilities, null, 2));
317
383
  }
318
384
  /**
319
385
  * Scan the storybook instance
320
386
  */
321
- export async function scanStorybook(config, log, options,
387
+ export async function scanStorybook(config, options,
322
388
  // For testing purposes only
323
389
  getArgvVal = getArgvValue, checkStorybookIsRun = checkStorybookIsRunning, sanitizeURLFunc = sanitizeURL, getStoriesJsonFunc = getStoriesJson) {
324
390
  // Prepare storybook scanning
@@ -342,7 +408,7 @@ getArgvVal = getArgvValue, checkStorybookIsRun = checkStorybookIsRunning, saniti
342
408
  /**
343
409
  * Parse the stories to skip
344
410
  */
345
- export function parseSkipStories(skipStories, log) {
411
+ export function parseSkipStories(skipStories) {
346
412
  if (Array.isArray(skipStories)) {
347
413
  return skipStories;
348
414
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@wdio/visual-service",
3
3
  "author": "Wim Selles - wswebcreation",
4
4
  "description": "Image comparison / visual regression testing for WebdriverIO",
5
- "version": "4.0.1",
5
+ "version": "4.1.0",
6
6
  "license": "MIT",
7
7
  "homepage": "https://webdriver.io/docs/visual-testing",
8
8
  "repository": {
@@ -23,7 +23,7 @@
23
23
  "@wdio/logger": "^8.28.0",
24
24
  "@wdio/types": "^8.32.4",
25
25
  "node-fetch": "^3.3.2",
26
- "webdriver-image-comparison": "^5.0.0"
26
+ "webdriver-image-comparison": "^5.1.0"
27
27
  },
28
28
  "scripts": {
29
29
  "build": "run-s clean build:*",