Skip to content

feat: add new package @wdio/image-comparison-core #982

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 70 commits into
base: ws/@wdio/image-comparison-core
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
3a90f87
feat: add new package @wdio/image-comparison-core
wswebcreation Jun 8, 2025
17f13e9
feat: update getMobileViewPortPosition
wswebcreation Jun 8, 2025
788379b
chore: replaced takeBase64Screenshot implementation
wswebcreation Jun 8, 2025
64a70fd
chore: fixed afterScreenshot
wswebcreation Jun 8, 2025
656b605
chore: updated beforeScreenshot
wswebcreation Jun 8, 2025
e7d24be
chore: clean saveWebScreen from methods
wswebcreation Jun 8, 2025
ea534d1
chore: update checkScreen
wswebcreation Jun 8, 2025
d45788d
chore: fix checkWebScreen
wswebcreation Jun 8, 2025
ce2924c
chore: fix saveElement and checkElement
wswebcreation Jun 8, 2025
465c237
chore: add full/tabbable page
wswebcreation Jun 8, 2025
b77d64a
chore: remove methods
wswebcreation Jun 8, 2025
fd08bab
chore: adjust the visual service to use the new core
wswebcreation Jun 8, 2025
4c02e6f
chore: migrated the service to the new module
wswebcreation Jun 8, 2025
bf53f12
chore: add browserInstance to the commands
wswebcreation Jun 8, 2025
e95aa5c
chore: added the browserinstance back and fix UTs
wswebcreation Jun 8, 2025
95dc2ae
fix UT's
wswebcreation Jun 8, 2025
90dfbef
fix tests
wswebcreation Jun 8, 2025
744ac3f
chore: cleanup methods
wswebcreation Jun 8, 2025
2ab6c0a
chore: remove webdriver-image-comparison
wswebcreation Jun 8, 2025
0f3c866
chore: multiple fixes
wswebcreation Jun 9, 2025
e955cdc
chore: fix UT's
wswebcreation Jun 9, 2025
816a4bb
chore: optimize types
wswebcreation Jun 9, 2025
e602d03
test: add tests vor checkAppElement
wswebcreation Jun 13, 2025
f90448c
chore: make private package public
wswebcreation Jun 13, 2025
9e3fe35
test: add checkAppScreen tests
wswebcreation Jun 13, 2025
8982a13
tesT: add new tests
wswebcreation Jun 13, 2025
90f61b3
chore: refactor mocks
wswebcreation Jun 13, 2025
bb4b1be
chore: simplify checks
wswebcreation Jun 13, 2025
3b00a1c
test: add checkScreen tests
wswebcreation Jun 13, 2025
812c15e
test: add checkTabbablePage
wswebcreation Jun 14, 2025
640dbe2
test: add checkWebElement
wswebcreation Jun 14, 2025
9e2f582
chore: revert Sauce tests
wswebcreation Jun 14, 2025
bb85362
test: add checkWebScreen
wswebcreation Jun 14, 2025
1f71dd7
test: add checkWebScreen tests
wswebcreation Jun 14, 2025
22db712
chore: update eslint
wswebcreation Jun 14, 2025
024ea95
test: add saveAppElement
wswebcreation Jun 14, 2025
8ecca36
chore: fix folders
wswebcreation Jun 14, 2025
0598825
chore: fix some tests
wswebcreation Jun 14, 2025
2271efa
test: add saveAppScreen
wswebcreation Jun 14, 2025
07a158c
test: add saveElement
wswebcreation Jun 14, 2025
c29a0d2
tesT: add saveFullPageScreen test
wswebcreation Jun 14, 2025
a4a55b6
test: add saveScreen tests
wswebcreation Jun 16, 2025
161fb34
test: add saveTabbablePage tests
wswebcreation Jun 16, 2025
25217ae
test: add saveWebElement tests
wswebcreation Jun 16, 2025
76af390
test: add saveWebScreen tests
wswebcreation Jun 16, 2025
103e869
chore: create BEFORE_SCREENSHOT_MOCK
wswebcreation Jun 16, 2025
d412d9b
chore: optimize mocks
wswebcreation Jun 16, 2025
9d22581
test: add drawTabbableOnCanvas tests
wswebcreation Jun 17, 2025
2ec9c98
test: add more tests drawTabbableOnCanvas
wswebcreation Jun 17, 2025
b54cf3d
test: add more tests for drawTabbableOnCanvas
wswebcreation Jun 17, 2025
9e90993
test: update drawTabbableOnCanvas
wswebcreation Jun 17, 2025
c2acf1a
chore: added todo's
wswebcreation Jun 17, 2025
4f1d58f
test: add scrollElementIntoView tests
wswebcreation Jun 17, 2025
ba3af64
test: add scrollToPosition tests
wswebcreation Jun 17, 2025
a5435e4
test: add createCompareReport tests
wswebcreation Jun 17, 2025
a6505b6
test: add processDiffPixels
wswebcreation Jun 18, 2025
ffcc1ca
test: add makeCroppedBase64Image tests
wswebcreation Jun 19, 2025
120e16d
test: add executeImageCompare tests
wswebcreation Jun 19, 2025
effd60e
test: add makeFullPageBase64Image tests
wswebcreation Jun 19, 2025
adbcf31
test: add takeResizedBase64Screenshot tests
wswebcreation Jun 19, 2025
61fecd0
fix: fix object comparison and add proper logging for takeBase64Eleme…
wswebcreation Jun 19, 2025
6484d58
test: add more tests for takeBase64ElementScreenshot
wswebcreation Jun 19, 2025
78e9899
fix: fix images tests
wswebcreation Jun 19, 2025
629fdc8
chore: use snapshots
wswebcreation Jun 20, 2025
cfcc1f2
test: add takeWebElementScreenshot tests
wswebcreation Jun 21, 2025
9a9a189
test: add logHiddenRemovedError
wswebcreation Jun 23, 2025
ef15aa9
test: add getDesktopFullPageScreenshotsData
wswebcreation Jun 23, 2025
1970366
test: add getAndroidChromeDriverFullPageScreenshotsData
wswebcreation Jun 23, 2025
36bf36f
test: add getMobileFullPageNativeWebScreenshotsData
wswebcreation Jun 24, 2025
37bb47a
chore: some small fixes
wswebcreation Jun 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@
"prepare": "husky",
"watch": "pnpm run -r --parallel watch"
},
"dependencies": {
"@wdio/ocr-service": "workspace:*",
"@wdio/visual-service": "workspace:*",
"webdriver-image-comparison": "workspace:*"
},
"devDependencies": {
"@changesets/cli": "^2.29.4",
"@tsconfig/node20": "^20.1.5",
Expand Down
12 changes: 12 additions & 0 deletions packages/image-comparison-core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
WebdriverIO Image Comparison Core
==========================

## Installation

The easiest way is to keep `@wdio/image-comparison-core` as a dev-dependency in your `package.json`, via:

```sh
npm install @wdio/image-comparison-core --save-dev
```

Instructions on how to get started can be found in the [visual testing](https://webdriver.io/docs/visual-testing) docs on the WebdriverIO project page.
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
{
"name": "webdriver-image-comparison",
"version": "9.0.4",
"name": "@wdio/image-comparison-core",
"version": "0.0.1",
"author": "Wim Selles - wswebcreation",
"description": "An image compare module that can be used for different NodeJS Test automation frameworks that support the webdriver protocol",
"keywords": [],
"description": "Image comparison core module for @wdio/visual-service - WebdriverIO visual testing framework",
"keywords": [
"webdriverio",
"wdio",
"visual-testing",
"image-comparison",
"screenshot",
"visual-regression",
"testing",
"automation"
],
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
Expand All @@ -27,10 +36,14 @@
"dependencies": {
"fs-extra": "^11.3.0",
"jimp": "^1.6.0",
"@wdio/logger": "^9.4.4"
"@wdio/logger": "^9.15.0",
"@wdio/types": "^9.15.0"
},
"devDependencies": {
"@types/fs-extra": "^11.0.4",
"webdriverio": "^9.14.0"
"webdriverio": "^9.15.0"
},
"publishConfig": {
"access": "public"
}
}
}
191 changes: 191 additions & 0 deletions packages/image-comparison-core/src/base.interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
export interface Folders {
/** The actual folder where the current screenshots need to be saved */
actualFolder: string;
/** The baseline folder where the baseline screenshots can be found */
baselineFolder: string;
/** The diff folder where the differences are saved */
diffFolder: string;
}

export interface BaseWebScreenshotOptions {
/**
* Disable the blinking cursor
* @default false
*/
disableBlinkingCursor?: boolean;
/**
* Disable all CSS animations
* @default false
*/
disableCSSAnimation?: boolean;
/**
* Make all text transparent to focus on layout
* @default false
*/
enableLayoutTesting?: boolean;
/**
* Use legacy screenshot method instead of BiDi protocol
* @default false
*/
enableLegacyScreenshotMethod?: boolean;
/**
* Hide all scrollbars
* @default true
*/
hideScrollBars?: boolean;
/**
* Elements to hide before taking screenshot
* @default []
*/
hideElements?: HTMLElement[];
/**
* Elements to remove before taking screenshot
* @default []
*/
removeElements?: HTMLElement[];
/**
* Wait for fonts to be loaded
* @default true
*/
waitForFontsLoaded?: boolean;
}

export interface BaseMobileWebScreenshotOptions {
/**
* Padding for the address bar shadow
* @default 6
*/
addressBarShadowPadding?: number;
/**
* Padding for the tool bar shadow
* @default 6
*/
toolBarShadowPadding?: number;
}

export interface BaseImageCompareOptions {
/**
* Compare images and discard alpha
* @default false
*/
ignoreAlpha?: boolean;
/**
* Compare images and discard anti aliasing
* @default false
*/
ignoreAntialiasing?: boolean;
/**
* Compare images in black and white mode
* @default false
*/
ignoreColors?: boolean;
/**
* Compare with reduced color sensitivity
* @default false
*/
ignoreLess?: boolean;
/**
* Compare with maximum sensitivity
* @default false
*/
ignoreNothing?: boolean;
/**
* Return raw mismatch percentage without rounding
* @default false
*/
rawMisMatchPercentage?: boolean;
/**
* Return all comparison data
* @default false
*/
returnAllCompareData?: boolean;
/**
* Save images only above this mismatch tolerance
* @default 0
*/
saveAboveTolerance?: number;
/**
* Scale images to same size before comparison
* @default false
*/
scaleImagesToSameSize?: boolean;
}

export interface BaseMobileBlockOutOptions {
/**
* Block out the side bar
* @default false
*/
blockOutSideBar?: boolean;
/**
* Block out the status bar
* @default false
*/
blockOutStatusBar?: boolean;
/**
* Block out the tool bar
* @default false
*/
blockOutToolBar?: boolean;
}

export interface BaseDeviceInfo {
/**
* The name of the browser
* @default ''
*/
browserName: string;
/**
* The name of the device
* @default ''
*/
deviceName: string;
/**
* The device pixel ratio
* @default 1
*/
devicePixelRatio: number;
/**
* Whether the device is Android
* @default false
*/
isAndroid: boolean;
/**
* Whether the device is iOS
* @default false
*/
isIOS: boolean;
/**
* Whether the device is mobile
* @default false
*/
isMobile: boolean;
}

export interface BaseCoordinates {
/** The x-coordinate */
x: number;
/** The y-coordinate */
y: number;
}

export interface BaseDimensions {
/** The width */
width: number;
/** The height */
height: number;
}

/** Base rectangle interface combining coordinates and dimensions */
export interface BaseRectangle extends BaseCoordinates, BaseDimensions {}

export interface BaseBoundingBox {
/** The bottom coordinate */
bottom: number;
/** The right coordinate */
right: number;
/** The left coordinate */
left: number;
/** The top coordinate */
top: number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,64 @@ import { FOLDERS } from './helpers/constants.js'
import type { Folders } from './base.interfaces.js'
import type { ClassOptions, DefaultOptions } from './helpers/options.interfaces.js'

const log = logger('@wdio/visual-service:webdriver-image-comparison')
const log = logger('@wdio/visual-service:@wdio/image-comparison-core')

export default class BaseClass {
defaultOptions: DefaultOptions
folders: Folders

constructor(options: ClassOptions) {
// determine default options
// Determine default options
this.defaultOptions = defaultOptions(options)

// Setup folder structure
this.folders = this._setupFolders(options)

// Clear runtime folders if requested
if (options.clearRuntimeFolder) {
this._clearRuntimeFolders()
}
}

/**
* Setup the folder structure for screenshots
* @private
*/
private _setupFolders(options: ClassOptions): Folders {
const baselineFolder = typeof options.baselineFolder === 'function'
? options.baselineFolder(options)
: normalize(options.baselineFolder || FOLDERS.DEFAULT.BASE)

const baseFolder = typeof options.screenshotPath === 'function'
? options.screenshotPath(options)
: normalize(options.screenshotPath || FOLDERS.DEFAULT.SCREENSHOTS)

this.folders = {
return {
actualFolder: join(baseFolder, FOLDERS.ACTUAL),
baselineFolder,
diffFolder: join(baseFolder, FOLDERS.DIFF),
}
}

if (options.clearRuntimeFolder) {
log.info('\x1b[33m\n##############################\n!!CLEARING!!\n##############################\x1b[0m')
/**
* Clear the runtime folders (actual and diff)
* @private
*/
private _clearRuntimeFolders(): void {
log.info('\x1b[33m\n##############################\n!!CLEARING RUNTIME FOLDERS!!\n##############################\x1b[0m')

try {
rmSync(this.folders.actualFolder, { recursive: true, force: true })
log.debug(`Cleared actual folder: ${this.folders.actualFolder}`)
} catch (error) {
log.warn(`Failed to clear actual folder ${this.folders.actualFolder}:`, error)
}

try {
rmSync(this.folders.diffFolder, { recursive: true, force: true })
log.debug(`Cleared diff folder: ${this.folders.diffFolder}`)
} catch (error) {
log.warn(`Failed to clear diff folder ${this.folders.diffFolder}:`, error)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import type { BaseCoordinates } from '../base.interfaces.js'

export interface ElementCoordinate extends BaseCoordinates{}
Loading