@wdio/visual-service 6.3.3 → 7.0.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/dist/service.js CHANGED
@@ -3,10 +3,12 @@ import { expect } from '@wdio/globals';
3
3
  import { dirname, normalize, resolve } from 'node:path';
4
4
  import { BaseClass, checkElement, checkFullPageScreen, checkScreen, saveElement, saveFullPageScreen, saveScreen, saveTabbablePage, checkTabbablePage, FOLDERS, DEFAULT_TEST_CONTEXT, } from 'webdriver-image-comparison';
5
5
  import { SevereServiceError } from 'webdriverio';
6
- import { determineNativeContext, enrichTestContext, getFolders, getInstanceData, getNativeContext } from './utils.js';
6
+ import { enrichTestContext, getFolders, getInstanceData, getNativeContext, isBiDiScreenshotSupported, } from './utils.js';
7
7
  import { toMatchScreenSnapshot, toMatchFullPageSnapshot, toMatchElementSnapshot, toMatchTabbablePageSnapshot } from './matcher.js';
8
8
  import { waitForStorybookComponentToBeLoaded } from './storybook/utils.js';
9
9
  import { PAGE_OPTIONS_MAP } from './constants.js';
10
+ import { ContextManager } from './contextManager.js';
11
+ import { wrapWithContext } from './wrapWithContext.js';
10
12
  const log = logger('@wdio/visual-service');
11
13
  const elementCommands = { saveElement, checkElement };
12
14
  const pageCommands = {
@@ -24,11 +26,11 @@ export default class WdioImageComparisonService extends BaseClass {
24
26
  #currentFilePath;
25
27
  #testContext;
26
28
  #browser;
27
- _isNativeContext;
29
+ _contextManager;
30
+ _contextManagers = new Map();
28
31
  constructor(options, _, config) {
29
32
  super(options);
30
33
  this.#config = config;
31
- this._isNativeContext = undefined;
32
34
  this.#testContext = DEFAULT_TEST_CONTEXT;
33
35
  }
34
36
  /**
@@ -39,7 +41,6 @@ export default class WdioImageComparisonService extends BaseClass {
39
41
  }
40
42
  async before(capabilities, _specs, browser) {
41
43
  this.#browser = browser;
42
- this._isNativeContext = determineNativeContext(this.#browser);
43
44
  if (!this.#browser.isMultiremote) {
44
45
  log.info('Adding commands to global browser');
45
46
  await this.#addCommandsToBrowser(this.#browser);
@@ -47,9 +48,6 @@ export default class WdioImageComparisonService extends BaseClass {
47
48
  else {
48
49
  await this.#extendMultiremoteBrowser(capabilities);
49
50
  }
50
- if (browser.isMultiremote) {
51
- this.#setupMultiremoteContextListener();
52
- }
53
51
  /**
54
52
  * add custom matcher for visual comparison when expect has been added.
55
53
  * this is not the case in standalone mode
@@ -75,13 +73,6 @@ export default class WdioImageComparisonService extends BaseClass {
75
73
  beforeScenario(world) {
76
74
  this.#testContext = this.#getTestContext(world);
77
75
  }
78
- afterCommand(commandName, _args, result, error) {
79
- // This is for the cases where in the E2E tests we switch to a WEBVIEW or back to NATIVE_APP context
80
- if (commandName === 'getContext' && error === undefined && typeof result === 'string') {
81
- // Multiremote logic is handled in the `before` method during an event listener
82
- this._isNativeContext = this.#browser?.isMultiremote ? this._isNativeContext : result.includes('NATIVE');
83
- }
84
- }
85
76
  #getBaselineFolder() {
86
77
  const isDefaultBaselineFolder = normalize(FOLDERS.DEFAULT.BASE) === this.folders.baselineFolder;
87
78
  const baselineFolder = (isDefaultBaselineFolder && this.#currentFilePath ? this.#currentFilePath : this.folders.baselineFolder);
@@ -108,6 +99,8 @@ export default class WdioImageComparisonService extends BaseClass {
108
99
  for (const browserName of browserNames) {
109
100
  log.info(`Adding commands to Multi Browser: ${browserName}`);
110
101
  const browserInstance = browser.getInstance(browserName);
102
+ const contextManager = new ContextManager(browserInstance);
103
+ this._contextManagers?.set(browserName, contextManager);
111
104
  await this.#addCommandsToBrowser(browserInstance);
112
105
  }
113
106
  /**
@@ -130,123 +123,179 @@ export default class WdioImageComparisonService extends BaseClass {
130
123
  * Add commands to the "normal" browser object
131
124
  */
132
125
  async #addCommandsToBrowser(currentBrowser) {
133
- const instanceData = await getInstanceData(currentBrowser);
134
- const isNativeContext = getNativeContext(this.#browser, currentBrowser, this._isNativeContext);
126
+ this._contextManager = new ContextManager(currentBrowser);
127
+ currentBrowser.visualService = this;
128
+ const instanceData = await getInstanceData({
129
+ currentBrowser,
130
+ initialDeviceRectangles: this._contextManager.getViewportContext(),
131
+ isNativeContext: this._contextManager.isNativeContext,
132
+ });
133
+ // Update the context manager with the current viewport
134
+ this._contextManager.setViewPortContext(instanceData.deviceRectangles);
135
135
  for (const [commandName, command] of Object.entries(elementCommands)) {
136
- this.#addElementCommand(currentBrowser, commandName, command, instanceData, isNativeContext);
136
+ this.#addElementCommand(currentBrowser, commandName, command, instanceData);
137
137
  }
138
138
  for (const [commandName, command] of Object.entries(pageCommands)) {
139
- this.#addPageCommand(currentBrowser, commandName, command, instanceData, isNativeContext);
139
+ this.#addPageCommand(currentBrowser, commandName, command, instanceData);
140
140
  }
141
141
  }
142
142
  /**
143
143
  * Add new element commands to the browser object
144
144
  */
145
- #addElementCommand(browser, commandName, command, instanceData, isNativeContext) {
145
+ #addElementCommand(browser, commandName, command, initialInstanceData) {
146
146
  log.info(`Adding element command "${commandName}" to browser object`);
147
+ const elementOptionsKey = commandName === 'saveElement' ? 'saveElementOptions' : 'checkElementOptions';
147
148
  const self = this;
148
149
  browser.addCommand(commandName, function (element, tag, elementOptions = {}) {
149
- const elementOptionsKey = commandName === 'saveElement' ? 'saveElementOptions' : 'checkElementOptions';
150
- return command({
151
- methods: {
152
- executor: (script, ...varArgs) => {
153
- return this.execute.bind(browser)(script, ...varArgs);
154
- },
155
- getElementRect: this.getElementRect.bind(browser),
156
- screenShot: this.takeScreenshot.bind(browser),
157
- takeElementScreenshot: this.takeElementScreenshot.bind(browser),
158
- },
159
- instanceData,
160
- folders: getFolders(elementOptions, self.folders, self.#getBaselineFolder()),
161
- element,
162
- tag,
163
- [elementOptionsKey]: {
164
- wic: self.defaultOptions,
165
- method: elementOptions,
166
- },
167
- isNativeContext,
168
- testContext: enrichTestContext({
169
- commandName,
170
- currentTestContext: self.#testContext,
171
- instanceData,
172
- tag,
173
- })
150
+ const wrapped = wrapWithContext({
151
+ browser,
152
+ command,
153
+ contextManager: self.contextManager,
154
+ getArgs: () => {
155
+ const updatedInstanceData = {
156
+ ...initialInstanceData,
157
+ deviceRectangles: self.contextManager.getViewportContext(),
158
+ };
159
+ const isCurrentContextNative = self.contextManager.isNativeContext;
160
+ return [{
161
+ methods: {
162
+ executor: (fn, ...args) => {
163
+ return this.execute(fn, ...args);
164
+ },
165
+ getElementRect: this.getElementRect.bind(this),
166
+ screenShot: this.takeScreenshot.bind(this),
167
+ takeElementScreenshot: this.takeElementScreenshot.bind(this),
168
+ },
169
+ instanceData: updatedInstanceData,
170
+ folders: getFolders(elementOptions, self.folders, self.#getBaselineFolder()),
171
+ element,
172
+ tag,
173
+ [elementOptionsKey]: {
174
+ wic: self.defaultOptions,
175
+ method: elementOptions,
176
+ },
177
+ isNativeContext: isCurrentContextNative,
178
+ testContext: enrichTestContext({
179
+ commandName,
180
+ currentTestContext: self.#testContext,
181
+ instanceData: updatedInstanceData,
182
+ tag,
183
+ }),
184
+ }];
185
+ }
174
186
  });
187
+ return wrapped.call(this);
175
188
  });
176
189
  }
177
190
  /**
178
191
  * Add new page commands to the browser object
179
192
  */
180
- #addPageCommand(browser, commandName, command, instanceData, isNativeContext) {
193
+ #addPageCommand(browser, commandName, command, initialInstanceData) {
181
194
  log.info(`Adding browser command "${commandName}" to browser object`);
182
195
  const self = this;
183
196
  const pageOptionsKey = PAGE_OPTIONS_MAP[commandName];
184
197
  if (commandName === 'waitForStorybookComponentToBeLoaded') {
185
198
  browser.addCommand(commandName, (options) => waitForStorybookComponentToBeLoaded(options));
199
+ return;
186
200
  }
187
- else {
188
- browser.addCommand(commandName, function (tag, pageOptions = {}) {
189
- return command({
190
- methods: {
191
- executor: (script, ...varArgs) => {
192
- return this.execute.bind(browser)(script, ...varArgs);
193
- },
194
- getElementRect: this.getElementRect.bind(browser),
195
- screenShot: this.takeScreenshot.bind(browser),
196
- },
197
- instanceData,
198
- folders: getFolders(pageOptions, self.folders, self.#getBaselineFolder()),
199
- tag,
200
- [pageOptionsKey]: {
201
- wic: self.defaultOptions,
202
- method: pageOptions,
203
- },
204
- isNativeContext,
205
- testContext: enrichTestContext({
206
- commandName,
207
- currentTestContext: self.#testContext,
208
- instanceData,
209
- tag,
210
- })
211
- });
201
+ browser.addCommand(commandName, function (tag, pageOptions = {}) {
202
+ const wrapped = wrapWithContext({
203
+ browser,
204
+ command,
205
+ contextManager: self.contextManager,
206
+ getArgs: () => {
207
+ const updatedInstanceData = {
208
+ ...initialInstanceData,
209
+ deviceRectangles: self.contextManager.getViewportContext()
210
+ };
211
+ const isCurrentContextNative = self.contextManager.isNativeContext;
212
+ return [{
213
+ methods: {
214
+ bidiScreenshot: isBiDiScreenshotSupported(browser) ? this.browsingContextCaptureScreenshot.bind(browser) : undefined,
215
+ executor: (fn, ...args) => {
216
+ return this.execute(fn, ...args);
217
+ },
218
+ getElementRect: this.getElementRect.bind(browser),
219
+ getWindowHandle: this.getWindowHandle.bind(browser),
220
+ screenShot: this.takeScreenshot.bind(browser),
221
+ },
222
+ instanceData: updatedInstanceData,
223
+ folders: getFolders(pageOptions, self.folders, self.#getBaselineFolder()),
224
+ tag,
225
+ [pageOptionsKey]: {
226
+ wic: self.defaultOptions,
227
+ method: pageOptions,
228
+ },
229
+ isNativeContext: isCurrentContextNative,
230
+ testContext: enrichTestContext({
231
+ commandName,
232
+ currentTestContext: self.#testContext,
233
+ instanceData: updatedInstanceData,
234
+ tag,
235
+ }),
236
+ }];
237
+ }
212
238
  });
213
- }
239
+ return wrapped.call(this);
240
+ });
214
241
  }
215
242
  #addMultiremoteElementCommand(browser, browserNames, commandName, command) {
216
243
  log.info(`Adding element command "${commandName}" to Multi browser object`);
217
244
  const self = this;
218
- browser.addCommand(commandName, async function (element, tag, pageOptions = {}) {
245
+ browser.addCommand(commandName, async function (element, tag, elementOptions = {}) {
219
246
  const returnData = {};
220
247
  const elementOptionsKey = commandName === 'saveElement' ? 'saveElementOptions' : 'checkElementOptions';
221
248
  for (const browserName of browserNames) {
222
249
  const browserInstance = browser.getInstance(browserName);
223
- const isNativeContext = getNativeContext(self.#browser, browserInstance, self._isNativeContext);
224
- const instanceData = await getInstanceData(browserInstance);
225
- returnData[browserName] = await command({
226
- methods: {
227
- executor: (script, ...varArgs) => {
228
- return browserInstance.execute.bind(browserInstance)(script, ...varArgs);
229
- },
230
- getElementRect: browserInstance.getElementRect.bind(browserInstance),
231
- screenShot: browserInstance.takeScreenshot.bind(browserInstance),
232
- takeElementScreenshot: browserInstance.takeElementScreenshot.bind(browserInstance),
233
- },
234
- instanceData,
235
- folders: getFolders(pageOptions, self.folders, self.#getBaselineFolder()),
236
- tag,
237
- element,
238
- [elementOptionsKey]: {
239
- wic: self.defaultOptions,
240
- method: pageOptions,
241
- },
242
- isNativeContext,
243
- testContext: enrichTestContext({
244
- commandName,
245
- currentTestContext: self.#testContext,
246
- instanceData,
247
- tag,
248
- })
250
+ const contextManager = self._contextManagers?.get(browserName);
251
+ if (!contextManager) {
252
+ throw new Error(`No ContextManager found for browser instance: ${browserName}`);
253
+ }
254
+ const isNativeContext = contextManager.isNativeContext;
255
+ const initialInstanceData = await getInstanceData({
256
+ currentBrowser: browserInstance,
257
+ initialDeviceRectangles: contextManager.getViewportContext(),
258
+ isNativeContext
259
+ });
260
+ const wrapped = wrapWithContext({
261
+ browser: browserInstance,
262
+ command,
263
+ contextManager,
264
+ getArgs: () => {
265
+ const updatedInstanceData = {
266
+ ...initialInstanceData,
267
+ deviceRectangles: contextManager.getViewportContext(),
268
+ };
269
+ return [{
270
+ methods: {
271
+ bidiScreenshot: isBiDiScreenshotSupported(browserInstance) ? browserInstance.browsingContextCaptureScreenshot.bind(browserInstance) : undefined,
272
+ executor: (fn, ...args) => {
273
+ return browserInstance.execute(fn, ...args);
274
+ },
275
+ getElementRect: browserInstance.getElementRect.bind(browserInstance),
276
+ getWindowHandle: browserInstance.getWindowHandle.bind(browserInstance),
277
+ screenShot: browserInstance.takeScreenshot.bind(browserInstance),
278
+ takeElementScreenshot: browserInstance.takeElementScreenshot.bind(browserInstance),
279
+ },
280
+ instanceData: updatedInstanceData,
281
+ folders: getFolders(elementOptions, self.folders, self.#getBaselineFolder()),
282
+ tag,
283
+ element,
284
+ [elementOptionsKey]: {
285
+ wic: self.defaultOptions,
286
+ method: elementOptions,
287
+ },
288
+ isNativeContext,
289
+ testContext: enrichTestContext({
290
+ commandName,
291
+ currentTestContext: self.#testContext,
292
+ instanceData: updatedInstanceData,
293
+ tag,
294
+ }),
295
+ }];
296
+ }
249
297
  });
298
+ returnData[browserName] = await wrapped.call(browserInstance);
250
299
  }
251
300
  return returnData;
252
301
  });
@@ -256,59 +305,65 @@ export default class WdioImageComparisonService extends BaseClass {
256
305
  const self = this;
257
306
  if (commandName === 'waitForStorybookComponentToBeLoaded') {
258
307
  browser.addCommand(commandName, waitForStorybookComponentToBeLoaded);
308
+ return;
259
309
  }
260
- else {
261
- browser.addCommand(commandName, async function (tag, pageOptions = {}) {
262
- const returnData = {};
263
- const pageOptionsKey = PAGE_OPTIONS_MAP[commandName];
264
- for (const browserName of browserNames) {
265
- const browserInstance = browser.getInstance(browserName);
266
- const isNativeContext = getNativeContext(self.#browser, browserInstance, self._isNativeContext);
267
- const instanceData = await getInstanceData(browserInstance);
268
- returnData[browserName] = await command({
269
- methods: {
270
- executor: (script, ...varArgs) => {
271
- return browserInstance.execute.bind(browserInstance)(script, ...varArgs);
272
- },
273
- getElementRect: browserInstance.getElementRect.bind(browserInstance),
274
- screenShot: browserInstance.takeScreenshot.bind(browserInstance),
275
- },
276
- instanceData,
277
- folders: getFolders(pageOptions, self.folders, self.#getBaselineFolder()),
278
- tag,
279
- [pageOptionsKey]: {
280
- wic: self.defaultOptions,
281
- method: pageOptions,
282
- },
283
- isNativeContext,
284
- testContext: enrichTestContext({
285
- commandName,
286
- currentTestContext: self.#testContext,
287
- instanceData,
288
- tag,
289
- })
290
- });
310
+ browser.addCommand(commandName, async function (tag, pageOptions = {}) {
311
+ const returnData = {};
312
+ const pageOptionsKey = PAGE_OPTIONS_MAP[commandName];
313
+ for (const browserName of browserNames) {
314
+ const browserInstance = browser.getInstance(browserName);
315
+ const contextManager = self._contextManagers?.get(browserName);
316
+ if (!contextManager) {
317
+ throw new Error(`No ContextManager found for browser instance: ${browserName}`);
291
318
  }
292
- return returnData;
293
- });
294
- }
295
- }
296
- #setupMultiremoteContextListener() {
297
- const multiremoteBrowser = this.#browser;
298
- const browserInstances = multiremoteBrowser.instances;
299
- for (const instanceName of browserInstances) {
300
- const instance = multiremoteBrowser[instanceName];
301
- instance.on('result', (result) => {
302
- if (result.command === 'getContext') {
303
- const value = result.result.value;
304
- const sessionId = instance.sessionId;
305
- if (typeof this._isNativeContext !== 'object' || this._isNativeContext === null) {
306
- this._isNativeContext = {};
319
+ const isNativeContext = getNativeContext({
320
+ capabilities: browserInstance.requestedCapabilities,
321
+ isMobile: browserInstance.isMobile,
322
+ });
323
+ const initialInstanceData = await getInstanceData({
324
+ currentBrowser: browserInstance,
325
+ initialDeviceRectangles: contextManager.getViewportContext(),
326
+ isNativeContext
327
+ });
328
+ const wrapped = wrapWithContext({
329
+ browser: browserInstance,
330
+ command,
331
+ contextManager,
332
+ getArgs: () => {
333
+ const updatedInstanceData = {
334
+ ...initialInstanceData,
335
+ deviceRectangles: contextManager.getViewportContext()
336
+ };
337
+ const isCurrentContextNative = contextManager.isNativeContext;
338
+ return [{
339
+ methods: {
340
+ executor: (fn, ...args) => {
341
+ return browserInstance.execute(fn, ...args);
342
+ },
343
+ getElementRect: browserInstance.getElementRect.bind(browserInstance),
344
+ screenShot: browserInstance.takeScreenshot.bind(browserInstance),
345
+ },
346
+ instanceData: updatedInstanceData,
347
+ folders: getFolders(pageOptions, self.folders, self.#getBaselineFolder()),
348
+ tag,
349
+ [pageOptionsKey]: {
350
+ wic: self.defaultOptions,
351
+ method: pageOptions,
352
+ },
353
+ isNativeContext: isCurrentContextNative,
354
+ testContext: enrichTestContext({
355
+ commandName,
356
+ currentTestContext: self.#testContext,
357
+ instanceData: updatedInstanceData,
358
+ tag,
359
+ }),
360
+ }];
307
361
  }
308
- this._isNativeContext[sessionId] = value.includes('NATIVE');
309
- }
310
- });
311
- }
362
+ });
363
+ returnData[browserName] = await wrapped.call(browserInstance);
364
+ }
365
+ return returnData;
366
+ });
312
367
  }
313
368
  #getTestContext(test) {
314
369
  const framework = this.#config?.framework;
@@ -359,4 +414,10 @@ export default class WdioImageComparisonService extends BaseClass {
359
414
  }
360
415
  throw new SevereServiceError(`Framework ${framework} is not supported by the Visual Service and should be either "mocha", "jasmine" or "cucumber".`);
361
416
  }
417
+ get contextManager() {
418
+ if (!this._contextManager) {
419
+ throw new Error('ContextManager has not been initialized');
420
+ }
421
+ return this._contextManager;
422
+ }
362
423
  }
@@ -1,4 +1,4 @@
1
- import type { Folders } from 'webdriver-image-comparison';
1
+ import type { CheckElementMethodOptions, ClassOptions, Folders } from 'webdriver-image-comparison';
2
2
  export interface StorybookData {
3
3
  id: string;
4
4
  title: string;
@@ -31,7 +31,9 @@ export type Stories = {
31
31
  [key: string]: StorybookData;
32
32
  };
33
33
  export type CreateTestFileOptions = {
34
+ additionalSearchParams: URLSearchParams;
34
35
  clip: boolean;
36
+ compareOptions: CheckElementMethodOptions;
35
37
  clipSelector: string;
36
38
  directoryPath: string;
37
39
  folders: Folders;
@@ -40,7 +42,7 @@ export type CreateTestFileOptions = {
40
42
  skipStories: string[] | RegExp;
41
43
  storiesJson: StorybookData[];
42
44
  storybookUrl: string;
43
- };
45
+ } & Pick<CreateTestContent, 'getStoriesBaselinePath'>;
44
46
  export interface CapabilityMap {
45
47
  chrome: WebdriverIO.Capabilities;
46
48
  firefox: WebdriverIO.Capabilities;
@@ -48,23 +50,27 @@ export interface CapabilityMap {
48
50
  edge: WebdriverIO.Capabilities;
49
51
  }
50
52
  export type CreateTestContent = {
53
+ additionalSearchParams: URLSearchParams;
51
54
  clip: boolean;
52
55
  clipSelector: string;
56
+ compareOptions: CheckElementMethodOptions;
53
57
  folders: Folders;
54
58
  framework: string;
55
59
  skipStories: string[] | RegExp;
56
60
  stories: StorybookData[];
57
61
  storybookUrl: string;
58
- };
62
+ } & Pick<CreateItContent, 'getStoriesBaselinePath'>;
59
63
  export type CreateItContent = {
64
+ additionalSearchParams: URLSearchParams;
60
65
  clip: boolean;
61
66
  clipSelector: string;
67
+ compareOptions: CheckElementMethodOptions;
62
68
  folders: Folders;
63
69
  framework: string;
64
70
  skipStories: string[] | RegExp;
65
71
  storyData: StorybookData;
66
72
  storybookUrl: string;
67
- };
73
+ } & Pick<NonNullable<ClassOptions['storybook']>, 'getStoriesBaselinePath'>;
68
74
  export type CategoryComponent = {
69
75
  category: string;
70
76
  component: string;
@@ -84,6 +90,13 @@ export type EmulatedDeviceType = {
84
90
  userAgent: string;
85
91
  };
86
92
  export type WaitForStorybookComponentToBeLoaded = {
93
+ /**
94
+ * Additional search parameters to be added to the Storybook URL
95
+ *
96
+ * @example addtionalSearchParams: new URLSearchParams({ foo: 'bar', abc: 'def' })
97
+ * This will generate the following Storybook URL for stories test: `http://storybook.url/iframe.html?id=story-id&foo=bar&abc=def`
98
+ */
99
+ additionalSearchParams?: URLSearchParams;
87
100
  clipSelector?: string;
88
101
  id: string;
89
102
  timeout?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"Types.d.ts","sourceRoot":"","sources":["../../src/storybook/Types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Types.d.ts","sourceRoot":"","sources":["../../src/storybook/Types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../../src/storybook/launcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAetD,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,SAAS;;gBAGrC,OAAO,EAAE,YAAY;IAK3B,SAAS,CAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,YAAY,CAAC,sBAAsB;IAuExF,UAAU;CAuBnB"}
1
+ {"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../../src/storybook/launcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,YAAY,EAA8B,MAAM,4BAA4B,CAAA;AAC1F,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAetD,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,SAAS;;gBAGrC,OAAO,EAAE,YAAY;IAK3B,SAAS,CAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,YAAY,CAAC,sBAAsB;IA+FxF,UAAU;CAuBnB"}
@@ -34,6 +34,21 @@ export default class VisualLauncher extends BaseClass {
34
34
  // Clear the capabilities
35
35
  capabilities.length = 0;
36
36
  log.info('Clearing the current capabilities.');
37
+ // Get compare options from config
38
+ const compareOptions = {
39
+ blockOutSideBar: this.#options.blockOutSideBar,
40
+ blockOutStatusBar: this.#options.blockOutStatusBar,
41
+ blockOutToolBar: this.#options.blockOutToolBar,
42
+ ignoreAlpha: this.#options.ignoreAlpha,
43
+ ignoreAntialiasing: this.#options.ignoreAntialiasing,
44
+ ignoreColors: this.#options.ignoreColors,
45
+ ignoreLess: this.#options.ignoreLess,
46
+ ignoreNothing: this.#options.ignoreNothing,
47
+ rawMisMatchPercentage: this.#options.rawMisMatchPercentage,
48
+ returnAllCompareData: this.#options.returnAllCompareData,
49
+ saveAboveTolerance: this.#options.saveAboveTolerance,
50
+ scaleImagesToSameSize: this.#options.scaleImagesToSameSize,
51
+ };
37
52
  // Determine some run options
38
53
  // --version
39
54
  const versionOption = this.#options?.storybook?.version;
@@ -60,13 +75,21 @@ export default class VisualLauncher extends BaseClass {
60
75
  const skipStoriesArgv = getArgvValue('--skipStories', value => value);
61
76
  const skipStories = skipStoriesOption ?? skipStoriesArgv ?? [];
62
77
  const parsedSkipStories = parseSkipStories(skipStories);
78
+ // --additionalSearchParams
79
+ const additionalSearchParamsOption = this.#options?.storybook?.additionalSearchParams;
80
+ const additionalSearchParamsArgv = getArgvValue('--additionalSearchParams', value => new URLSearchParams(value));
81
+ const additionalSearchParams = additionalSearchParamsOption ?? additionalSearchParamsArgv ?? new URLSearchParams();
82
+ const getStoriesBaselinePath = this.#options?.storybook?.getStoriesBaselinePath;
63
83
  // Create the test files
64
84
  createTestFiles({
85
+ additionalSearchParams,
65
86
  clip,
66
87
  clipSelector,
88
+ compareOptions,
67
89
  directoryPath: tempDir,
68
90
  folders: this.folders,
69
91
  framework,
92
+ getStoriesBaselinePath,
70
93
  numShards,
71
94
  skipStories: parsedSkipStories,
72
95
  storiesJson,
@@ -36,12 +36,12 @@ export declare function getStoriesJson(url: string): Promise<Stories>;
36
36
  /**
37
37
  * Get arg value from the process.argv
38
38
  */
39
- export declare function getArgvValue(argName: string, parseFunc: (value: string) => any): any;
39
+ export declare function getArgvValue<ParseFuncReturnType>(argName: string, parseFunc: (value: string) => ParseFuncReturnType): ParseFuncReturnType | undefined;
40
40
  /**
41
41
  * Creates a it function for the test file
42
42
  * @TODO: improve this
43
43
  */
44
- export declare function itFunction({ clip, clipSelector, folders: { baselineFolder }, framework, skipStories, storyData, storybookUrl }: CreateItContent): string;
44
+ export declare function itFunction({ additionalSearchParams, clip, clipSelector, compareOptions, folders, framework, skipStories, storyData, storybookUrl, getStoriesBaselinePath }: CreateItContent): string;
45
45
  /**
46
46
  * Write the test file
47
47
  */
@@ -49,7 +49,7 @@ export declare function writeTestFile(directoryPath: string, fileID: string, tes
49
49
  /**
50
50
  * Create the test content
51
51
  */
52
- export declare function createTestContent({ clip, clipSelector, folders, framework, skipStories, stories, storybookUrl }: CreateTestContent, itFunc?: typeof itFunction): string;
52
+ export declare function createTestContent({ additionalSearchParams, clip, clipSelector, compareOptions, folders, framework, getStoriesBaselinePath, skipStories, stories, storybookUrl }: CreateTestContent, itFunc?: typeof itFunction): string;
53
53
  /**
54
54
  * The custom command
55
55
  */
@@ -61,7 +61,7 @@ export declare function createFileData(describeTitle: string, testContent: strin
61
61
  /**
62
62
  * Create the test files
63
63
  */
64
- export declare function createTestFiles({ clip, clipSelector, directoryPath, folders, framework, numShards, skipStories, storiesJson, storybookUrl }: CreateTestFileOptions, createTestCont?: typeof createTestContent, createFileD?: typeof createFileData, writeTestF?: typeof writeTestFile): void;
64
+ export declare function createTestFiles({ additionalSearchParams, clip, clipSelector, compareOptions, directoryPath, folders, framework, getStoriesBaselinePath, numShards, skipStories, storiesJson, storybookUrl }: CreateTestFileOptions, createTestCont?: typeof createTestContent, createFileD?: typeof createFileData, writeTestF?: typeof writeTestFile): void;
65
65
  export declare function createChromeCapabilityWithEmulation({ screen: { width, height, dpr }, name, userAgent }: EmulatedDeviceType, isHeadless: boolean): WebdriverIO.Capabilities;
66
66
  /**
67
67
  * Throw an error message if the capabilities are not set up correctly
@@ -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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"}