Skip to content
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

Ws/fix-747-improve-mobile-webview-screenshot #777

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
b247eea
chore: update deps
wswebcreation Mar 15, 2025
94e400f
chore: revert major eslint
wswebcreation Mar 15, 2025
4722216
feat: initial setup for device layer calculations
wswebcreation Mar 16, 2025
867ee1b
chore: fixed some stuff and updated some broken UT's
wswebcreation Mar 16, 2025
ccb3609
fix: right import and export
wswebcreation Mar 16, 2025
26fbf99
fix: fix mocks
wswebcreation Mar 16, 2025
bcaeaa4
chore: optimise code a bit and add docs
wswebcreation Mar 17, 2025
f533196
chore: fix linking and types
wswebcreation Mar 17, 2025
ce869d9
fix: fix return data from overlay
wswebcreation Mar 17, 2025
ade0343
feat: add Android support for blockouts based on device rectangles
wswebcreation Mar 17, 2025
1afd8b3
feat: support ios and android for checkScreen
wswebcreation Mar 17, 2025
bd1cbd8
feat: add checkElement support
wswebcreation Mar 17, 2025
dc9a3fb
fix: optimise code and fix UTs for element
wswebcreation Mar 17, 2025
14731c4
feat: support savefullpagescreenshot with new viewport data for Android
wswebcreation Mar 18, 2025
1c6ebee
feat: support fullpage for iOS portrait
wswebcreation Mar 18, 2025
bfab8c2
test: fix tests
wswebcreation Mar 18, 2025
5d46b3b
fix: multiple fixes for fullpage
wswebcreation Mar 19, 2025
a32e458
chore: remove logs
wswebcreation Mar 19, 2025
311794d
fix: fix Android Appium 1 issues
wswebcreation Mar 23, 2025
fa0537c
chore: update iOS stuff
wswebcreation Mar 24, 2025
9e5f7b9
chore: updated safari desktop screenshots
wswebcreation Mar 25, 2025
a67b457
Merge branch 'main' into ws/fix-747-improve-mobile-webview-screenshot
wswebcreation Mar 25, 2025
bcb31d5
test: update snapshots
wswebcreation Mar 25, 2025
6cb30b6
Merge branch 'main' into ws/fix-747-improve-mobile-webview-screenshot
wswebcreation Mar 28, 2025
f6b0713
feat: move the new logic to the webdriver-image-comparison module
wswebcreation Mar 29, 2025
37d2244
fix: fix unit tests
wswebcreation Mar 29, 2025
099ab9f
breaking: taking element screenshot for iOS
wswebcreation Mar 30, 2025
4c49179
chore: optimise deviceRectangles
wswebcreation Mar 30, 2025
c87255b
chore: refactor stuff
wswebcreation Mar 30, 2025
7659ad9
chore: improve readability for vars in utils
wswebcreation Mar 31, 2025
0617938
chore: update baseline and workflow
wswebcreation Apr 3, 2025
48ffabc
chore: last image updates
wswebcreation Apr 4, 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
6 changes: 3 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ jobs:
LAMBDATEST_USERNAME: ${{ secrets.LAMBDATEST_USERNAME }}
LAMBDATEST_ACCESS_KEY: ${{ secrets.LAMBDATEST_ACCESS_KEY }}
BUILD_PREFIX: true
run: pnpm test.lambdatest.desktop --maxConcurrency=3
run: pnpm test.lambdatest.desktop --maxConcurrency=4

- name: 📤 Upload artifacts
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -239,7 +239,7 @@ jobs:
LAMBDATEST_USERNAME: ${{ secrets.LAMBDATEST_USERNAME }}
LAMBDATEST_ACCESS_KEY: ${{ secrets.LAMBDATEST_ACCESS_KEY }}
BUILD_PREFIX: true
run: pnpm test.lambdatest.emu.web --maxConcurrency=4
run: pnpm test.lambdatest.emu.web --maxConcurrency=6

- name: 📤 Upload artifacts
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -302,7 +302,7 @@ jobs:
LAMBDATEST_USERNAME: ${{ secrets.LAMBDATEST_USERNAME }}
LAMBDATEST_ACCESS_KEY: ${{ secrets.LAMBDATEST_ACCESS_KEY }}
BUILD_PREFIX: true
run: pnpm test.lambdatest.sims.web --maxConcurrency=4
run: pnpm test.lambdatest.sims.web --maxConcurrency=6

- name: 📤 Upload artifacts
uses: actions/upload-artifact@v4
Expand Down
42 changes: 21 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"scripts": {
"build": "pnpm run -r build",
"build:reporter": "node ./packages/visual-reporter/dist/cli.js --jsonOutput=.tmp/actual/output.json --reportFolder=.tmp/ --logLevel=debug",
"clean": "rimraf coverage dist .tmp '**/dist'",
"clean": "rimraf coverage dist .tmp **/dist",
"release": "run-s build && changeset publish",
"test": "run-s test:*",
"test:lint": "rimraf .eslintcache && eslint packages tests",
Expand Down Expand Up @@ -56,43 +56,43 @@
"webdriver-image-comparison": "workspace:*"
},
"devDependencies": {
"@changesets/cli": "^2.27.12",
"@changesets/cli": "^2.28.1",
"@tsconfig/node20": "^20.1.4",
"@types/eslint": "^9.6.1",
"@types/inquirer": "^9.0.7",
"@types/jsdom": "~21.1.7",
"@types/node": "^22",
"@types/xml2js": "~0.4.14",
"@typescript-eslint/eslint-plugin": "^8.24.0",
"@typescript-eslint/parser": "^8.24.0",
"@typescript-eslint/utils": "^8.24.0",
"@typescript-eslint/eslint-plugin": "^8.26.1",
"@typescript-eslint/parser": "^8.26.1",
"@typescript-eslint/utils": "^8.26.1",
"@vitest/coverage-v8": "^3.0.8",
"@vitest/ui": "^3.0.8",
"@wdio/appium-service": "^9.9.1",
"@wdio/cli": "^9.9.1",
"@wdio/globals": "^9.9.1",
"@wdio/local-runner": "^9.9.1",
"@wdio/mocha-framework": "^9.9.0",
"@wdio/sauce-service": "^9.9.1",
"@wdio/shared-store-service": "^9.9.1",
"@wdio/spec-reporter": "^9.9.0",
"@wdio/types": "^9.9.0",
"@wdio/appium-service": "^9.12.0",
"@wdio/cli": "^9.12.0",
"@wdio/globals": "^9.12.0",
"@wdio/local-runner": "^9.12.0",
"@wdio/mocha-framework": "^9.11.0",
"@wdio/sauce-service": "^9.12.0",
"@wdio/shared-store-service": "^9.12.0",
"@wdio/spec-reporter": "^9.11.0",
"@wdio/types": "^9.10.1",
"cross-env": "^7.0.3",
"eslint": "^9.20.1",
"eslint": "^9.22.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-unicorn": "^56.0.1",
"eslint-plugin-wdio": "^9.9.1",
"husky": "^9.1.7",
"jsdom": "^25.0.1",
"jsdom": "^26.0.0",
"npm-run-all2": "^7.0.2",
"release-it": "^17.11.0",
"release-it": "^18.1.2",
"rimraf": "^6.0.1",
"saucelabs": "^8.0.0",
"saucelabs": "^9.0.2",
"ts-node": "^10.9.2",
"typescript": "^5.7.3",
"typescript": "^5.8.2",
"vitest": "^3.0.8",
"wdio-lambdatest-service": "^4.0.0",
"webdriverio": "^9.9.1"
"webdriverio": "^9.12.0",
"wdio-lambdatest-service": "^4.0.0"
},
"packageManager": "[email protected]+sha256.cf86a7ad764406395d4286a6d09d730711720acc6d93e9dce9ac7ac4dc4a28a7"
}
6 changes: 3 additions & 3 deletions packages/ocr-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@
"watch": "pnpm run build:tsc -w"
},
"dependencies": {
"@wdio/globals": "^9.9.1",
"@wdio/globals": "^9.12.0",
"@wdio/logger": "^9.4.4",
"@wdio/types": "^9.9.0",
"@wdio/types": "^9.10.1",
"fuse.js": "^7.1.0",
"@inquirer/prompts": "7.3.2",
"@inquirer/prompts": "7.3.3",
"jimp": "^1.6.0",
"node-tesseract-ocr": "^2.2.1",
"tesseract.js": "^5.1.1",
Expand Down
4 changes: 2 additions & 2 deletions packages/ocr-service/src/utils/getData.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logger from '@wdio/logger'
import { getNodeOcrData, getSystemOcrData } from './tesseract.js'
import type { GetOcrData, Line, GetData, GetDataOptions, RectReturn, Words } from '../types.js'
import { adjustElementBbox, getScreenshotSize, isRectanglesObject } from './index.js'
import { adjustElementBbox, getBase64ScreenshotSize, isRectanglesObject } from './index.js'
import { drawHighlightedWords, processImage } from './imageProcessing.js'

const log = logger('@wdio/ocr-service:getData')
Expand All @@ -22,7 +22,7 @@ export default async function getData(browser: WebdriverIO.Browser, options: Get
if (!cliFile) {
const screenSize = await browser.getWindowSize()
screenshot = await browser.takeScreenshot()
const { width } = getScreenshotSize(screenshot)
const { width } = getBase64ScreenshotSize(screenshot)
dpr = width / screenSize.width
} else {
screenshot = cliFile
Expand Down
2 changes: 1 addition & 1 deletion packages/ocr-service/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { mkdirSync } from 'node:fs'
import type { ChainablePromiseElement } from 'webdriverio'
import type { ClickPoint, DetermineClickPointOptions, Rectangles, RectReturn, ScreenshotSize } from '../types.js'

export function getScreenshotSize(screenshot: string): ScreenshotSize {
export function getBase64ScreenshotSize(screenshot: string): ScreenshotSize {
return {
height: Math.round(Buffer.from(screenshot, 'base64').readUInt32BE(20)),
width: Math.round(Buffer.from(screenshot, 'base64').readUInt32BE(16)),
Expand Down
10 changes: 5 additions & 5 deletions packages/ocr-service/tests/utils/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { mkdirSync } from 'node:fs'
import { describe, it, expect, vi } from 'vitest'
import { adjustElementBbox, createOcrDir, determineClickPoint, getDprPositions, getScreenshotSize, isRectanglesObject } from '../../src/utils/index.js'
import { adjustElementBbox, createOcrDir, determineClickPoint, getDprPositions, getBase64ScreenshotSize, isRectanglesObject } from '../../src/utils/index.js'
import type { RectReturn } from '../../src/types.js'

vi.mock('node:fs', () => ({
Expand All @@ -15,26 +15,26 @@ function createMockScreenshot(width: number, height: number): string {
return buffer.toString('base64')
}

describe('getScreenshotSize', () => {
describe('getBase64ScreenshotSize', () => {
it('should correctly extract dimensions from a valid screenshot', () => {
const width = 800
const height = 600
const base64 = createMockScreenshot(width, height)
const result = getScreenshotSize(base64)
const result = getBase64ScreenshotSize(base64)

expect(result).toEqual({ width: width, height: height })
})

it('should handle invalid base64 strings gracefully', () => {
const invalidBase64 = 'not-a-real-base64-string'
const action = () => getScreenshotSize(invalidBase64)
const action = () => getBase64ScreenshotSize(invalidBase64)

expect(action).toThrowError()
})

it('should handle unexpected data layout', () => {
const malformedBase64 = Buffer.from([1, 2, 3, 4, 5]).toString('base64')
const action = () => getScreenshotSize(malformedBase64)
const action = () => getBase64ScreenshotSize(malformedBase64)

expect(action).toThrowError()
})
Expand Down
18 changes: 9 additions & 9 deletions packages/ocr-service/tests/utils/ocrGetData.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { describe, it, expect, vi, beforeEach } from 'vitest'
import getData from '../../src/utils/getData.js'
import * as Tesseract from '../../src/utils/tesseract.js'
import * as ImageProcessing from '../../src/utils/imageProcessing.js'
import { adjustElementBbox, getScreenshotSize, isRectanglesObject } from '../../src/utils/index.js'
import { adjustElementBbox, getBase64ScreenshotSize, isRectanglesObject } from '../../src/utils/index.js'

const browser = wdioBrowser
const log = logger('test')
Expand All @@ -15,7 +15,7 @@ vi.mock('../../src/utils/tesseract.js')
vi.mock('../../src/utils/imageProcessing.js')
vi.mock('../../src/utils/index.js')
vi.mock('webdriver-image-comparison/dist/helpers/utils', () => ({
getScreenshotSize: vi.fn(() => ({ width: 1200 })),
getBase64ScreenshotSize: vi.fn(() => ({ width: 1200 })),
}))
vi.mock('../../src/utils/tesseract.js', () => ({
getNodeOcrData: vi.fn().mockResolvedValue({
Expand All @@ -42,7 +42,7 @@ vi.mock('@wdio/globals', () => ({
isAndroid: false,
isIOS: false,
getElementRect:vi.fn().mockResolvedValue({ x: 10, y: 20, width: 300, height: 400 }),
getScreenshotSize:vi.fn().mockReturnValue({ width: 1200 }),
getBase64ScreenshotSize:vi.fn().mockReturnValue({ width: 1200 }),
getWindowSize: vi.fn().mockResolvedValue({ width: 1200, height: 800 }),
takeScreenshot:vi.fn().mockResolvedValue('screenshotData'),
}
Expand All @@ -61,13 +61,13 @@ describe('getData', () => {
language: 'ENG',
ocrImagesPath: '/fake/ocr/path'
}
vi.mocked(getScreenshotSize).mockReturnValue({ height: 1200, width: 1200 })
vi.mocked(getBase64ScreenshotSize).mockReturnValue({ height: 1200, width: 1200 })

const result = await getData(browser, options)

expect(browser.getWindowSize).toHaveBeenCalled()
expect(browser.takeScreenshot).toHaveBeenCalled()
expect(getScreenshotSize).toHaveBeenCalledWith('screenshotData')
expect(getBase64ScreenshotSize).toHaveBeenCalledWith('screenshotData')
expect(isRectanglesObject).not.toHaveBeenCalled()
expect(ImageProcessing.processImage).toHaveBeenCalledTimes(1)
expect(Tesseract.getSystemOcrData).toHaveBeenCalledWith({
Expand All @@ -87,13 +87,13 @@ describe('getData', () => {
language: 'ENG',
ocrImagesPath: '/fake/ocr/path'
}
vi.mocked(getScreenshotSize).mockReturnValue({ height: 1200, width: 1200 })
vi.mocked(getBase64ScreenshotSize).mockReturnValue({ height: 1200, width: 1200 })

const result = await getData(browser, options)

expect(browser.getWindowSize).toHaveBeenCalled()
expect(browser.takeScreenshot).toHaveBeenCalled()
expect(getScreenshotSize).toHaveBeenCalledWith('screenshotData')
expect(getBase64ScreenshotSize).toHaveBeenCalledWith('screenshotData')
expect(isRectanglesObject).not.toHaveBeenCalled()
expect(ImageProcessing.processImage).toHaveBeenCalledTimes(1)
expect(Tesseract.getNodeOcrData).toHaveBeenCalledWith({
Expand All @@ -114,13 +114,13 @@ describe('getData', () => {
language: 'ENG',
ocrImagesPath: '/fake/ocr/path'
}
vi.mocked(getScreenshotSize).mockReturnValue({ height: 1200, width: 1200 })
vi.mocked(getBase64ScreenshotSize).mockReturnValue({ height: 1200, width: 1200 })

const result = await getData(browser, options)

expect(browser.getWindowSize).toHaveBeenCalled()
expect(browser.takeScreenshot).toHaveBeenCalled()
expect(getScreenshotSize).toHaveBeenCalledWith('screenshotData')
expect(getBase64ScreenshotSize).toHaveBeenCalledWith('screenshotData')
expect(isRectanglesObject).toHaveBeenCalledTimes(1)
expect(ImageProcessing.processImage).toHaveBeenCalledTimes(2)
expect(Tesseract.getSystemOcrData).toHaveBeenCalledWith({
Expand Down
36 changes: 18 additions & 18 deletions packages/visual-reporter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,39 +29,39 @@
"watch:scripts": "npm run build:scripts --watch"
},
"dependencies": {
"@inquirer/prompts": "^7.3.2",
"@inquirer/prompts": "^7.3.3",
"ora": "^8.2.0",
"sirv-cli": "^3.0.0",
"sirv-cli": "^3.0.1",
"sharp": "^0.33.5"
},
"devDependencies": {
"@remix-run/node": "^2.15.3",
"@remix-run/react": "^2.15.3",
"@remix-run/serve": "^2.15.3",
"@remix-run/dev": "^2.15.3",
"@remix-run/node": "^2.16.0",
"@remix-run/react": "^2.16.0",
"@remix-run/serve": "^2.16.0",
"@remix-run/dev": "^2.16.0",
"@types/react": "^18.3.18",
"@types/react-dom": "^18.3.5",
"@typescript-eslint/eslint-plugin": "^8.24.0",
"@typescript-eslint/parser": "^8.24.0",
"autoprefixer": "^10.4.20",
"eslint": "^9.20.1",
"eslint-import-resolver-typescript": "^3.8.0",
"@typescript-eslint/eslint-plugin": "^8.26.1",
"@typescript-eslint/parser": "^8.26.1",
"autoprefixer": "^10.4.21",
"eslint": "^9.22.0",
"eslint-import-resolver-typescript": "^3.9.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react": "^7.37.4",
"eslint-plugin-react-hooks": "^5.1.0",
"isbot": "^5.1.22",
"postcss": "^8.5.2",
"eslint-plugin-react-hooks": "^5.2.0",
"isbot": "^5.1.23",
"postcss": "^8.5.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.4.0",
"react-select": "^5.10.0",
"react-icons": "^5.5.0",
"react-select": "^5.10.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.3",
"typescript": "^5.8.2",
"vite": "^5.4.15",
"vite-tsconfig-paths": "^5.1.4"
},
"engines": {
"node": ">=20.0.0"
}
}
}
4 changes: 2 additions & 2 deletions packages/visual-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
"watch": "pnpm run build:tsc -w"
},
"dependencies": {
"@wdio/globals": "^9.9.1",
"@wdio/globals": "^9.12.0",
"@wdio/logger": "^9.4.4",
"@wdio/types": "^9.9.0",
"@wdio/types": "^9.10.1",
"webdriver-image-comparison": "workspace:*"
},
"devDependencies": {}
Expand Down
18 changes: 15 additions & 3 deletions packages/visual-service/src/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,12 +172,16 @@ export default class WdioImageComparisonService extends BaseClass {
* Add commands to the "normal" browser object
*/
async #addCommandsToBrowser(currentBrowser: WebdriverIO.Browser) {
const instanceData = await getInstanceData(currentBrowser)
const isNativeContext = getNativeContext(
this.#browser as WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser,
currentBrowser,
this._isNativeContext as NativeContextType
)
const instanceData = await getInstanceData({
currentBrowser,
initialDeviceRectangles: this.deviceRectangles,
isNativeContext,
})

for (const [commandName, command] of Object.entries(elementCommands)) {
this.#addElementCommand(currentBrowser, commandName, command, instanceData, isNativeContext)
Expand Down Expand Up @@ -309,7 +313,11 @@ export default class WdioImageComparisonService extends BaseClass {
browserInstance,
self._isNativeContext as NativeContextType
)
const instanceData = await getInstanceData(browserInstance)
const instanceData = await getInstanceData({
currentBrowser: browserInstance,
initialDeviceRectangles: self.deviceRectangles,
isNativeContext
})

returnData[browserName] = await command(
{
Expand Down Expand Up @@ -369,7 +377,11 @@ export default class WdioImageComparisonService extends BaseClass {
browserInstance,
self._isNativeContext as NativeContextType
)
const instanceData = await getInstanceData(browserInstance)
const instanceData = await getInstanceData({
currentBrowser: browserInstance,
initialDeviceRectangles: self.deviceRectangles,
isNativeContext
})

returnData[browserName] = await command(
{
Expand Down
Loading
Loading