@wdio/image-comparison-core 1.1.2 → 1.1.4

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,63 @@
1
1
  # @wdio/image-comparison-core
2
2
 
3
+ ## 1.1.4
4
+
5
+ ### Patch Changes
6
+
7
+ - 0a19d78: Fix `clearRuntimeFolder` clearing the actual and diff folders after each spec/feature execution instead of once before all workers start. This caused only the last spec's visual data to be present in the output when running multiple specs.
8
+
9
+ # Committers: 1
10
+
11
+ - Wim Selles ([@wswebcreation](https://github.com/wswebcreation))
12
+
13
+ - ce74703: Stop creating empty diff folders when no visual differences exist. The diff directory is now only created on disk when a diff image is actually saved, instead of being eagerly created during path preparation. Fixes #879.
14
+
15
+ # Committers: 1
16
+
17
+ - Wim Selles ([@wswebcreation](https://github.com/wswebcreation))
18
+
19
+ ## 1.1.3
20
+
21
+ ### Patch Changes
22
+
23
+ - a3bc7a4: ## #1115 Respect `alwaysSaveActualImage: false` for `checkScreen` methods
24
+
25
+ When using visual matchers like `toMatchScreenSnapshot('tag', 0.9)` with `alwaysSaveActualImage: false`, the actual image was still being saved even when the comparison passed within the threshold.
26
+
27
+ The root cause was that the matcher's expected threshold was not being passed to the core comparison logic. The core used `saveAboveTolerance` (defaulting to 0) to decide whether to save images, while the matcher used the user-provided threshold to determine pass/fail - these were disconnected.
28
+
29
+ This fix ensures:
30
+
31
+ - When `alwaysSaveActualImage: false` and `saveAboveTolerance` is not explicitly set, actual images are never saved (respecting the literal meaning of the option)
32
+ - When `saveAboveTolerance` is explicitly set (like matchers do internally), actual images are saved only when the mismatch exceeds that threshold
33
+
34
+ # Committers: 1
35
+
36
+ - Wim Selles ([@wswebcreation](https://github.com/wswebcreation))
37
+
38
+ - a3bc7a4: ## Fix: `save*` methods now always save files regardless of `alwaysSaveActualImage` setting
39
+
40
+ Previously, when `alwaysSaveActualImage: false` was set in the configuration, `save*` methods (`saveScreen`, `saveElement`, `saveFullPageScreen`, `saveAppScreen`, `saveAppElement`) were not saving files to disk, causing test failures.
41
+
42
+ The `alwaysSaveActualImage` option is intended to control whether actual images are saved during `check*` methods (comparison operations), not `save*` methods. Since `save*` methods are explicitly designed to save screenshots, they should always save files regardless of this setting.
43
+
44
+ This fix ensures:
45
+
46
+ - `save*` methods always save files to disk, even when `alwaysSaveActualImage: false` is set in the config
47
+ - `alwaysSaveActualImage: false` continues to work correctly for `check*` methods (as intended for issue #1115)
48
+ - The behavior is now consistent: `save*` = always save, `check*` = respect `alwaysSaveActualImage` setting
49
+
50
+ **Implementation details:**
51
+
52
+ - The visual service overrides `alwaysSaveActualImage: true` when calling `save*` methods directly from the browser API
53
+ - `save*` methods respect whatever `alwaysSaveActualImage` value is passed to them (no special logic needed)
54
+ - `check*` methods pass through the config value (which may be `false`), so `save*` methods respect it when called internally
55
+ - This clean separation ensures `save*` methods work correctly when called directly while still respecting `alwaysSaveActualImage` for `check*` methods
56
+
57
+ # Committers: 1
58
+
59
+ - Wim Selles ([@wswebcreation](https://github.com/wswebcreation))
60
+
3
61
  ## 1.1.2
4
62
 
5
63
  ### Patch Changes
package/dist/base.d.ts CHANGED
@@ -11,8 +11,8 @@ export default class BaseClass {
11
11
  private _setupFolders;
12
12
  /**
13
13
  * Clear the runtime folders (actual and diff)
14
- * @private
14
+ * @protected
15
15
  */
16
- private _clearRuntimeFolders;
16
+ protected _clearRuntimeFolders(): void;
17
17
  }
18
18
  //# sourceMappingURL=base.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAA;AAInF,MAAM,CAAC,OAAO,OAAO,SAAS;IAC1B,cAAc,EAAE,cAAc,CAAA;IAC9B,OAAO,EAAE,OAAO,CAAA;gBAEJ,OAAO,EAAE,YAAY;IAajC;;;OAGG;IACH,OAAO,CAAC,aAAa;IAgBrB;;;OAGG;IACH,OAAO,CAAC,oBAAoB;CAiB/B"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAA;AAInF,MAAM,CAAC,OAAO,OAAO,SAAS;IAC1B,cAAc,EAAE,cAAc,CAAA;IAC9B,OAAO,EAAE,OAAO,CAAA;gBAEJ,OAAO,EAAE,YAAY;IAQjC;;;OAGG;IACH,OAAO,CAAC,aAAa;IAgBrB;;;OAGG;IACH,SAAS,CAAC,oBAAoB,IAAI,IAAI;CAiBzC"}
package/dist/base.js CHANGED
@@ -12,10 +12,6 @@ export default class BaseClass {
12
12
  this.defaultOptions = defaultOptions(options);
13
13
  // Setup folder structure
14
14
  this.folders = this._setupFolders(options);
15
- // Clear runtime folders if requested
16
- if (options.clearRuntimeFolder) {
17
- this._clearRuntimeFolders();
18
- }
19
15
  }
20
16
  /**
21
17
  * Setup the folder structure for screenshots
@@ -36,7 +32,7 @@ export default class BaseClass {
36
32
  }
37
33
  /**
38
34
  * Clear the runtime folders (actual and diff)
39
- * @private
35
+ * @protected
40
36
  */
41
37
  _clearRuntimeFolders() {
42
38
  log.info('\x1b[33m\n##############################\n!!CLEARING RUNTIME FOLDERS!!\n##############################\x1b[0m');
package/dist/base.test.js CHANGED
@@ -35,11 +35,9 @@ describe('BaseClass', () => {
35
35
  expect(instance.folders.baselineFolder).toBe('functional/baseline');
36
36
  expect(instance.folders.actualFolder).toContain('functional/screenshots');
37
37
  });
38
- it('clears runtime folders if clearRuntimeFolder is true', () => {
39
- const options = {
40
- clearRuntimeFolder: true,
41
- };
42
- new BaseClass(options);
43
- expect(rmSync).toHaveBeenCalledTimes(2);
38
+ it('should not clear runtime folders in the constructor - clearing should only happen once in the launcher (issue #683)', () => {
39
+ vi.mocked(rmSync).mockClear();
40
+ new BaseClass({ clearRuntimeFolder: true });
41
+ expect(rmSync).not.toHaveBeenCalled();
44
42
  });
45
43
  });
@@ -1 +1 @@
1
- {"version":3,"file":"saveFullPageScreen.d.ts","sourceRoot":"","sources":["../../src/commands/saveFullPageScreen.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAA;AAGhF,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,sBAAsB,CAAA;AAI7E;;GAEG;AACH,wBAA8B,kBAAkB,CAC5C,EACI,eAAe,EACf,YAAY,EACZ,OAAO,EACP,GAAG,EACH,mBAAmB,EACnB,eAAe,GAClB,EAAE,iCAAiC,GACrC,OAAO,CAAC,gBAAgB,CAAC,CAuE3B"}
1
+ {"version":3,"file":"saveFullPageScreen.d.ts","sourceRoot":"","sources":["../../src/commands/saveFullPageScreen.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAA;AAGhF,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,sBAAsB,CAAA;AAI7E;;GAEG;AACH,wBAA8B,kBAAkB,CAC5C,EACI,eAAe,EACf,YAAY,EACZ,OAAO,EACP,GAAG,EACH,mBAAmB,EACnB,eAAe,GAClB,EAAE,iCAAiC,GACrC,OAAO,CAAC,gBAAgB,CAAC,CAsE3B"}
@@ -13,7 +13,6 @@ export default async function saveFullPageScreen({ browserInstance, instanceData
13
13
  throw new Error('The method saveFullPageScreen is not supported in native context for native mobile apps!');
14
14
  }
15
15
  // 2. Set some variables
16
- const { formatImageName, savePerInstance } = saveFullPageOptions.wic;
17
16
  const enableLegacyScreenshotMethod = getMethodOrWicOption(saveFullPageOptions.method, saveFullPageOptions.wic, 'enableLegacyScreenshotMethod');
18
17
  const fullPageScrollTimeout = getMethodOrWicOption(saveFullPageOptions.method, saveFullPageOptions.wic, 'fullPageScrollTimeout');
19
18
  const hideAfterFirstScroll = saveFullPageOptions.method.hideAfterFirstScroll || [];
@@ -54,7 +53,7 @@ export default async function saveFullPageScreen({ browserInstance, instanceData
54
53
  instanceData,
55
54
  enrichedInstanceData,
56
55
  beforeOptions,
57
- wicOptions: { formatImageName, savePerInstance, alwaysSaveActualImage: saveFullPageOptions.wic.alwaysSaveActualImage }
56
+ wicOptions: saveFullPageOptions.wic
58
57
  });
59
58
  return afterScreenshot(browserInstance, afterOptions);
60
59
  }
@@ -290,4 +290,20 @@ describe('saveFullPageScreen', () => {
290
290
  fileName: 'test-fullpage.png'
291
291
  });
292
292
  });
293
+ it('should pass through alwaysSaveActualImage value from options (service overrides for direct save* calls)', async () => {
294
+ const options = {
295
+ ...baseOptions,
296
+ saveFullPageOptions: {
297
+ ...baseOptions.saveFullPageOptions,
298
+ wic: {
299
+ ...baseOptions.saveFullPageOptions.wic,
300
+ alwaysSaveActualImage: false,
301
+ }
302
+ }
303
+ };
304
+ await saveFullPageScreen(options);
305
+ expect(buildAfterScreenshotOptionsSpy).toHaveBeenCalled();
306
+ const buildAfterScreenshotOptionsCall = buildAfterScreenshotOptionsSpy.mock.calls[buildAfterScreenshotOptionsSpy.mock.calls.length - 1];
307
+ expect(buildAfterScreenshotOptionsCall[0].wicOptions).toHaveProperty('alwaysSaveActualImage', false);
308
+ });
293
309
  });
@@ -9,7 +9,7 @@ import { createBeforeScreenshotOptions, buildAfterScreenshotOptions } from '../h
9
9
  */
10
10
  export default async function saveWebElement({ browserInstance, instanceData, folders, element, tag, saveElementOptions, }) {
11
11
  // 1. Set some variables
12
- const { addressBarShadowPadding, autoElementScroll, formatImageName, savePerInstance } = saveElementOptions.wic;
12
+ const { addressBarShadowPadding, autoElementScroll } = saveElementOptions.wic;
13
13
  const enableLegacyScreenshotMethod = getMethodOrWicOption(saveElementOptions.method, saveElementOptions.wic, 'enableLegacyScreenshotMethod');
14
14
  const resizeDimensions = saveElementOptions.method.resizeDimensions || DEFAULT_RESIZE_DIMENSIONS;
15
15
  // 2. Prepare the screenshot
@@ -47,7 +47,7 @@ export default async function saveWebElement({ browserInstance, instanceData, fo
47
47
  instanceData,
48
48
  enrichedInstanceData,
49
49
  beforeOptions,
50
- wicOptions: { formatImageName, savePerInstance, alwaysSaveActualImage: saveElementOptions.wic.alwaysSaveActualImage }
50
+ wicOptions: saveElementOptions.wic
51
51
  });
52
52
  return afterScreenshot(browserInstance, afterOptions);
53
53
  }
@@ -250,4 +250,20 @@ describe('saveWebElement', () => {
250
250
  expect(buildAfterScreenshotOptionsSpy.mock.calls[0][0]).toMatchSnapshot();
251
251
  expect(afterScreenshotSpy.mock.calls[0][1]).toMatchSnapshot();
252
252
  });
253
+ it('should pass through alwaysSaveActualImage value from options (service overrides for direct save* calls)', async () => {
254
+ const options = {
255
+ ...baseOptions,
256
+ saveElementOptions: {
257
+ ...baseOptions.saveElementOptions,
258
+ wic: {
259
+ ...baseOptions.saveElementOptions.wic,
260
+ alwaysSaveActualImage: false,
261
+ }
262
+ }
263
+ };
264
+ await saveWebElement(options);
265
+ expect(buildAfterScreenshotOptionsSpy).toHaveBeenCalled();
266
+ const buildAfterScreenshotOptionsCall = buildAfterScreenshotOptionsSpy.mock.calls[buildAfterScreenshotOptionsSpy.mock.calls.length - 1];
267
+ expect(buildAfterScreenshotOptionsCall[0].wicOptions).toHaveProperty('alwaysSaveActualImage', false);
268
+ });
253
269
  });
@@ -8,7 +8,7 @@ import { createBeforeScreenshotOptions, buildAfterScreenshotOptions } from '../h
8
8
  */
9
9
  export default async function saveWebScreen({ browserInstance, instanceData, folders, tag, saveScreenOptions, isNativeContext = false, }) {
10
10
  // 1. Set some variables
11
- const { addIOSBezelCorners, formatImageName, savePerInstance } = saveScreenOptions.wic;
11
+ const { addIOSBezelCorners } = saveScreenOptions.wic;
12
12
  const enableLegacyScreenshotMethod = getMethodOrWicOption(saveScreenOptions.method, saveScreenOptions.wic, 'enableLegacyScreenshotMethod');
13
13
  // 2. Prepare the screenshot
14
14
  const beforeOptions = createBeforeScreenshotOptions(instanceData, saveScreenOptions.method, saveScreenOptions.wic);
@@ -42,7 +42,7 @@ export default async function saveWebScreen({ browserInstance, instanceData, fol
42
42
  instanceData,
43
43
  enrichedInstanceData,
44
44
  beforeOptions,
45
- wicOptions: { formatImageName, savePerInstance, alwaysSaveActualImage: saveScreenOptions.wic.alwaysSaveActualImage }
45
+ wicOptions: saveScreenOptions.wic
46
46
  });
47
47
  return afterScreenshot(browserInstance, afterOptions);
48
48
  }
@@ -219,4 +219,19 @@ describe('saveWebScreen', () => {
219
219
  expect(takeWebScreenshotSpy.mock.calls[0]).toMatchSnapshot();
220
220
  expect(afterScreenshotSpy.mock.calls[0]).toMatchSnapshot();
221
221
  });
222
+ it('should pass through alwaysSaveActualImage value from options (service overrides for direct save* calls)', async () => {
223
+ const options = createTestOptions(baseOptions, {
224
+ saveScreenOptions: {
225
+ ...baseOptions.saveScreenOptions,
226
+ wic: {
227
+ ...baseOptions.saveScreenOptions.wic,
228
+ alwaysSaveActualImage: false,
229
+ }
230
+ }
231
+ });
232
+ await saveWebScreen(options);
233
+ expect(afterScreenshotSpy).toHaveBeenCalled();
234
+ const afterScreenshotCall = afterScreenshotSpy.mock.calls[afterScreenshotSpy.mock.calls.length - 1];
235
+ expect(afterScreenshotCall[1]).toHaveProperty('alwaysSaveActualImage', false);
236
+ });
222
237
  });
@@ -15,7 +15,6 @@ export declare const DEFAULT_COMPARE_OPTIONS: {
15
15
  ignoreNothing: boolean;
16
16
  rawMisMatchPercentage: boolean;
17
17
  returnAllCompareData: boolean;
18
- saveAboveTolerance: number;
19
18
  scaleImagesToSameSize: boolean;
20
19
  };
21
20
  export declare const DEFAULT_FORMAT_STRING = "{tag}-{browserName}-{width}x{height}-dpr-{dpr}";
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/helpers/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAA;AAC1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAA;AAE3E,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;CAenC,CAAA;AACD,eAAO,MAAM,qBAAqB,mDAAmD,CAAA;AACrF,eAAO,MAAM,uBAAuB,+CAA+C,CAAA;AACnF,eAAO,MAAM,OAAO;;;;;;;;CAQV,CAAA;AACV,eAAO,MAAM,cAAc;;;CAG1B,CAAA;AACD,eAAO,MAAM,OAAO,YAAY,CAAA;AAChC,eAAO,MAAM,SAAS,cAAc,CAAA;AACpC,eAAO,MAAM,aAAa,YAAY,CAAA;AACtC,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,gBAAgB,CAKhE,CAAA;AACD,eAAO,MAAM,wBAAwB,OAAO,CAAA;AAC5C,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;CAepC,CAAA;AACD,eAAO,MAAM,iBAAiB,EAAE,gBAS/B,CAAA;AAUD,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAU3B,CAAA;AAsCD,eAAO,MAAM,WAAW,EAAE,UAuQzB,CAAA;AAED,eAAO,MAAM,wBAAwB,UA2BpC,CAAA;AAED,eAAO,MAAM,oBAAoB,EAAE,WAqBlC,CAAA"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/helpers/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAA;AAC1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAA;AAE3E,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;CAcnC,CAAA;AACD,eAAO,MAAM,qBAAqB,mDAAmD,CAAA;AACrF,eAAO,MAAM,uBAAuB,+CAA+C,CAAA;AACnF,eAAO,MAAM,OAAO;;;;;;;;CAQV,CAAA;AACV,eAAO,MAAM,cAAc;;;CAG1B,CAAA;AACD,eAAO,MAAM,OAAO,YAAY,CAAA;AAChC,eAAO,MAAM,SAAS,cAAc,CAAA;AACpC,eAAO,MAAM,aAAa,YAAY,CAAA;AACtC,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,gBAAgB,CAKhE,CAAA;AACD,eAAO,MAAM,wBAAwB,OAAO,CAAA;AAC5C,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;CAepC,CAAA;AACD,eAAO,MAAM,iBAAiB,EAAE,gBAS/B,CAAA;AAUD,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAU3B,CAAA;AAsCD,eAAO,MAAM,WAAW,EAAE,UAuQzB,CAAA;AAED,eAAO,MAAM,wBAAwB,UA2BpC,CAAA;AAED,eAAO,MAAM,oBAAoB,EAAE,WAqBlC,CAAA"}
@@ -11,7 +11,6 @@ export const DEFAULT_COMPARE_OPTIONS = {
11
11
  ignoreNothing: false,
12
12
  rawMisMatchPercentage: false,
13
13
  returnAllCompareData: false,
14
- saveAboveTolerance: 0,
15
14
  scaleImagesToSameSize: false,
16
15
  };
17
16
  export const DEFAULT_FORMAT_STRING = '{tag}-{browserName}-{width}x{height}-dpr-{dpr}';
@@ -364,8 +364,10 @@ export interface CompareOptions {
364
364
  returnAllCompareData: boolean;
365
365
  /**
366
366
  * Mismatch percentage threshold above which the image with differences will be saved.
367
+ * When undefined, actual images won't be saved (respects alwaysSaveActualImage: false).
368
+ * Matchers set this value internally based on the expected threshold.
367
369
  */
368
- saveAboveTolerance: number;
370
+ saveAboveTolerance?: number;
369
371
  /**
370
372
  * Scale images to the same size before comparing them.
371
373
  */
@@ -1 +1 @@
1
- {"version":3,"file":"options.interfaces.d.ts","sourceRoot":"","sources":["../../src/helpers/options.interfaces.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"options.interfaces.d.ts","sourceRoot":"","sources":["../../src/helpers/options.interfaces.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,10 @@ import type { BaseExecuteCompareOptions, BuildBaseExecuteCompareOptionsOptions,
2
2
  import type { ClassOptions, CompareOptions } from './options.interfaces.js';
3
3
  import type { DeviceRectangles } from '../methods/rectangles.interfaces.js';
4
4
  import type { BaseDimensions } from '../base.interfaces.js';
5
+ /**
6
+ * Resolve the folder path without creating it on disk
7
+ */
8
+ export declare function getPath(folder: string, options: GetAndCreatePathOptions): string;
5
9
  /**
6
10
  * Get and create a folder
7
11
  */
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/helpers/utils.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACR,yBAAyB,EACzB,qCAAqC,EACrC,yBAAyB,EACzB,oBAAoB,EACpB,mBAAmB,EACnB,yBAAyB,EACzB,kCAAkC,EAClC,aAAa,EAEb,qBAAqB,EACrB,iCAAiC,EACjC,uBAAuB,EACvB,qBAAqB,EACrB,0BAA0B,EAC1B,gCAAgC,EAChC,8BAA8B,EAC9B,qBAAqB,EACrB,iCAAiC,EACjC,cAAc,EACjB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAI3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAA;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAI3D;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAczF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,MAAM,CAyCrE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE/D;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAExF;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAAC,SAAS,EAAE,OAAO,EAAE,mBAAmB,EAAE,OAAO,GAAG,OAAO,CAEzG;AAED;;GAEG;AACH,wBAAgB,kCAAkC,CAAC,SAAS,EAAE,OAAO,EAAE,mBAAmB,EAAE,OAAO,GAAG,OAAO,CAE5G;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,iCAAiC,GAAG,MAAM,CAQ7F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,8BAA8B,GAAG,MAAM,CASvF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,gBAAgB,EAAE,MAAM,GAAG,CAAC,CAMxE;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,iBAAiB,SAAI,GAAG,cAAc,CAKjG;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,gBAAgB,EAAE,cAAc,GAAG,MAAM,CAKhG;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,oBAAoB,EAAE,MAAM,GAAG,qBAAqB,CA4GzF;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAC,OAAO,6BAEpC;AAED;;GAEG;AACH,wBAAgB,WAAW,YAE1B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,YAEnC;AACD;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,YAAY,2BAgCnE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,EACtC,eAAe,EACf,KAAK,EACL,eAAe,GAClB,EAAE,0BAA0B,GAAG,OAAO,CAAC,cAAc,CAAC,CA6CtD;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkCrG;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBnH;AAED;;;;;;;;GAQG;AACH,wBAAsB,yBAAyB,CAAC,EAC5C,eAAe,EACf,uBAAuB,EACvB,SAAS,EACT,KAAK,EACL,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,WAAW,GACd,EAAE,gCAAgC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuC9D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,EACrD,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,EAC9B,GAAG,EAAE,CAAC,EACN,GAAG,EAAE,CAAC,GACP,CAAC,CAAC,CAAC,CAAC,CAEN;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,eAAe,EAAE,WAAW,CAAC,OAAO,GAAG,OAAO,CAMlF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,YAAY,EAAE,YAAY,EAAE,OAAO,GAAG,OAAO,CAE/G;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,EAAE,CAE9G;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,gBAAgB,EAAE,GAAG,GAAG,OAAO,CAElE;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACvC,OAAO,EAAE,kCAAkC,GAC5C,oBAAoB,CA6BtB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAC9B,OAAO,EAAE,yBAAyB,GACnC,aAAa,CAcf;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAC1C,OAAO,EAAE,qCAAqC,GAC/C,yBAAyB,CAyC3B;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,iCAAiC,GAAG,mBAAmB,CA2B1G"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/helpers/utils.ts"],"names":[],"mappings":"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"}
@@ -7,13 +7,19 @@ import { injectWebviewOverlay } from '../clientSideScripts/injectWebviewOverlay.
7
7
  import { getMobileWebviewClickAndDimensions } from '../clientSideScripts/getMobileWebviewClickAndDimensions.js';
8
8
  const log = logger('@wdio/visual-service:@wdio/image-comparison-core:utils');
9
9
  /**
10
- * Get and create a folder
10
+ * Resolve the folder path without creating it on disk
11
11
  */
12
- export function getAndCreatePath(folder, options) {
12
+ export function getPath(folder, options) {
13
13
  const { browserName = NOT_KNOWN, deviceName = NOT_KNOWN, isMobile, savePerInstance, } = options;
14
14
  const instanceName = (isMobile ? deviceName : `${DESKTOP}_${browserName}`).replace(/ /g, '_');
15
15
  const subFolder = savePerInstance ? instanceName : '';
16
- const folderName = join(folder, subFolder);
16
+ return join(folder, subFolder);
17
+ }
18
+ /**
19
+ * Get and create a folder
20
+ */
21
+ export function getAndCreatePath(folder, options) {
22
+ const folderName = getPath(folder, options);
17
23
  mkdirSync(folderName, { recursive: true });
18
24
  return folderName;
19
25
  }
@@ -553,7 +559,7 @@ export function prepareComparisonFilePaths(options) {
553
559
  const createFolderOptions = { browserName, deviceName, isMobile, savePerInstance };
554
560
  const actualFolderPath = getAndCreatePath(actualFolder, createFolderOptions);
555
561
  const baselineFolderPath = getAndCreatePath(baselineFolder, createFolderOptions);
556
- const diffFolderPath = getAndCreatePath(diffFolder, createFolderOptions);
562
+ const diffFolderPath = getPath(diffFolder, createFolderOptions);
557
563
  const actualFilePath = join(actualFolderPath, fileName);
558
564
  const baselineFilePath = join(baselineFolderPath, fileName);
559
565
  const diffFilePath = join(diffFolderPath, fileName);
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
- import { existsSync } from 'node:fs';
2
+ import { existsSync, mkdirSync } from 'node:fs';
3
3
  import { join } from 'node:path';
4
4
  vi.mock('node:fs', async () => {
5
5
  const actual = await vi.importActual('node:fs');
@@ -10,7 +10,7 @@ vi.mock('node:fs', async () => {
10
10
  };
11
11
  });
12
12
  import logger from '@wdio/logger';
13
- import { buildBaseExecuteCompareOptions, buildFolderOptions, calculateDprData, canUseBidiScreenshot, checkAndroidChromeDriverScreenshot, checkAndroidNativeWebScreenshot, checkTestInBrowser, checkTestInMobileBrowser, createConditionalProperty, executeNativeClick, extractCommonCheckVariables, formatFileName, getAddressBarShadowPadding, getAndCreatePath, getBase64ScreenshotSize, getBooleanOption, getDevicePixelRatio, getIosBezelImageNames, getMethodOrWicOption, getMobileScreenSize, getMobileViewPortPosition, getToolBarShadowPadding, hasResizeDimensions, isObject, isStorybook, loadBase64Html, logAllDeprecatedCompareOptions, updateVisualBaseline, } from './utils.js';
13
+ import { buildBaseExecuteCompareOptions, buildFolderOptions, calculateDprData, canUseBidiScreenshot, checkAndroidChromeDriverScreenshot, checkAndroidNativeWebScreenshot, checkTestInBrowser, checkTestInMobileBrowser, createConditionalProperty, executeNativeClick, extractCommonCheckVariables, formatFileName, getAddressBarShadowPadding, getAndCreatePath, getBase64ScreenshotSize, getBooleanOption, getDevicePixelRatio, getIosBezelImageNames, getMethodOrWicOption, getMobileScreenSize, getMobileViewPortPosition, getPath, getToolBarShadowPadding, hasResizeDimensions, isObject, isStorybook, loadBase64Html, logAllDeprecatedCompareOptions, prepareComparisonFilePaths, updateVisualBaseline, } from './utils.js';
14
14
  import { IMAGE_STRING } from '../mocks/image.js';
15
15
  import { DEVICE_RECTANGLES } from './constants.js';
16
16
  import { getMobileWebviewClickAndDimensions } from '../clientSideScripts/getMobileWebviewClickAndDimensions.js';
@@ -93,6 +93,93 @@ describe('utils', () => {
93
93
  expect(existsSync(folder)).toMatchSnapshot();
94
94
  });
95
95
  });
96
+ describe('getPath', () => {
97
+ const folder = join(process.cwd(), '/.tmp/utils');
98
+ it('should return the folder path for a mobile device with savePerInstance', () => {
99
+ const options = {
100
+ browserName: '',
101
+ deviceName: 'deviceName',
102
+ isMobile: true,
103
+ savePerInstance: true,
104
+ };
105
+ expect(getPath(folder, options)).toEqual(join(folder, options.deviceName));
106
+ });
107
+ it('should return the folder path for a desktop browser with savePerInstance', () => {
108
+ const options = {
109
+ browserName: 'browser',
110
+ deviceName: '',
111
+ isMobile: false,
112
+ savePerInstance: true,
113
+ };
114
+ expect(getPath(folder, options)).toEqual(join(folder, `desktop_${options.browserName}`));
115
+ });
116
+ it('should return the base folder when savePerInstance is false', () => {
117
+ const options = {
118
+ browserName: 'browser',
119
+ deviceName: '',
120
+ isMobile: false,
121
+ savePerInstance: false,
122
+ };
123
+ expect(getPath(folder, options)).toEqual(folder);
124
+ });
125
+ it('should not create any directories on disk', () => {
126
+ vi.mocked(mkdirSync).mockClear();
127
+ const options = {
128
+ browserName: 'chrome',
129
+ deviceName: '',
130
+ isMobile: false,
131
+ savePerInstance: true,
132
+ };
133
+ getPath(folder, options);
134
+ expect(mkdirSync).not.toHaveBeenCalled();
135
+ });
136
+ });
137
+ describe('prepareComparisonFilePaths', () => {
138
+ beforeEach(() => {
139
+ vi.mocked(mkdirSync).mockClear();
140
+ });
141
+ it('should create actual and baseline folders but not the diff folder', () => {
142
+ const options = {
143
+ actualFolder: '/tmp/actual',
144
+ baselineFolder: '/tmp/baseline',
145
+ diffFolder: '/tmp/diff',
146
+ browserName: 'chrome',
147
+ deviceName: '',
148
+ isMobile: false,
149
+ savePerInstance: false,
150
+ fileName: 'test.png',
151
+ };
152
+ const result = prepareComparisonFilePaths(options);
153
+ expect(result.actualFolderPath).toEqual('/tmp/actual');
154
+ expect(result.baselineFolderPath).toEqual('/tmp/baseline');
155
+ expect(result.diffFolderPath).toEqual('/tmp/diff');
156
+ expect(result.actualFilePath).toEqual(join('/tmp/actual', 'test.png'));
157
+ expect(result.baselineFilePath).toEqual(join('/tmp/baseline', 'test.png'));
158
+ expect(result.diffFilePath).toEqual(join('/tmp/diff', 'test.png'));
159
+ const mkdirCalls = vi.mocked(mkdirSync).mock.calls.map(call => call[0]);
160
+ expect(mkdirCalls).toContain('/tmp/actual');
161
+ expect(mkdirCalls).toContain('/tmp/baseline');
162
+ expect(mkdirCalls).not.toContain('/tmp/diff');
163
+ });
164
+ it('should include instance subfolder in paths when savePerInstance is true', () => {
165
+ const options = {
166
+ actualFolder: '/tmp/actual',
167
+ baselineFolder: '/tmp/baseline',
168
+ diffFolder: '/tmp/diff',
169
+ browserName: 'chrome',
170
+ deviceName: '',
171
+ isMobile: false,
172
+ savePerInstance: true,
173
+ fileName: 'test.png',
174
+ };
175
+ const result = prepareComparisonFilePaths(options);
176
+ expect(result.actualFolderPath).toEqual(join('/tmp/actual', 'desktop_chrome'));
177
+ expect(result.baselineFolderPath).toEqual(join('/tmp/baseline', 'desktop_chrome'));
178
+ expect(result.diffFolderPath).toEqual(join('/tmp/diff', 'desktop_chrome'));
179
+ const mkdirCalls = vi.mocked(mkdirSync).mock.calls.map(call => call[0]);
180
+ expect(mkdirCalls).not.toContain(join('/tmp/diff', 'desktop_chrome'));
181
+ });
182
+ });
96
183
  describe('formatFileName', () => {
97
184
  const formatFileOptions = {
98
185
  browserName: '',
@@ -1 +1 @@
1
- {"version":3,"file":"images.d.ts","sourceRoot":"","sources":["../../src/methods/images.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"images.d.ts","sourceRoot":"","sources":["../../src/methods/images.ts"],"names":[],"mappings":"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"}
@@ -620,14 +620,57 @@ describe('executeImageCompare', () => {
620
620
  });
621
621
  expect(fsPromises.writeFile).toHaveBeenCalledWith('/mock/actual/test.png', Buffer.from(base64Image, 'base64'));
622
622
  });
623
- it('should save base64 actual on diff when not always saving', async () => {
623
+ it('should NOT save base64 actual on diff when alwaysSaveActualImage is false and saveAboveTolerance is not set (#1115)', async () => {
624
+ // When alwaysSaveActualImage: false and saveAboveTolerance is not explicitly set,
625
+ // actual images should never be saved - respecting the literal meaning of the option
624
626
  const base64Image = Buffer.from('base64-image').toString('base64');
625
627
  const optionsWithDiff = {
626
628
  ...mockOptions,
627
629
  folderOptions: {
628
630
  ...mockOptions.folderOptions,
629
631
  alwaysSaveActualImage: false,
630
- }
632
+ },
633
+ compareOptions: {
634
+ ...mockOptions.compareOptions,
635
+ wic: {
636
+ ...mockOptions.compareOptions.wic,
637
+ saveAboveTolerance: undefined,
638
+ },
639
+ },
640
+ };
641
+ vi.mocked(compareImages.default).mockResolvedValue({
642
+ rawMisMatchPercentage: 0.5,
643
+ misMatchPercentage: 0.5,
644
+ getBuffer: vi.fn().mockResolvedValue(Buffer.from('diff-image-data')),
645
+ diffBounds: { left: 0, top: 0, right: 0, bottom: 0 },
646
+ analysisTime: 10,
647
+ diffPixels: []
648
+ });
649
+ await executeImageCompare({
650
+ isViewPortScreenshot: true,
651
+ isNativeContext: false,
652
+ options: optionsWithDiff,
653
+ testContext: mockTestContext,
654
+ actualBase64Image: base64Image,
655
+ });
656
+ expect(fsPromises.writeFile).not.toHaveBeenCalled();
657
+ });
658
+ it('should save base64 actual on diff when saveAboveTolerance is explicitly set to 0', async () => {
659
+ // When saveAboveTolerance is explicitly set (even to 0), save actual images when diff exceeds it
660
+ const base64Image = Buffer.from('base64-image').toString('base64');
661
+ const optionsWithDiff = {
662
+ ...mockOptions,
663
+ folderOptions: {
664
+ ...mockOptions.folderOptions,
665
+ alwaysSaveActualImage: false,
666
+ },
667
+ compareOptions: {
668
+ ...mockOptions.compareOptions,
669
+ wic: {
670
+ ...mockOptions.compareOptions.wic,
671
+ saveAboveTolerance: 0,
672
+ },
673
+ },
631
674
  };
632
675
  vi.mocked(compareImages.default).mockResolvedValue({
633
676
  rawMisMatchPercentage: 0.5,
@@ -315,10 +315,15 @@ export async function executeImageCompare({ isViewPortScreenshot, isNativeContex
315
315
  // 6. Generate and save the diff when there is a diff
316
316
  const { diffBoundingBoxes, storeDiffs } = await generateAndSaveDiff(data, imageCompareOptions, ignoredBoxes, diffFilePath, rawMisMatchPercentage);
317
317
  // 6a. Save actual image on failure if alwaysSaveActualImage is false
318
- const saveAboveTolerance = imageCompareOptions.saveAboveTolerance ?? 0;
319
- const hasFailure = rawMisMatchPercentage > saveAboveTolerance;
320
- if (useBase64Image && hasFailure && actualBase64Image) {
321
- // Save the actual image only when comparison fails
318
+ // Only save when saveAboveTolerance is explicitly set (e.g., by matchers).
319
+ // When using checkScreen directly without saveAboveTolerance, respect
320
+ // alwaysSaveActualImage: false literally and don't save actual images.
321
+ // @see https://github.com/webdriverio/visual-testing/issues/1115
322
+ const saveAboveTolerance = imageCompareOptions.saveAboveTolerance;
323
+ const shouldSaveOnFailure = saveAboveTolerance !== undefined;
324
+ const hasFailure = rawMisMatchPercentage > (saveAboveTolerance ?? 0);
325
+ if (useBase64Image && shouldSaveOnFailure && hasFailure && actualBase64Image) {
326
+ // Save the actual image only when comparison fails and threshold was explicitly set
322
327
  await saveBase64Image(actualBase64Image, actualFilePath);
323
328
  }
324
329
  // 7. Create JSON report if requested
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wdio/image-comparison-core",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "author": "Wim Selles - wswebcreation",
5
5
  "description": "Image comparison core module for @wdio/visual-service - WebdriverIO visual testing framework",
6
6
  "keywords": [