Skip to content

Commit d73691a

Browse files
committed
issue656_fix_attempt_1
1 parent 9e0f788 commit d73691a

File tree

8 files changed

+2414
-2340
lines changed

8 files changed

+2414
-2340
lines changed

packages/ocr-service/src/commands/ocrClickOnText.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,22 @@ import { determineClickPoint } from '../utils/index.js'
33
import type { OcrClickOnTextOptions } from '../types.js'
44
import { drawTarget } from '../utils/imageProcessing.js'
55

6-
export default async function ocrClickOnText(this: WebdriverIO.Browser, options: OcrClickOnTextOptions): Promise<void> {
7-
const element = await ocrGetElementPositionByText.bind(this)(options)
6+
export default async function ocrClickOnText(this: WebdriverIO.Browser, options: OcrClickOnTextOptions): Promise<void>
7+
export default async function ocrClickOnText(browser: WebdriverIO.Browser, options: OcrClickOnTextOptions): Promise<void>
8+
export default async function ocrClickOnText(this: WebdriverIO.Browser | undefined, arg1: WebdriverIO.Browser | OcrClickOnTextOptions, arg2?: OcrClickOnTextOptions): Promise<void> {
9+
let browserInstance: WebdriverIO.Browser
10+
let options: OcrClickOnTextOptions
11+
if (arg2 !== undefined) {
12+
browserInstance = arg1 as WebdriverIO.Browser
13+
options = arg2 as OcrClickOnTextOptions
14+
} else {
15+
if (this === undefined) {
16+
throw new Error('ocrClickOnText must be called as a WebdriverIO browser command or with a browser instance as the first argument.')
17+
}
18+
browserInstance = this as WebdriverIO.Browser
19+
options = arg1 as OcrClickOnTextOptions
20+
}
21+
const element = await ocrGetElementPositionByText(browserInstance, options)
822
let { x, y } = determineClickPoint({ rectangles: element.dprPosition })
923
const { relativePosition } = options
1024

@@ -18,10 +32,10 @@ export default async function ocrClickOnText(this: WebdriverIO.Browser, options:
1832
// Draw a target on the image so a user can see where the click will happen
1933
await drawTarget({ filePath: element.filePath, targetX: x, targetY: y })
2034

21-
const actionType = this.isMobile ? 'touch' : 'mouse'
35+
const actionType = browserInstance.isMobile ? 'touch' : 'mouse'
2236
const clickDuration = options.clickDuration ?? 500
2337

24-
await this
38+
await browserInstance
2539
.action('pointer', {
2640
parameters: { pointerType: actionType }
2741
})

packages/ocr-service/src/commands/ocrGetElementPositionByText.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,21 @@ import { fuzzyFind } from '../utils/fuzzySearch.js'
55

66
const log = logger('@wdio/ocr-service:ocrGetElementPositionByText')
77

8-
export default async function ocrGetElementPositionByText(
9-
this: WebdriverIO.Browser,
10-
data: OcrGetElementPositionByTextOptions
11-
): Promise<OcrGetElementPositionByText> {
8+
export default async function ocrGetElementPositionByText(this: WebdriverIO.Browser, data: OcrGetElementPositionByTextOptions): Promise<OcrGetElementPositionByText>
9+
export default async function ocrGetElementPositionByText(browser: WebdriverIO.Browser, data: OcrGetElementPositionByTextOptions): Promise<OcrGetElementPositionByText>
10+
export default async function ocrGetElementPositionByText(this: WebdriverIO.Browser | undefined, arg1: WebdriverIO.Browser | OcrGetElementPositionByTextOptions, arg2?: OcrGetElementPositionByTextOptions): Promise<OcrGetElementPositionByText> {
11+
let browserInstance: WebdriverIO.Browser
12+
let data: OcrGetElementPositionByTextOptions
13+
if (arg2 !== undefined) {
14+
browserInstance = arg1 as WebdriverIO.Browser
15+
data = arg2
16+
} else {
17+
if (this === undefined) {
18+
throw new Error('ocrGetElementPositionByText must be called as a WebdriverIO browser command or with a browser instance as the first argument.')
19+
}
20+
browserInstance = this as WebdriverIO.Browser
21+
data = arg1 as OcrGetElementPositionByTextOptions
22+
}
1223
const {
1324
contrast,
1425
haystack,
@@ -18,7 +29,7 @@ export default async function ocrGetElementPositionByText(
1829
ocrImagesPath,
1930
text,
2031
} = data
21-
const textPositions = await getTextPositions(this, {
32+
const textPositions = await getTextPositions(browserInstance, {
2233
contrast,
2334
haystack,
2435
isTesseractAvailable,
Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
11
import getData from '../utils/getData.js'
22
import type { OcrGetTextOptions } from '../types.js'
33

4-
export default async function ocrGetText(this: WebdriverIO.Browser, options: OcrGetTextOptions): Promise<string> {
5-
const { text } = await getData(this, options)
6-
4+
export default async function ocrGetText(this: WebdriverIO.Browser, options: OcrGetTextOptions): Promise<string>
5+
export default async function ocrGetText(browser: WebdriverIO.Browser, options: OcrGetTextOptions): Promise<string>
6+
export default async function ocrGetText(this: WebdriverIO.Browser | undefined, arg1: WebdriverIO.Browser | OcrGetTextOptions, arg2?: OcrGetTextOptions): Promise<string> {
7+
let browserInstance: WebdriverIO.Browser
8+
let options: OcrGetTextOptions
9+
if (arg2 !== undefined) {
10+
browserInstance = arg1 as WebdriverIO.Browser
11+
options = arg2
12+
} else {
13+
if (this === undefined) {
14+
throw new Error('ocrGetText must be called as a WebdriverIO browser command or with a browser instance as the first argument.')
15+
}
16+
browserInstance = this as WebdriverIO.Browser
17+
options = arg1 as OcrGetTextOptions
18+
}
19+
const { text } = await getData(browserInstance, options)
720
return text.replace(/\n\s*\n/g, '\n')
8-
}
21+
}

packages/ocr-service/src/commands/ocrSetValue.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,21 @@ import type { OcrSetValueOptions } from '../types.js'
22
import sendKeys from '../utils/sendKeys.js'
33
import ocrClickOnText from './ocrClickOnText.js'
44

5-
export default async function ocrSetValue(this: WebdriverIO.Browser, options: OcrSetValueOptions): Promise<void> {
5+
export default async function ocrSetValue(this: WebdriverIO.Browser, options: OcrSetValueOptions): Promise<void>
6+
export default async function ocrSetValue(browser: WebdriverIO.Browser, options: OcrSetValueOptions): Promise<void>
7+
export default async function ocrSetValue(this: WebdriverIO.Browser | undefined, arg1: WebdriverIO.Browser | OcrSetValueOptions, arg2?: OcrSetValueOptions): Promise<void> {
8+
let browserInstance: WebdriverIO.Browser
9+
let options: OcrSetValueOptions
10+
if (arg2 !== undefined) {
11+
browserInstance = arg1 as WebdriverIO.Browser
12+
options = arg2
13+
} else {
14+
if (this === undefined) {
15+
throw new Error('ocrSetValue must be called as a WebdriverIO browser command or with a browser instance as the first argument.')
16+
}
17+
browserInstance = this as WebdriverIO.Browser
18+
options = arg1 as OcrSetValueOptions
19+
}
620
const {
721
contrast,
822
clickDuration,
@@ -17,7 +31,7 @@ export default async function ocrSetValue(this: WebdriverIO.Browser, options: Oc
1731
} = options
1832

1933
// 1. First click on the position of the text to make sure it is intractable
20-
await ocrClickOnText.bind(this)({
34+
await ocrClickOnText(browserInstance, {
2135
contrast,
2236
clickDuration,
2337
haystack,
@@ -29,25 +43,25 @@ export default async function ocrSetValue(this: WebdriverIO.Browser, options: Oc
2943
})
3044

3145
// 2. If Mobile then a keyboard might be shown
32-
if (this.isMobile) {
46+
if (browserInstance.isMobile) {
3347
try {
3448
// Wait for 3 seconds for the keyboard to be shown
35-
await this.waitUntil(
36-
async () => this.isKeyboardShown(),
49+
await browserInstance.waitUntil(
50+
async () => browserInstance.isKeyboardShown(),
3751
{ timeout: 3 * 1000 })
3852
} catch (_ign) {
3953
// Keyboard is not shown
4054
}
4155
}
4256
// 3. Send the value to the active element
43-
await sendKeys(this, value, submitValue)
57+
await sendKeys(browserInstance, value, submitValue)
4458

4559
// 4. If Mobile then hide the keyboard
46-
if (this.isMobile) {
60+
if (browserInstance.isMobile) {
4761
try {
48-
await this.hideKeyboard()
49-
await this.waitUntil(
50-
async () => !(await this.isKeyboardShown()),
62+
await browserInstance.hideKeyboard()
63+
await browserInstance.waitUntil(
64+
async () => !(await browserInstance.isKeyboardShown()),
5165
{ timeout: 3 * 1000 })
5266
} catch (_ign) {
5367
// Keyboard is not present or not hidden

packages/ocr-service/src/commands/ocrWaitForTextDisplayed.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,28 @@
1-
import type { OcrWaitForTextDisplayedOptions } from '../types.js'
1+
import type { OcrWaitForTextDisplayedOptions, OcrGetElementPositionByText } from '../types.js'
22
import ocrGetElementPositionByText from './ocrGetElementPositionByText.js'
33

4-
export default async function ocrWaitForTextDisplayed(
5-
this: WebdriverIO.Browser,
6-
options: OcrWaitForTextDisplayedOptions
7-
) {
4+
export default async function ocrWaitForTextDisplayed(this: WebdriverIO.Browser, options: OcrWaitForTextDisplayedOptions): Promise<OcrGetElementPositionByText>
5+
export default async function ocrWaitForTextDisplayed(browser: WebdriverIO.Browser, options: OcrWaitForTextDisplayedOptions): Promise<OcrGetElementPositionByText>
6+
export default async function ocrWaitForTextDisplayed(this: WebdriverIO.Browser | undefined, arg1: WebdriverIO.Browser | OcrWaitForTextDisplayedOptions, arg2?: OcrWaitForTextDisplayedOptions): Promise<OcrGetElementPositionByText> {
7+
let browserInstance: WebdriverIO.Browser
8+
let options: OcrWaitForTextDisplayedOptions
9+
if (arg2 !== undefined) {
10+
browserInstance = arg1 as WebdriverIO.Browser
11+
options = arg2 as OcrWaitForTextDisplayedOptions
12+
} else {
13+
if (this === undefined) {
14+
throw new Error('ocrWaitForTextDisplayed must be called as a WebdriverIO browser command or with a browser instance as the first argument.')
15+
}
16+
browserInstance = this as WebdriverIO.Browser
17+
options = arg1 as OcrWaitForTextDisplayedOptions
18+
}
819
const { timeout, timeoutMsg } = options
920

10-
return this.waitUntil(
11-
async () => ocrGetElementPositionByText.bind(this)(options),
21+
return browserInstance.waitUntil(
22+
async () => {
23+
// Pass browserInstance directly as the first argument
24+
return ocrGetElementPositionByText(browserInstance, options)
25+
},
1226
{
1327
timeout: timeout || 180000,
1428
timeoutMsg: timeoutMsg || `Could not find the text "${options.text}" within the requested time.`,

packages/ocr-service/src/service.ts

Lines changed: 41 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import logger from '@wdio/logger'
2-
import type { Capabilities } from '@wdio/types'
32
import { isSystemTesseractAvailable } from './utils/tesseract.js'
43
import { CONTRAST, DEFAULT_IMAGES_FOLDER, SUPPORTED_LANGUAGES } from './utils/constants.js'
54
import { createOcrDir } from './utils/index.js'
@@ -9,26 +8,31 @@ import ocrGetElementPositionByText from './commands/ocrGetElementPositionByText.
98
import ocrWaitForTextDisplayed from './commands/ocrWaitForTextDisplayed.js'
109
import ocrClickOnText from './commands/ocrClickOnText.js'
1110
import ocrSetValue from './commands/ocrSetValue.js'
11+
import type { OcrGetTextOptions, OcrGetElementPositionByTextOptions, OcrWaitForTextDisplayedOptions, OcrClickOnTextOptions, OcrSetValueOptions } from './types.js'
1212

13-
const log = logger('@wdio/ocr-service')
14-
const ocrCommands = {
15-
ocrGetText,
16-
ocrGetElementPositionByText,
17-
ocrWaitForTextDisplayed,
18-
ocrClickOnText,
19-
ocrSetValue,
13+
const ocrCommands: {
14+
[key: string]: (context: any, options: any) => Promise<any>
15+
} = {
16+
'ocrGetText': async (context, options) => ocrGetText(context, options as OcrGetTextOptions),
17+
'ocrGetElementPositionByText': async (context, options) => ocrGetElementPositionByText(context, options as OcrGetElementPositionByTextOptions),
18+
'ocrWaitForTextDisplayed': async (context, options) => ocrWaitForTextDisplayed(context, options as OcrWaitForTextDisplayedOptions),
19+
'ocrClickOnText': async (context, options) => ocrClickOnText(context, options as OcrClickOnTextOptions),
20+
'ocrSetValue': async (context, options) => ocrSetValue(context, options as OcrSetValueOptions),
2021
}
2122

23+
const log = logger('@wdio/ocr-service')
24+
2225
export default class WdioOcrService {
23-
private _browser?: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser
2426
private _ocrDir: string
2527
private _ocrLanguage: string
2628
private _ocrContrast: number
29+
private _isTesseractAvailable: boolean
2730

2831
constructor(options: OcrOptions) {
2932
this._ocrDir = createOcrDir(options?.imagesFolder || DEFAULT_IMAGES_FOLDER)
30-
this._ocrLanguage = options?.language || SUPPORTED_LANGUAGES.ENGLISH
3133
this._ocrContrast = options?.contrast || CONTRAST
34+
this._ocrLanguage = options?.language || SUPPORTED_LANGUAGES.ENGLISH
35+
this._isTesseractAvailable = isSystemTesseractAvailable()
3236
}
3337

3438
/**
@@ -43,76 +47,44 @@ export default class WdioOcrService {
4347
_specs: string[],
4448
browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser
4549
) {
46-
this._browser = browser
47-
48-
if (!this._browser.isMultiremote) {
49-
log.info('Adding commands to global browser')
50-
await this.#addCommandsToBrowser(this._browser)
51-
} else {
52-
await this.#extendMultiremoteBrowser(capabilities as Capabilities.RequestedMultiremoteCapabilities)
53-
}
54-
}
55-
56-
async #extendMultiremoteBrowser (capabilities: Capabilities.RequestedMultiremoteCapabilities) {
57-
const browser = this._browser as WebdriverIO.MultiRemoteBrowser
58-
const browserNames = Object.keys(capabilities)
5950
const self = this
60-
log.info(`Adding commands to Multi Browser: ${browserNames.join(', ')}`)
61-
62-
for (const browserName of browserNames) {
63-
const multiremoteBrowser = browser as WebdriverIO.MultiRemoteBrowser
64-
const browserInstance = multiremoteBrowser.getInstance(browserName)
65-
await this.#addCommandsToBrowser(browserInstance)
66-
}
67-
51+
const browserNames = Object.keys(capabilities)
6852
/**
69-
* Add all OCR commands to the global browser object that will execute
70-
* on each browser in the Multi Remote.
53+
* Add all OCR commands to the browser object and instances
7154
*/
72-
for (const command of Object.keys(ocrCommands)) {
73-
browser.addCommand(command, async function (...args: unknown[]) {
74-
const returnData: Record<string, any> = {}
75-
55+
for (const commandName of Object.keys(ocrCommands)) {
56+
log.info(`Adding browser command "${commandName}" to browser object`)
57+
browser.addCommand(commandName, async function (
58+
this: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser,
59+
...args: unknown[]
60+
) {
7661
if (typeof args[0] === 'object' && args[0] !== null) {
7762
const options = args[0] as Record<string, any>
63+
options.ocrImagesPath = options?.imagesFolder || self._ocrDir
7864
options.contrast = options?.contrast || self._ocrContrast
65+
options.language = options?.language || self._ocrLanguage
66+
options.isTesseractAvailable = self._isTesseractAvailable
7967
args[0] = options
8068
}
81-
82-
for (const browserName of browserNames) {
83-
const multiremoteBrowser = browser as WebdriverIO.MultiRemoteBrowser
84-
const browserInstance = multiremoteBrowser.getInstance(browserName) as WebdriverIO.Browser & Record<string, any>
85-
86-
if (typeof browserInstance[command] === 'function') {
87-
returnData[browserName] = await browserInstance[command].apply(browserInstance, args)
88-
} else {
89-
throw new Error(`Command ${command} is not a function on the browser instance ${browserName}`)
69+
if (this.isMultiremote){
70+
const returnData: Record<string, any> = {}
71+
for (const browserName of browserNames) {
72+
const multiremoteBrowser = browser as WebdriverIO.MultiRemoteBrowser
73+
const browserInstance = multiremoteBrowser.getInstance(browserName) as WebdriverIO.Browser & Record<string, any>
74+
if (typeof browserInstance[commandName] === 'function') {
75+
returnData[browserName] = await browserInstance[commandName].call(browserInstance, args[0])
76+
} else {
77+
throw new Error(`Command ${commandName} is not a function on the browser instance ${browserName}`)
78+
}
9079
}
80+
return returnData
9181
}
92-
93-
return returnData
94-
})
95-
}
96-
}
97-
98-
async #addCommandsToBrowser(currentBrowser: WebdriverIO.Browser) {
99-
const isTesseractAvailable = isSystemTesseractAvailable()
100-
const self = this
101-
102-
for (const [commandName, command] of Object.entries(ocrCommands)) {
103-
log.info(`Adding browser command "${commandName}" to browser object`)
104-
currentBrowser.addCommand(
105-
commandName,
106-
function (this: typeof currentBrowser, options) {
107-
return command.bind(this)({
108-
...options,
109-
contrast: options?.contrast || self._ocrContrast,
110-
isTesseractAvailable,
111-
language: options?.language || self._ocrLanguage,
112-
ocrImagesPath: self._ocrDir,
113-
})
82+
const handler = ocrCommands[commandName]
83+
if (handler) {
84+
return await handler(this, args[0])
11485
}
115-
)
86+
throw new Error(`Command ${commandName} is not a function of browser.`)
87+
})
11688
}
11789
}
11890
}

0 commit comments

Comments
 (0)