Skip to content

Fix for issues_657 and issue_983 #989

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 9 additions & 0 deletions .changeset/spotty-bananas-glow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@wdio/ocr-service": minor
---

\- improve typing for executor (as previously done in webdriverio package)

\- For both ocr-service and visual-service, the functions are now first add to the browser object and then to each instances to avoid having the loop for each instance in the command of a single instance (function with the loop no longer call itself like in the issue 657 and are now correctly declared to the correct element to fix issue 983)

\- Update the clean script for visual-reporter to work with Windows
39 changes: 22 additions & 17 deletions packages/ocr-service/src/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@ export default class WdioOcrService {
private _ocrDir: string
private _ocrLanguage: string
private _ocrContrast: number
private _isTesseractAvailable: boolean

constructor(options: OcrOptions) {
this._ocrDir = createOcrDir(options?.imagesFolder || DEFAULT_IMAGES_FOLDER)
this._ocrLanguage = options?.language || SUPPORTED_LANGUAGES.ENGLISH
this._ocrContrast = options?.contrast || CONTRAST
this._ocrLanguage = options?.language || SUPPORTED_LANGUAGES.ENGLISH
this._isTesseractAvailable = isSystemTesseractAvailable()
}

/**
Expand Down Expand Up @@ -58,45 +61,47 @@ export default class WdioOcrService {
const browserNames = Object.keys(capabilities)
const self = this
log.info(`Adding commands to Multi Browser: ${browserNames.join(', ')}`)

for (const browserName of browserNames) {
const multiremoteBrowser = browser as WebdriverIO.MultiRemoteBrowser
const browserInstance = multiremoteBrowser.getInstance(browserName)
await this.#addCommandsToBrowser(browserInstance)
}

/**
* Add all OCR commands to the global browser object that will execute
* on each browser in the Multi Remote.
* Add all commands to the global browser object that will execute on each browser in the Multi Remote.
*/
for (const command of Object.keys(ocrCommands)) {
browser.addCommand(command, async function (...args: unknown[]) {
for (const commandName of Object.keys(ocrCommands)) {
browser.addCommand(commandName, async function (...args: unknown[]) {
const returnData: Record<string, any> = {}

if (typeof args[0] === 'object' && args[0] !== null) {
const options = args[0] as Record<string, any>
options.ocrImagesPath = options?.imagesFolder || self._ocrDir
options.contrast = options?.contrast || self._ocrContrast
options.language = options?.language || self._ocrLanguage
options.isTesseractAvailable = self._isTesseractAvailable
args[0] = options
}

for (const browserName of browserNames) {
const multiremoteBrowser = browser as WebdriverIO.MultiRemoteBrowser
const browserInstance = multiremoteBrowser.getInstance(browserName) as WebdriverIO.Browser & Record<string, any>

if (typeof browserInstance[command] === 'function') {
returnData[browserName] = await browserInstance[command].apply(browserInstance, args)
if (typeof browserInstance[commandName] === 'function') {
returnData[browserName] = await browserInstance[commandName].apply(browserInstance, args)
} else {
throw new Error(`Command ${command} is not a function on the browser instance ${browserName}`)
throw new Error(`Command ${commandName} is not a function on the browser instance ${browserName}`)
}
}

return returnData
})
}
/**
* Add all commands to each instance (but Single Remote version)
*/
for (const browserName of browserNames) {
const multiremoteBrowser = browser as WebdriverIO.MultiRemoteBrowser
const browserInstance = multiremoteBrowser.getInstance(browserName)
await this.#addCommandsToBrowser(browserInstance)
}
}

async #addCommandsToBrowser(currentBrowser: WebdriverIO.Browser) {
const isTesseractAvailable = isSystemTesseractAvailable()
const self = this

for (const [commandName, command] of Object.entries(ocrCommands)) {
Expand All @@ -106,10 +111,10 @@ export default class WdioOcrService {
function (this: typeof currentBrowser, options) {
return command.bind(this)({
...options,
ocrImagesPath: self._ocrDir,
contrast: options?.contrast || self._ocrContrast,
isTesseractAvailable,
language: options?.language || self._ocrLanguage,
ocrImagesPath: self._ocrDir,
isTesseractAvailable: self._isTesseractAvailable
})
}
)
Expand Down
2 changes: 1 addition & 1 deletion packages/visual-reporter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"build": "run-s clean build:*",
"build:report": "remix vite:build",
"build:scripts": "tsc -p tsconfig.scripts.json",
"clean": "rimraf coverage build *.tsbuildinfo",
"clean": "rimraf coverage build --glob *.tsbuildinfo",
"dev": "cross-env VISUAL_REPORT_LOCAL_DEV=true run-s build:scripts script:prepare.report && run-p watch:scripts dev:remix",
"dev:remix": "remix vite:dev",
"script:prepare.report": "node ./dist/prepareReportAssets.js",
Expand Down
27 changes: 13 additions & 14 deletions packages/visual-service/src/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import logger from '@wdio/logger'
import { expect } from '@wdio/globals'
import { dirname, normalize, resolve } from 'node:path'
import type { Capabilities, Frameworks } from '@wdio/types'
import type { TransformElement } from 'webdriverio'
import {
BaseClass,
checkElement,
Expand Down Expand Up @@ -142,7 +143,14 @@ export default class WdioImageComparisonService extends BaseClass {
const browserNames = Object.keys(capabilities)

/**
* Add all the commands to each browser in the Multi Remote
* Add all commands to the global browser object that will execute on each browser in the Multi Remote.
*/
for (const [commandName, command] of Object.entries(pageCommands)) {
this.#addMultiremoteCommand(browser, browserNames, commandName, command)
}

/**
* Add all commands to each instance (but Single Remote version)
*/
for (const browserName of browserNames) {
log.info(`Adding commands to Multi Browser: ${browserName}`)
Expand All @@ -155,15 +163,6 @@ export default class WdioImageComparisonService extends BaseClass {
await this.#addCommandsToBrowser(browserInstance)
}

/**
* Add all the commands to the global browser object that will execute
* on each browser in the Multi Remote
* Start with the page commands
*/
for (const [commandName, command] of Object.entries(pageCommands)) {
this.#addMultiremoteCommand(browser, browserNames, commandName, command)
}

/**
* Add all the element commands to the global browser object that will execute
* on each browser in the Multi Remote
Expand Down Expand Up @@ -234,7 +233,7 @@ export default class WdioImageComparisonService extends BaseClass {
methods: {
bidiScreenshot: isBiDiScreenshotSupported(browser) ? this.browsingContextCaptureScreenshot.bind(browser) : undefined,
executor: <ReturnValue, InnerArguments extends unknown[]>(
fn: string | ((...args: InnerArguments) => ReturnValue),
fn: string | ((...innerArgs: TransformElement<InnerArguments>) => ReturnValue),
...args: InnerArguments
): Promise<ReturnValue> => {
return this.execute(fn, ...args) as Promise<ReturnValue>
Expand Down Expand Up @@ -311,7 +310,7 @@ export default class WdioImageComparisonService extends BaseClass {
methods: {
bidiScreenshot: isBiDiScreenshotSupported(browser) ? this.browsingContextCaptureScreenshot.bind(browser) : undefined,
executor: <ReturnValue, InnerArguments extends unknown[]>(
fn: string | ((...args: InnerArguments) => ReturnValue),
fn: string | ((...innerArgs: TransformElement<InnerArguments>) => ReturnValue),
...args: InnerArguments
): Promise<ReturnValue> => {
return this.execute(fn, ...args) as Promise<ReturnValue>
Expand Down Expand Up @@ -387,7 +386,7 @@ export default class WdioImageComparisonService extends BaseClass {
methods: {
bidiScreenshot: isBiDiScreenshotSupported(browserInstance) ? browserInstance.browsingContextCaptureScreenshot.bind(browserInstance) : undefined,
executor: <ReturnValue, InnerArguments extends unknown[]>(
fn: string | ((...args: InnerArguments) => ReturnValue),
fn: string | ((...innerArgs: TransformElement<InnerArguments>) => ReturnValue),
...args: InnerArguments
): Promise<ReturnValue> => {
return browserInstance.execute(fn, ...args) as Promise<ReturnValue>
Expand Down Expand Up @@ -480,7 +479,7 @@ export default class WdioImageComparisonService extends BaseClass {
methods: {
bidiScreenshot: isBiDiScreenshotSupported(browserInstance) ? browserInstance.browsingContextCaptureScreenshot.bind(browserInstance) : undefined,
executor: <ReturnValue, InnerArguments extends unknown[]>(
fn: string | ((...args: InnerArguments) => ReturnValue),
fn: string | ((...innerArgs: TransformElement<InnerArguments>) => ReturnValue),
...args: InnerArguments
): Promise<ReturnValue> => {
return browserInstance.execute(fn, ...args) as Promise<ReturnValue>
Expand Down
5 changes: 3 additions & 2 deletions packages/visual-service/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Capabilities } from '@wdio/types'
import type { AppiumCapabilities } from 'node_modules/@wdio/types/build/Capabilities.js'
import { getMobileScreenSize, getMobileViewPortPosition, IOS_OFFSETS, NOT_KNOWN } from 'webdriver-image-comparison'
import type { Folders, InstanceData, TestContext } from 'webdriver-image-comparison'
import type { TransformElement, TransformReturn } from 'webdriverio'
import type {
EnrichTestContextOptions,
getFolderMethodOptions,
Expand Down Expand Up @@ -70,8 +71,8 @@ async function getMobileInstanceData({

if (isMobile) {
const executor = <ReturnValue, InnerArguments extends unknown[]>(
fn: string | ((...args: InnerArguments) => ReturnValue),
...args: InnerArguments) => currentBrowser.execute(fn, ...args) as Promise<ReturnValue>
fn: string | ((...innerArgs: TransformElement<InnerArguments>) => ReturnValue),
...args: InnerArguments) => currentBrowser.execute(fn, ...args) as Promise<TransformReturn<ReturnValue>>
const getUrl = () => currentBrowser.getUrl()
const url = (arg:string) => currentBrowser.url(arg)
const currentDriverCapabilities = currentBrowser.capabilities
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import type { RectanglesOutput } from './rectangles.interfaces.js'

import type { TransformReturn, TransformElement } from 'webdriverio'
// There a multiple ways to call the executor method, for mobile and web
type ExecuteScript = <ReturnValue, Args extends unknown[]>(
fn: (...args: Args) => ReturnValue,
...args: Args
) => Promise<ReturnValue>;
type ExecuteScript = <ReturnValue, InnerArguments extends unknown[]>(
fn: (...innerArgs: TransformElement<InnerArguments>) => ReturnValue,
...args: InnerArguments
) => Promise<TransformReturn<ReturnValue>>;

type ExecuteMobile = <ReturnValue>(
fn: string,
args?: Record<string, any>
) => Promise<ReturnValue>;
) => Promise<TransformReturn<ReturnValue>>;
interface BrowsingContextCaptureScreenshotParameters {
context: string;
origin?: 'viewport' | 'document';
Expand Down
Loading