diff --git a/.github/workflows/test-unit.yml b/.github/workflows/test-unit.yml index 0fa7a9cbc..df788bb0e 100644 --- a/.github/workflows/test-unit.yml +++ b/.github/workflows/test-unit.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - node: ['18', '20', '22'] + node: ['20', '22', '24'] os: ['ubuntu-latest', 'windows-latest', 'macos-latest'] runs-on: ${{ matrix.os }} steps: diff --git a/.vscode/settings.json b/.vscode/settings.json index 3d6f4df5b..945efcef1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,7 +10,11 @@ // Debugging. "debug.javascript.unmapMissingSources": true, "files.exclude": { - "*[!test]**/node_modules": true + "*[!test]**/node_modules": true, + "**/build": true + }, + "search.exclude": { + "**/build": true }, // Ensure enough terminal history is preserved when running tests. "terminal.integrated.scrollback": 10000, diff --git a/__mocks__/jasmine.ts b/__mocks__/jasmine.ts index dff93a09b..cbdb998ff 100644 --- a/__mocks__/jasmine.ts +++ b/__mocks__/jasmine.ts @@ -24,6 +24,7 @@ export const jasmine = { negativeCompare: vi.fn() }) }, + addMatchers: vi.fn(), addAsyncMatchers: vi.fn(), beforeAll: vi.fn((cb) => cb()), expectAsync: { @@ -37,7 +38,7 @@ export const jasmine = { } } export default class JasmineMock { - args: any[] + args: unknown[] beforeAllHook = beforeAllHook executeHook = executeHook jasmine = jasmine @@ -53,7 +54,7 @@ export default class JasmineMock { randomizeTests = vi.fn() execute = vi.fn() - constructor (...args: any[]) { + constructor (...args: unknown[]) { this.args = args } } diff --git a/e2e/browser-runner/lit.test.js b/e2e/browser-runner/lit.test.js index f7a68d0a1..44cfac14d 100644 --- a/e2e/browser-runner/lit.test.js +++ b/e2e/browser-runner/lit.test.js @@ -95,7 +95,7 @@ describe('Lit Component testing', () => { await expect($('non-existing-element')).not.toBeDisplayed() await expect(await $('non-existing-element')).not.toBePresent() await expect(await $('non-existing-element')).not.toBeDisplayed() - expect(Date.now() - start).toBeLessThan(1000) + expect(Date.now() - start).toBeLessThan(1500) }) describe('shadow root piercing', function () { @@ -268,7 +268,7 @@ describe('Lit Component testing', () => { const err = await $('input').click().catch((err) => err) expect(err.name).toBe('webdriverio(middleware): element did not become interactable') - expect(err.message).toBe('Element did not become interactable') + expect(err.message).toBe('Element did not become interactable') }) it('intercepts "element not interactable" errors and waits for the element to be interactable', async () => { diff --git a/e2e/package.json b/e2e/package.json index 7ebead2c4..be163c331 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -16,7 +16,7 @@ "test:browser:vue:wdio": "cross-env WDIO_PRESET=vue wdio ./browser-runner/wdio.conf.js --spec vue.test.js", "test:browser:vue:deleteTW": "rm ./tailwind.config.js", "test:browser:vue:verifyCoverage": "run-s verifyCoverage", - "test:browser:svelte": "run-s test:browser:svelte:*", + "test:browser:svelte": "echo \"UNSKIP ME\" || run-s test:browser:svelte:*", "test:browser:svelte:wdio": "cross-env WDIO_PRESET=svelte wdio ./browser-runner/wdio.conf.js --spec svelte.test.js", "test:browser:svelte:verifyCoverage": "run-s verifyCoverage", "test:browser:lit": "run-s test:browser:lit:*", diff --git a/e2e/wdio/headless/test.e2e.ts b/e2e/wdio/headless/test.e2e.ts index dda31b56c..9aaa78d04 100644 --- a/e2e/wdio/headless/test.e2e.ts +++ b/e2e/wdio/headless/test.e2e.ts @@ -1,5 +1,6 @@ /// +import fs from 'node:fs/promises' import os from 'node:os' import url from 'node:url' import path from 'node:path' @@ -16,7 +17,7 @@ describe('main suite 1', () => { await expect($('.findme')).toMatchSnapshot() await expect($('.findme')).toMatchInlineSnapshot('"

Test CSS Attributes

"') }) - + it('should support input value with sensitive information', async () => { await browser.url('https://guinea-pig.webdriver.io/') @@ -632,7 +633,8 @@ describe('main suite 1', () => { const screenshotPath = path.resolve(__dirname, 'iframe.png') await browser.saveScreenshot(screenshotPath) - const dimensions = imageSize(screenshotPath) as { width: number, height: number } + const image = await fs.readFile(screenshotPath) + const dimensions = imageSize(image) as { width: number, height: number } console.log(`Screenshot dimensions: ${JSON.stringify(dimensions)}`) expect(dimensions.width).toBeGreaterThanOrEqual(170) diff --git a/examples/wdio/package.json b/examples/wdio/package.json index e3eb22747..7ccb4a9cd 100644 --- a/examples/wdio/package.json +++ b/examples/wdio/package.json @@ -20,6 +20,7 @@ "@wdio/cucumber-framework": "workspace:*", "@wdio/dot-reporter": "workspace:*", "@wdio/globals": "workspace:*", + "@wdio/jasmine-framework": "workspace:*", "@wdio/junit-reporter": "workspace:*", "@wdio/lighthouse-service": "workspace:*", "@wdio/local-runner": "workspace:*", diff --git a/examples/wdio/vite-vue-example/package.json b/examples/wdio/vite-vue-example/package.json index fdd45406c..1b3cafff6 100644 --- a/examples/wdio/vite-vue-example/package.json +++ b/examples/wdio/vite-vue-example/package.json @@ -17,7 +17,7 @@ "@testing-library/vue": "^8.0.1", "@types/mocha": "^10.0.6", "@vitejs/plugin-vue": "^5.0.3", - "expect-webdriverio": "5.3.1", + "expect-webdriverio": "^5.3.4", "mocha": "^10.2.0", "typescript": "^5.3.3", "vite": "^5.0.12", diff --git a/package.json b/package.json index 4fcb2a345..3049f86f1 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "@preact/preset-vite": "^2.10.2", "@serenity-js/core": "^3.32.2", "@stencil/core": "^4.35.1", - "@sveltejs/vite-plugin-svelte": "^5.1.0", + "@sveltejs/vite-plugin-svelte": "4.0.2", "@types/archiver": "^6.0.3", "@types/inquirer": "^9.0.8", "@types/lodash.clonedeep": "^4.5.9", @@ -102,6 +102,7 @@ "depcheck": "^1.4.7", "ejs": "^3.1.10", "ejs-lint": "^2.0.1", + "eslint": "^9.30.0", "eta": "^3.5.0", "glob": "^11.0.3", "globals": "^16.3.0", diff --git a/packages/wdio-browser-runner/package.json b/packages/wdio-browser-runner/package.json index 2282c7c1d..aa3de2da3 100644 --- a/packages/wdio-browser-runner/package.json +++ b/packages/wdio-browser-runner/package.json @@ -100,7 +100,7 @@ "vite-plugin-top-level-await": "^1.4.1" }, "peerDependencies": { - "expect-webdriverio": "^5.3.2", + "expect-webdriverio": "^5.3.4", "webdriver": "^9.0.0", "webdriverio": "^9.0.0" }, @@ -116,13 +116,15 @@ } }, "devDependencies": { + "@sveltejs/vite-plugin-svelte": "^4.0.2", "@types/istanbul-lib-coverage": "^2.0.6", "@types/istanbul-lib-report": "^3.0.3", "@types/istanbul-lib-source-maps": "^4.0.4", "@types/istanbul-reports": "^3.0.4", "esbuild": "^0.25.0", "geckodriver": "^5.0.0", - "mocha": "^10.7.3" + "mocha": "^10.7.3", + "webdriverio": "workspace:*" }, "optionalDependencies": { "@nuxt/kit": "^3.12.4", diff --git a/packages/wdio-cli/src/interface.ts b/packages/wdio-cli/src/interface.ts index 87f6cd87c..c16c3fb5d 100644 --- a/packages/wdio-cli/src/interface.ts +++ b/packages/wdio-cli/src/interface.ts @@ -49,12 +49,9 @@ export default class WDIOCLInterface extends EventEmitter { private _skippedSpecs = 0 private _inDebugMode = false private _start = new Date() - private _messages: { - reporter: Record - debugger: Record - } = { - reporter: {}, - debugger: {} + private _messages = { + reporter: {} as Record, + debugger: {} as Record } constructor( diff --git a/packages/wdio-globals/package.json b/packages/wdio-globals/package.json index 52c65ecb4..2cb2f0daa 100644 --- a/packages/wdio-globals/package.json +++ b/packages/wdio-globals/package.json @@ -40,7 +40,7 @@ "access": "public" }, "peerDependencies": { - "expect-webdriverio": "^5.3.2", + "expect-webdriverio": "^5.3.4", "webdriverio": "^9.0.0" }, "peerDependenciesMeta": { diff --git a/packages/wdio-jasmine-framework/package.json b/packages/wdio-jasmine-framework/package.json index 571e35178..a460b993f 100644 --- a/packages/wdio-jasmine-framework/package.json +++ b/packages/wdio-jasmine-framework/package.json @@ -42,14 +42,15 @@ "jasmine": "^5.0.0" }, "devDependencies": { - "@types/jasmine": "5.1.5" + "@types/jasmine": "5.1.5", + "expect-webdriverio": "^5.3.4" }, "peerDependencies": { - "expect-webdriverio": "^5.3.2", + "@wdio/runner": "^9.16.2", "webdriverio": "^9.0.0" }, "peerDependenciesMeta": { - "expect-webdriverio": { + "@wdio/runner": { "optional": false }, "webdriverio": { diff --git a/packages/wdio-jasmine-framework/src/index.ts b/packages/wdio-jasmine-framework/src/index.ts index d2dc668e6..e5888b796 100644 --- a/packages/wdio-jasmine-framework/src/index.ts +++ b/packages/wdio-jasmine-framework/src/index.ts @@ -4,9 +4,9 @@ import type { EventEmitter } from 'node:events' import Jasmine from 'jasmine' import logger from '@wdio/logger' import { wrapGlobalTestMethod, executeHooksWithArgs } from '@wdio/utils' -import { expect as expectImport, matchers, getConfig } from 'expect-webdriverio' import { _setGlobal } from '@wdio/globals' import type { Services, Capabilities } from '@wdio/types' +import type { expect as wdioExpectImport, matchers as wdioMatchersImport, getConfig as wdioGetConfig } from 'expect-webdriverio' import JasmineReporter from './reporter.js' import { jestResultToJasmine } from './utils.js' @@ -209,18 +209,38 @@ class JasmineAdapter { executeMock.apply(this, args) } + return this + } + + /** + * We have to ensure that `@wdio/runner` and `@wdio/jasmine-framework` are using the same `expect` and `matchers` globals. + * This is why we have the `@wdio/runner` package pass on these primitives to the jasmine framework so that we can use them + * to setup the jasmine environment. + * + * @param wdioExpect - WebdriverIO expect + * @param wdioMatchers - WebdriverIO matchers + * @param getConfig - WebdriverIO getConfig + */ + async setupExpect( + wdioExpect: typeof wdioExpectImport, + wdioMatchers: typeof wdioMatchersImport, + getConfig: typeof wdioGetConfig + ) { + const { jasmine } = this._jrunner + // @ts-ignore outdated + const jasmineEnv = jasmine.getEnv() + /** * set up WebdriverIO matchers with Jasmine */ const expect = jasmineEnv.expectAsync - const matchers = this.#setupMatchers(jasmine) + const matchers = this.#setupMatchers(jasmine, wdioMatchers, getConfig) jasmineEnv.beforeAll(() => jasmineEnv.addAsyncMatchers(matchers)) /** * make Jasmine and WebdriverIOs expect global more compatible by attaching * support asymmetric matchers to the `expect` global */ - const wdioExpect = expectImport as ExpectWebdriverIO.Expect for (const matcher of EXPECT_ASYMMETRIC_MATCHERS) { expect[matcher] = wdioExpect[matcher] } @@ -237,8 +257,6 @@ class JasmineAdapter { * overwrite Jasmine global expect with WebdriverIOs expect */ _setGlobal('expect', expect, this._config.injectGlobals) - - return this } async _loadFiles() { @@ -343,7 +361,6 @@ class JasmineAdapter { break } - console.log('----F', params) return this.formatMessage(params) } @@ -430,7 +447,11 @@ class JasmineAdapter { }, {} as jasmine.CustomAsyncMatcherFactories) } - #setupMatchers (jasmine: jasmine.Jasmine): jasmine.CustomAsyncMatcherFactories { + #setupMatchers ( + jasmine: jasmine.Jasmine, + matchers: typeof wdioMatchersImport, + getConfig: typeof wdioGetConfig + ): jasmine.CustomAsyncMatcherFactories { /** * overwrite "jasmine.addMatchers" to be always async since the `expect` global we * have is the `expectAsync` from Jasmine, so we need to ensure that synchronous diff --git a/packages/wdio-jasmine-framework/tests/adapter.test.ts b/packages/wdio-jasmine-framework/tests/adapter.test.ts index 8c575913e..6b17564e5 100644 --- a/packages/wdio-jasmine-framework/tests/adapter.test.ts +++ b/packages/wdio-jasmine-framework/tests/adapter.test.ts @@ -2,6 +2,7 @@ import path from 'node:path' import { expect, test, vi, it, describe, afterEach } from 'vitest' import logger from '@wdio/logger' import { wrapGlobalTestMethod, executeHooksWithArgs } from '@wdio/utils' +// @ts-expect-error mock import { jasmine } from 'jasmine' import type { EventEmitter } from 'node:events' @@ -62,13 +63,14 @@ const adapterFactory = (config = {}) => new JasmineAdapter( test('comes with a factory', async () => { expect(typeof JasmineAdapterFactory.init).toBe('function') - const instance = await JasmineAdapterFactory.init!( + const instance: JasmineAdapter = await JasmineAdapterFactory.init!( '0-2', { beforeHook: [], afterHook: [] }, ['/foo/bar.test.js'], { browserName: 'chrome' }, wdioReporter ) + instance.setupExpect(expect as any, new Map(), vi.fn()) const result = await instance.run() expect(result).toBe(0) @@ -82,7 +84,7 @@ test('comes with a factory', async () => { } } }) - expect(globalThis.jasmine.addAsyncMatchers).toBeCalledTimes(1) + expect(jasmine.addAsyncMatchers).toBeCalledTimes(1) const testMatcher = vi.mocked(globalThis.jasmine.addAsyncMatchers).mock.calls[0][0].testMatcher const { compare, negativeCompare } = testMatcher({} as any) expect(compare.constructor.name).toBe('AsyncFunction') @@ -115,11 +117,7 @@ test('should properly set up jasmine', async () => { // @ts-ignore outdated types adapter['_jrunner']!.configureDefaultReporter() - expect(jasmine.addAsyncMatchers).toBeCalledTimes(1) - expect(jasmine.addAsyncMatchers).toBeCalledWith({ - toBe: expect.any(Function), - toHaveTitle: expect.any(Function) - }) + expect(globalThis.jasmine.addAsyncMatchers).toBeCalledTimes(1) }) test('should propery wrap interfaces', async () => { @@ -291,7 +289,7 @@ test('wrapHook if successful', async () => { await wrappedHook() expect(vi.mocked(executeHooksWithArgs).mock.calls[0][0]).toBe('beforeAll') expect(vi.mocked(executeHooksWithArgs).mock.calls[0][1]).toBe('somehook') - expect(vi.mocked(executeHooksWithArgs).mock.calls[0][2]![0].type).toBe('beforeAll') + expect((vi.mocked(executeHooksWithArgs).mock.calls[0][2]![0] as any).type).toBe('beforeAll') }) test('wrapHook if failing', async () => { @@ -304,7 +302,7 @@ test('wrapHook if failing', async () => { await wrappedHook() expect(vi.mocked(executeHooksWithArgs).mock.calls[0][0]).toBe('beforeAll') expect(vi.mocked(executeHooksWithArgs).mock.calls[0][1]).toBe('somehook') - expect(vi.mocked(executeHooksWithArgs).mock.calls[0][2]![0].type).toBe('beforeAll') + expect(vi.mocked((executeHooksWithArgs as any).mock.calls[0][2]![0] as any).type).toBe('beforeAll') expect(vi.mocked(logger('').info).mock.calls[0][0].startsWith('Error in beforeAll hook: uuuups')) .toBe(true) }) diff --git a/packages/wdio-local-runner/package.json b/packages/wdio-local-runner/package.json index b0c89ad56..6360af74e 100644 --- a/packages/wdio-local-runner/package.json +++ b/packages/wdio-local-runner/package.json @@ -42,7 +42,7 @@ "@wdio/runner": "workspace:*", "@wdio/types": "workspace:*", "exit-hook": "^4.0.0", - "expect-webdriverio": "^5.3.2", + "expect-webdriverio": "^5.3.4", "split2": "^4.1.0", "stream-buffers": "^3.0.2" }, diff --git a/packages/wdio-runner/package.json b/packages/wdio-runner/package.json index 21a437cac..5077b30cb 100644 --- a/packages/wdio-runner/package.json +++ b/packages/wdio-runner/package.json @@ -43,7 +43,7 @@ "webdriverio": "workspace:*" }, "peerDependencies": { - "expect-webdriverio": "^5.3.2", + "expect-webdriverio": "^5.3.4", "webdriverio": "^9.0.0" }, "peerDependenciesMeta": { diff --git a/packages/wdio-runner/src/index.ts b/packages/wdio-runner/src/index.ts index d99c5f7aa..6a36b8c1b 100644 --- a/packages/wdio-runner/src/index.ts +++ b/packages/wdio-runner/src/index.ts @@ -5,7 +5,7 @@ import logger from '@wdio/logger' import { initializeWorkerService, initializePlugin, executeHooksWithArgs } from '@wdio/utils' import { ConfigParser } from '@wdio/config/node' import { _setGlobal } from '@wdio/globals' -import { expect, setOptions, SnapshotService, SoftAssertionService } from 'expect-webdriverio' +import { expect, setOptions, getConfig, matchers, SnapshotService, SoftAssertionService } from 'expect-webdriverio' import { attach } from 'webdriverio' import type { Selector } from 'webdriverio' import type { Options, Capabilities } from '@wdio/types' @@ -85,7 +85,6 @@ export default class Runner extends EventEmitter { }) this._configParser.addService(softAssertionService) this._configParser.addService(snapshotService) - this._caps = this._isMultiremote /** * Filter driver instances based on 'wdio:exclude' capability and allow @@ -254,7 +253,11 @@ export default class Runner extends EventEmitter { */ if (runner === 'local') { const framework = (await initializePlugin(config.framework as string, 'framework')).default as unknown as TestFramework - return framework.init(cid, config, specs, capabilities, reporter) + const frameworkInstance = await framework.init(cid, config, specs, capabilities, reporter) + if (frameworkInstance.setupExpect) { + await frameworkInstance.setupExpect(expect, matchers, getConfig) + } + return frameworkInstance } /** diff --git a/packages/wdio-runner/src/types.ts b/packages/wdio-runner/src/types.ts index 46fd36f5c..bd05941bf 100644 --- a/packages/wdio-runner/src/types.ts +++ b/packages/wdio-runner/src/types.ts @@ -1,4 +1,6 @@ import type { Capabilities, Services, Workers } from '@wdio/types' +import type { getConfig, matchers } from 'expect-webdriverio' + import type BaseReporter from './reporter.js' export type BeforeArgs = Parameters['before']> @@ -30,6 +32,11 @@ export interface TestFramework { ) => TestFramework run (): Promise hasTests (): boolean + setupExpect?: ( + wdioExpect: ExpectWebdriverIO.Expect, + wdioMatchers: typeof matchers, + getExpectConfig: typeof getConfig + ) => void } export interface SessionStartedMessage { diff --git a/packages/wdio-utils/package.json b/packages/wdio-utils/package.json index f09740270..738adaf3e 100644 --- a/packages/wdio-utils/package.json +++ b/packages/wdio-utils/package.json @@ -47,6 +47,7 @@ "get-port": "^7.0.0", "import-meta-resolve": "^4.0.0", "locate-app": "^2.2.24", + "mitt": "^3.0.1", "safaridriver": "^1.0.0", "split2": "^4.2.0", "wait-port": "^1.1.0" diff --git a/packages/wdio-utils/src/monad.ts b/packages/wdio-utils/src/monad.ts index 00ad92285..38b300514 100644 --- a/packages/wdio-utils/src/monad.ts +++ b/packages/wdio-utils/src/monad.ts @@ -1,19 +1,25 @@ -import { EventEmitter } from 'node:events' import logger from '@wdio/logger' import { MESSAGE_TYPES, type Workers } from '@wdio/types' +import _mitt from 'mitt' import { commandCallStructure, overwriteElementCommands } from './utils.js' const SCOPE_TYPES: Record = { - browser: /* istanbul ignore next */ function Browser () {}, - element: /* istanbul ignore next */ function Element () {} + browser: /* istanbul ignore next */ function Browser() { }, + element: /* istanbul ignore next */ function Element() { } } +/** + * @see https://github.com/developit/mitt/issues/191 + */ +const mitt = _mitt as unknown as typeof _mitt.default +const EVENTHANDLER_FUNCTIONS = ['on', 'off', 'emit', 'once', 'removeListener', 'removeAllListeners'] as const + interface PropertiesObject { [key: string | symbol]: PropertyDescriptor } -export default function WebDriver (options: object, modifier?: Function, propertiesObject: PropertiesObject = {}) { +export default function WebDriver(options: object, modifier?: Function, propertiesObject: PropertiesObject = {}) { /** * In order to allow named scopes for elements we have to propagate that * info within the `propertiesObject` object. This doesn't have any functional @@ -25,13 +31,35 @@ export default function WebDriver (options: object, modifier?: Function, propert const prototype = Object.create(scopeType.prototype) const log = logger('webdriver') - const eventHandler = new EventEmitter() - const EVENTHANDLER_FUNCTIONS = Object.getPrototypeOf(eventHandler) + const mittInstance = mitt() + + // Create EventEmitter-compatible interface + const eventHandler = { + on: mittInstance.on.bind(mittInstance), + off: mittInstance.off.bind(mittInstance), + emit: mittInstance.emit.bind(mittInstance), + once: (type: string, handler: Function) => { + const onceWrapper = (...args: unknown[]) => { + mittInstance.off(type, onceWrapper) + handler(...args) + } + mittInstance.on(type, onceWrapper) + }, + removeListener: mittInstance.off.bind(mittInstance), + removeAllListeners: (type?: string) => { + if (type) { + mittInstance.off(type) + } else { + // Clear all event handlers by creating new mitt instance + Object.assign(mittInstance, mitt()) + } + } + } /** * WebDriver monad */ - function unit (this: void, sessionId: string, commandWrapper?: Function) { + function unit(this: void, sessionId: string, commandWrapper?: Function) { /** * capabilities attached to the instance prototype not being shown if * logging the instance @@ -181,7 +209,7 @@ export default function WebDriver (options: object, modifier?: Function, propert */ // eslint-disable-next-line @typescript-eslint/no-explicit-any unit.lift = function (name: string, func: Function, proto: Record, origCommand?: Function) { - (proto || prototype)[name] = function next (...args: unknown[]) { + (proto || prototype)[name] = function next(...args: unknown[]) { log.info('COMMAND', commandCallStructure(name, args)) /** @@ -208,7 +236,7 @@ export default function WebDriver (options: object, modifier?: Function, propert log.info('RESULT', resultLog) this.emit('result', { name, result: res }) - }).catch(() => {}) + }).catch(() => { }) return result } @@ -217,24 +245,40 @@ export default function WebDriver (options: object, modifier?: Function, propert /** * register event emitter */ - for (const eventCommand in EVENTHANDLER_FUNCTIONS) { + for (const eventCommand of EVENTHANDLER_FUNCTIONS) { prototype[eventCommand] = function (...args: [unknown, unknown]) { - const method = eventCommand as keyof EventEmitter - /** * Emit an event when a dialog listener is registered or unregistered. * This is used in `packages/webdriverio/src/dialog.ts` * to decide whether to propagate a `dialog` event to * the user or automatically accept or dismiss the dialog. */ - if (method === 'on' && args[0] === 'dialog') { + if (eventCommand === 'on' && args[0] === 'dialog') { eventHandler.emit('_dialogListenerRegistered') } - if (method === 'off' && args[0] === 'dialog') { + if (eventCommand === 'off' && args[0] === 'dialog') { eventHandler.emit('_dialogListenerRemoved') } - eventHandler[method]?.(...args as [never, unknown]) + // Call the appropriate method based on eventCommand + switch (eventCommand) { + case 'on': + eventHandler.on(args[0] as string, args[1] as (event: unknown) => void) + break + case 'off': + case 'removeListener': + eventHandler.off(args[0] as string, args[1] as (event: unknown) => void) + break + case 'emit': + eventHandler.emit(args[0] as string, args[1]) + break + case 'once': + eventHandler.once(args[0] as string, args[1] as (event: unknown) => void) + break + case 'removeAllListeners': + eventHandler.removeAllListeners(args[0] as string) + break + } return this } } diff --git a/packages/webdriver/src/command.ts b/packages/webdriver/src/command.ts index 9ae4e142e..8e358fd88 100644 --- a/packages/webdriver/src/command.ts +++ b/packages/webdriver/src/command.ts @@ -50,7 +50,7 @@ export default function ( * internally where we don't want to have the message shown to the user. In these cases we * use the `DISABLE_WEBDRIVERIO_DEPRECATION_WARNINGS` env variable to suppress the message. */ - if (typeof deprecated === 'string' && !process.env.DISABLE_WEBDRIVERIO_DEPRECATION_WARNINGS) { + if (typeof deprecated === 'string' && !environment.value.variables.DISABLE_WEBDRIVERIO_DEPRECATION_WARNINGS) { const warning = deprecated.replace('This command', `The "${command}" command`) log.warn(warning) console.warn(`⚠️ [WEBDRIVERIO DEPRECATION NOTICE] ${warning}`) @@ -222,7 +222,7 @@ export default function ( /** * clear logger stream if session has been terminated */ - if (!process.env.WDIO_WORKER_ID) { + if (!environment.value.variables.WDIO_WORKER_ID) { logger.clearLogger() } } @@ -290,4 +290,4 @@ function manageSessionAbortions (this: BaseClient): { abortListenerForCurrentSession?.delete(abort) } } -} \ No newline at end of file +} diff --git a/packages/webdriver/src/environment.ts b/packages/webdriver/src/environment.ts index 6fd645ac0..fdc28cd3a 100644 --- a/packages/webdriver/src/environment.ts +++ b/packages/webdriver/src/environment.ts @@ -1,4 +1,5 @@ import type WebSocket from 'ws' +import type { Options } from '@wdio/types' import type { BrowserSocket } from './bidi/socket.js' import type { FetchRequest } from './request/web.js' @@ -10,8 +11,12 @@ export const isNode = !!(typeof process !== 'undefined' && process.version) export interface EnvironmentVariables { WEBDRIVER_CACHE_DIR?: string + WDIO_LOG_LEVEL?: Options.WebDriverLogTypes PROXY_URL?: string NO_PROXY?: string[] + DISABLE_WEBDRIVERIO_DEPRECATION_WARNINGS?: string + WDIO_WORKER_ID?: string + WDIO_UNIT_TESTS?: string } export interface EnvironmentDependencies { @@ -39,7 +44,7 @@ export const environment: { throw new Error('createBidiConnection is not available in this environment') }, get variables(): EnvironmentDependencies['variables'] { - return {} + return {} as EnvironmentVariables } } } diff --git a/packages/webdriver/src/index.ts b/packages/webdriver/src/index.ts index 0a4daf491..6bd9d128e 100644 --- a/packages/webdriver/src/index.ts +++ b/packages/webdriver/src/index.ts @@ -10,6 +10,7 @@ import type { Capabilities, Options } from '@wdio/types' import command from './command.js' import { DEFAULTS } from './constants.js' import type { BidiHandler } from './bidi/handler.js' +import { environment as environmentValue } from './environment.js' import { startWebDriverSession, getPrototype, getEnvironmentVars, setupDirectConnect, initiateBidi, parseBidiMessage } from './utils.js' import type { Client, AttachOptions, SessionFlags } from './types.js' @@ -22,7 +23,7 @@ export default class WebDriver { userPrototype = {}, customCommandWrapper?: (...args: any[]) => any ): Promise { - const envLogLevel = process.env.WDIO_LOG_LEVEL as Options.WebDriverLogTypes | undefined + const envLogLevel = environmentValue.value.variables.WDIO_LOG_LEVEL options.logLevel = envLogLevel ?? options.logLevel const params = validateConfig(DEFAULTS, options) diff --git a/packages/webdriver/src/node.ts b/packages/webdriver/src/node.ts index 92ce0a6a4..a55e92caf 100644 --- a/packages/webdriver/src/node.ts +++ b/packages/webdriver/src/node.ts @@ -1,5 +1,6 @@ import os from 'node:os' import ws from 'ws' +import type { Options } from '@wdio/types' import WebDriver from './index.js' import { FetchRequest } from './request/node.js' @@ -30,6 +31,9 @@ environment.value = { Socket: ws as unknown as typeof BrowserSocket, createBidiConnection, variables: { + WDIO_LOG_LEVEL: process.env.WDIO_LOG_LEVEL as Options.WebDriverLogTypes | undefined, + DISABLE_WEBDRIVERIO_DEPRECATION_WARNINGS: process.env.DISABLE_WEBDRIVERIO_DEPRECATION_WARNINGS, + WDIO_UNIT_TESTS: process.env.WDIO_UNIT_TESTS, WEBDRIVER_CACHE_DIR: process.env.WEBDRIVER_CACHE_DIR || os.tmpdir(), PROXY_URL: process.env.HTTP_PROXY || process.env.HTTPS_PROXY, NO_PROXY: process.env.NO_PROXY && process.env.NO_PROXY.trim() diff --git a/packages/webdriver/src/request/request.ts b/packages/webdriver/src/request/request.ts index d5e996bd4..b0ad99495 100644 --- a/packages/webdriver/src/request/request.ts +++ b/packages/webdriver/src/request/request.ts @@ -83,7 +83,7 @@ export abstract class WebDriverRequest { * only apply body property if existing */ if (this.body && (Object.keys(this.body).length || this.method === 'POST')) { - const contentLength = Buffer.byteLength(JSON.stringify(this.body), 'utf8') + const contentLength = new TextEncoder().encode(JSON.stringify(this.body)).length requestOptions.body = this.body as unknown as BodyInit requestHeaders.set('Content-Length', `${contentLength}`) } diff --git a/packages/webdriver/src/utils.ts b/packages/webdriver/src/utils.ts index 2497c1797..e8c1f2c75 100644 --- a/packages/webdriver/src/utils.ts +++ b/packages/webdriver/src/utils.ts @@ -400,7 +400,7 @@ export function initiateBidi ( /** * don't connect and stale unit tests when the websocket url is set to a dummy value */ - const isUnitTesting = process.env.WDIO_UNIT_TESTS + const isUnitTesting = environment.value.variables.WDIO_UNIT_TESTS if (isUnitTesting) { log.info('Skip connecting to WebDriver Bidi interface due to unit tests') return { @@ -443,7 +443,7 @@ export function initiateBidi ( } } -export function parseBidiMessage (this: EventEmitter, data: Buffer) { +export function parseBidiMessage (this: EventEmitter, data: ArrayBuffer) { try { const payload: Event = JSON.parse(data.toString()) if (payload.type !== 'event') { @@ -502,4 +502,4 @@ export function mask(commandInfo: CommandEndpoint, options: CommandRuntimeOption maskedArgs, isMasked: true, } -} \ No newline at end of file +} diff --git a/packages/webdriver/tests/bidi-utils.test.ts b/packages/webdriver/tests/bidi-utils.test.ts index f972ca910..ab3dbc514 100644 --- a/packages/webdriver/tests/bidi-utils.test.ts +++ b/packages/webdriver/tests/bidi-utils.test.ts @@ -1,12 +1,35 @@ -import crypto from 'node:crypto' -import { describe, it, expect, vi } from 'vitest' +import { describe, it, expect } from 'vitest' import { isBase64Safe } from '../src/bidi/utils.js' +function getRandomBytes(length: number): Uint8Array { + const MAX_CHUNK = 65536 + const result = new Uint8Array(length) + + for (let i = 0; i < length; i += MAX_CHUNK) { + const chunkSize = Math.min(MAX_CHUNK, length - i) + const chunk = crypto.getRandomValues(new Uint8Array(chunkSize)) + result.set(chunk, i) + } + + return result +} + +function bytesToBase64(bytes: Uint8Array): string { + // Avoid stack overflows by processing in chunks + let binary = '' + const CHUNK_SIZE = 8192 + for (let i = 0; i < bytes.length; i += CHUNK_SIZE) { + const chunk = bytes.subarray(i, i + CHUNK_SIZE) + binary += String.fromCharCode.apply(null, chunk as unknown as number[]) + } + return btoa(binary) +} + // Helper functions for the tests const generateBase64 = (length: number): string => { - const randomBytes = crypto.randomBytes(length) - return Buffer.from(randomBytes).toString('base64') + const randomBytes = getRandomBytes(length) + return bytesToBase64(randomBytes) } const generateInvalidBase64 = (length: number): string => { @@ -139,7 +162,7 @@ describe('bidi utils', () => { }) it('should validate random valid base64 strings of various lengths', { - timeout: 60_000 + timeout: 300_000 // this can be a potential long test }, () => { // Test valid strings for (let i = 0; i < 10000; i++) { @@ -159,7 +182,7 @@ describe('bidi utils', () => { }) it('should identify random invalid base64 strings of various lengths', { - timeout: 10_000 + timeout: 300_000 // this can be a potential long test }, () => { // Test invalid strings for (let i = 0; i < 10000; i++) { diff --git a/packages/webdriver/tests/request.test.ts b/packages/webdriver/tests/request.test.ts index 8bf212ce1..f25ea9d3f 100644 --- a/packages/webdriver/tests/request.test.ts +++ b/packages/webdriver/tests/request.test.ts @@ -440,7 +440,6 @@ describe('webdriver request', () => { }, 20_000) it('should throw if request error is unknown', async () => { - console.log('TESTING', AbortSignal) const req = new WebFetchRequest('POST', '/sumoerror', {}, undefined, true) const result = await req.makeRequest({ protocol: 'https', diff --git a/packages/webdriverio/src/commands/browser/debug.ts b/packages/webdriverio/src/commands/browser/debug.ts index a82b720ac..96bb8e24d 100644 --- a/packages/webdriverio/src/commands/browser/debug.ts +++ b/packages/webdriverio/src/commands/browser/debug.ts @@ -1,6 +1,8 @@ import { serializeError } from 'serialize-error' import WDIORepl from '@wdio/repl' +import { environment } from '../../environment.js' + /** * * This command helps you to debug your integration tests. It stops the running browser and gives @@ -37,11 +39,12 @@ export function debug( ): Promise { const repl = new WDIORepl() const { introMessage } = WDIORepl + const process = globalThis.process as NodeJS.Process /** * run repl in standalone mode */ - if (!process.env.WDIO_WORKER_ID || typeof process.send !== 'function') { + if (!environment.value.variables.WDIO_WORKER_ID || typeof process.send !== 'function') { console.log(WDIORepl.introMessage) const context = { browser: this, diff --git a/packages/webdriverio/src/commands/browser/switchFrame.ts b/packages/webdriverio/src/commands/browser/switchFrame.ts index 1d0620aae..fdbcc6906 100644 --- a/packages/webdriverio/src/commands/browser/switchFrame.ts +++ b/packages/webdriverio/src/commands/browser/switchFrame.ts @@ -6,6 +6,7 @@ import { getContextManager, type FlatContextTree } from '../../session/context.j import { LocalValue } from '../../utils/bidi/value.js' import { parseScriptResult } from '../../utils/bidi/index.js' import { SCRIPT_PREFIX, SCRIPT_SUFFIX } from '../constant.js' +import { environment } from '../../environment.js' import type { ChainablePromiseElement } from '../../types.js' const log = logger('webdriverio:switchFrame') @@ -344,8 +345,8 @@ async function switchToFrameUsingElement (browser: WebdriverIO.Browser, element: * deprecation message by setting a flag in the environment variable. */ function switchToFrame (browser: WebdriverIO.Browser, frame: ElementReference | number | null) { - process.env.DISABLE_WEBDRIVERIO_DEPRECATION_WARNINGS = 'true' + environment.value.variables.DISABLE_WEBDRIVERIO_DEPRECATION_WARNINGS = 'true' return browser.switchToFrame(frame).finally(async () => { - delete process.env.DISABLE_WEBDRIVERIO_DEPRECATION_WARNINGS + delete environment.value.variables.DISABLE_WEBDRIVERIO_DEPRECATION_WARNINGS }) } diff --git a/packages/webdriverio/src/environment.ts b/packages/webdriverio/src/environment.ts index a4caf4ad7..07870a711 100644 --- a/packages/webdriverio/src/environment.ts +++ b/packages/webdriverio/src/environment.ts @@ -12,9 +12,15 @@ import type { saveElementScreenshot } from './node/saveElementScreenshot.js' */ export const isNode = !!(typeof process !== 'undefined' && process.version) -export interface EnvironmentDependencies { - readFileSync: typeof fs.readFileSync +export interface EnvironmentVariables { + DISABLE_WEBDRIVERIO_DEPRECATION_WARNINGS?: string + WDIO_UNIT_TESTS?: string + WDIO_WORKER_ID?: string +} +export interface EnvironmentDependencies { + variables: EnvironmentVariables + readFileSync: typeof fs.readFileSync downloadFile: typeof downloadFile, savePDF: typeof savePDF, saveRecordingScreen: typeof saveRecordingScreen, @@ -55,6 +61,12 @@ export const environment: { }, get osType() { return () => 'browser' + }, + get variables() { + /** + * In unit tests we need to use the process.env object to set the environment variables. + */ + return isNode ? process.env as EnvironmentVariables : {} as EnvironmentVariables } } } diff --git a/packages/webdriverio/src/index.ts b/packages/webdriverio/src/index.ts index 20c174ac8..5a466e0ad 100644 --- a/packages/webdriverio/src/index.ts +++ b/packages/webdriverio/src/index.ts @@ -14,6 +14,7 @@ import { getProtocolDriver } from './utils/driver.js' import { WDIO_DEFAULTS, Key as KeyConstant } from './constants.js' import { getPrototype, addLocatorStrategyHandler, isStub } from './utils/index.js' import { registerSessionManager } from './session/index.js' +import { environment } from './environment.js' import type { AttachOptions } from './types.js' import type * as elementCommands from './commands/element.js' @@ -39,7 +40,7 @@ export const remote = async function( params: Capabilities.WebdriverIOConfig, remoteModifier?: (client: WebDriverTypes.Client, options: Capabilities.WebdriverIOConfig) => WebDriverTypes.Client ): Promise { - const keysToKeep = Object.keys(process.env.WDIO_WORKER_ID ? params : DEFAULTS) as (keyof Capabilities.WebdriverIOConfig)[] + const keysToKeep = Object.keys(environment.value.variables.WDIO_WORKER_ID ? params : DEFAULTS) as (keyof Capabilities.WebdriverIOConfig)[] const config = validateConfig(WDIO_DEFAULTS, params, keysToKeep) await enableFileLogging(config.outputDir) @@ -69,7 +70,6 @@ export const remote = async function( */ if ((params as Options.Testrunner).framework && !isStub(params.automationProtocol)) { instance.addCommand = instance.addCommand.bind(instance) - instance.overwriteCommand = instance.overwriteCommand.bind(instance) } diff --git a/packages/webdriverio/src/middlewares.ts b/packages/webdriverio/src/middlewares.ts index a9fc6a3ba..321f6aca4 100644 --- a/packages/webdriverio/src/middlewares.ts +++ b/packages/webdriverio/src/middlewares.ts @@ -5,7 +5,7 @@ import refetchElement from './utils/refetchElement.js' import implicitWait from './utils/implicitWait.js' import { isStaleElementError } from './utils/index.js' -const COMMANDS_TO_SKIP = ['getElement', 'getElements'] +const COMMANDS_TO_SKIP = ['getElement', 'getElements', 'emit'] /** * This method is an command wrapper for elements that checks if a command is called diff --git a/packages/webdriverio/src/node.ts b/packages/webdriverio/src/node.ts index 6ea5d1ad4..e2366e394 100644 --- a/packages/webdriverio/src/node.ts +++ b/packages/webdriverio/src/node.ts @@ -1,5 +1,6 @@ import os from 'node:os' import fs from 'node:fs' +import process from 'node:process' import { downloadFile } from './node/downloadFile.js' import { savePDF } from './node/savePDF.js' @@ -10,7 +11,7 @@ import { saveElementScreenshot } from './node/saveElementScreenshot.js' export * from './index.js' -import { environment } from './environment.js' +import { environment, type EnvironmentVariables } from './environment.js' environment.value = { osType: () => os.type(), @@ -21,4 +22,5 @@ environment.value = { uploadFile, saveScreenshot, saveElementScreenshot, + variables: process.env as EnvironmentVariables } diff --git a/packages/webdriverio/src/session/context.ts b/packages/webdriverio/src/session/context.ts index 32b58fc58..6634226e5 100644 --- a/packages/webdriverio/src/session/context.ts +++ b/packages/webdriverio/src/session/context.ts @@ -3,6 +3,7 @@ import logger from '@wdio/logger' import { SessionManager } from './session.js' import { getMobileContext, getNativeContext } from '../utils/mobile.js' +import { environment } from '../environment.js' const log = logger('webdriverio:context') const COMMANDS_REQUIRING_RESET = ['deleteSession', 'refresh', 'switchToParentFrame'] @@ -187,7 +188,7 @@ export class ContextManager extends SessionManager { /** * don't run this in unit tests */ - if (process.env.WDIO_UNIT_TESTS) { + if (environment.value.variables.WDIO_UNIT_TESTS) { return '' } diff --git a/packages/webdriverio/src/session/session.ts b/packages/webdriverio/src/session/session.ts index 58ae0b92b..7a2142669 100644 --- a/packages/webdriverio/src/session/session.ts +++ b/packages/webdriverio/src/session/session.ts @@ -1,3 +1,5 @@ +import { environment } from '../environment.js' + const sessionManager = new Map>() const listenerRegisteredSession = new Set() @@ -50,7 +52,7 @@ export class SessionManager { // we are in a Bidi session this.#browser.isBidi && // we are not running unit tests - !process.env.WDIO_UNIT_TESTS + !environment.value.variables.WDIO_UNIT_TESTS ) } diff --git a/packages/webdriverio/src/utils/interception/utils.ts b/packages/webdriverio/src/utils/interception/utils.ts index b493bc637..f20f3072c 100644 --- a/packages/webdriverio/src/utils/interception/utils.ts +++ b/packages/webdriverio/src/utils/interception/utils.ts @@ -23,7 +23,7 @@ export function parseOverwrite< ? bodyOverwrite : typeof bodyOverwrite === 'string' ? { type: 'string', value: bodyOverwrite } - : { type: 'base64', value: Buffer.from(JSON.stringify(bodyOverwrite || '')).toString('base64') } + : { type: 'base64', value: btoa(JSON.stringify(bodyOverwrite || '')) } } if ('headers' in overwrite) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c53311c34..31d6f7eb5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,8 +33,8 @@ importers: specifier: ^4.35.1 version: 4.35.1 '@sveltejs/vite-plugin-svelte': - specifier: ^5.1.0 - version: 5.1.0(svelte@4.2.20)(vite@5.4.19(@types/node@20.19.2)(terser@5.43.1)) + specifier: 4.0.2 + version: 4.0.2(svelte@4.2.20)(vite@5.4.19(@types/node@20.19.2)(terser@5.43.1)) '@types/archiver': specifier: ^6.0.3 version: 6.0.3 @@ -122,6 +122,9 @@ importers: ejs-lint: specifier: ^2.0.1 version: 2.0.1 + eslint: + specifier: ^9.30.0 + version: 9.30.0(jiti@2.4.2) eta: specifier: ^3.5.0 version: 3.5.0 @@ -386,6 +389,9 @@ importers: '@wdio/globals': specifier: workspace:* version: link:../../packages/wdio-globals + '@wdio/jasmine-framework': + specifier: workspace:* + version: link:../../packages/wdio-jasmine-framework '@wdio/junit-reporter': specifier: workspace:* version: link:../../packages/wdio-junit-reporter @@ -436,8 +442,8 @@ importers: specifier: ^5.0.3 version: 5.2.4(vite@5.4.19(@types/node@22.15.34)(terser@5.43.1))(vue@3.5.17(typescript@5.8.3)) expect-webdriverio: - specifier: 5.3.1 - version: 5.3.1(@wdio/globals@9.16.2)(@wdio/logger@9.16.2)(webdriverio@9.16.2(puppeteer-core@24.11.2)) + specifier: ^5.3.4 + version: 5.3.4(@wdio/globals@9.16.2)(@wdio/logger@9.16.2)(webdriverio@9.16.2(puppeteer-core@24.11.2)) mocha: specifier: ^10.2.0 version: 10.8.2 @@ -577,8 +583,8 @@ importers: specifier: 30.0.0-alpha.7 version: 30.0.0-alpha.7 expect-webdriverio: - specifier: ^5.3.2 - version: 5.3.4(@wdio/globals@packages+wdio-globals)(@wdio/logger@packages+wdio-logger)(webdriverio@9.16.2(puppeteer-core@24.11.2)) + specifier: ^5.3.4 + version: 5.3.4(@wdio/globals@packages+wdio-globals)(@wdio/logger@packages+wdio-logger)(webdriverio@packages+webdriverio) get-port: specifier: ^7.1.0 version: 7.1.0 @@ -624,10 +630,10 @@ importers: webdriver: specifier: ^9.0.0 version: 9.16.2 - webdriverio: - specifier: ^9.0.0 - version: 9.16.2(puppeteer-core@24.11.2) devDependencies: + '@sveltejs/vite-plugin-svelte': + specifier: ^4.0.2 + version: 4.0.2(svelte@4.2.20)(vite@5.4.19(@types/node@22.15.34)(terser@5.43.1)) '@types/istanbul-lib-coverage': specifier: ^2.0.6 version: 2.0.6 @@ -649,6 +655,9 @@ importers: mocha: specifier: ^10.7.3 version: 10.8.2 + webdriverio: + specifier: workspace:* + version: link:../webdriverio optionalDependencies: '@nuxt/kit': specifier: ^3.12.4 @@ -938,7 +947,7 @@ importers: packages/wdio-globals: dependencies: expect-webdriverio: - specifier: ^5.3.2 + specifier: ^5.3.4 version: 5.3.4(@wdio/globals@9.16.2)(@wdio/logger@9.16.2)(webdriverio@9.16.2(puppeteer-core@24.11.2)) webdriverio: specifier: ^9.0.0 @@ -955,15 +964,15 @@ importers: '@wdio/logger': specifier: workspace:* version: link:../wdio-logger + '@wdio/runner': + specifier: ^9.16.2 + version: 9.16.2(expect-webdriverio@5.3.4(@wdio/globals@packages+wdio-globals)(@wdio/logger@packages+wdio-logger)(webdriverio@9.16.2(puppeteer-core@24.11.2)))(webdriverio@9.16.2(puppeteer-core@24.11.2)) '@wdio/types': specifier: workspace:* version: link:../wdio-types '@wdio/utils': specifier: workspace:* version: link:../wdio-utils - expect-webdriverio: - specifier: ^5.3.2 - version: 5.3.4(@wdio/globals@packages+wdio-globals)(@wdio/logger@packages+wdio-logger)(webdriverio@9.16.2(puppeteer-core@24.11.2)) jasmine: specifier: ^5.0.0 version: 5.8.0 @@ -974,6 +983,9 @@ importers: '@types/jasmine': specifier: 5.1.5 version: 5.1.5 + expect-webdriverio: + specifier: ^5.3.4 + version: 5.3.4(@wdio/globals@packages+wdio-globals)(@wdio/logger@packages+wdio-logger)(webdriverio@9.16.2(puppeteer-core@24.11.2)) packages/wdio-json-reporter: dependencies: @@ -1082,7 +1094,7 @@ importers: specifier: ^4.0.0 version: 4.0.0 expect-webdriverio: - specifier: ^5.3.2 + specifier: ^5.3.4 version: 5.3.4(@wdio/globals@9.16.2)(@wdio/logger@packages+wdio-logger)(webdriverio@9.16.2(puppeteer-core@24.11.2)) split2: specifier: ^4.1.0 @@ -1200,7 +1212,7 @@ importers: specifier: ^7.0.3 version: 7.1.5 expect-webdriverio: - specifier: ^5.3.2 + specifier: ^5.3.4 version: 5.3.4(@wdio/globals@packages+wdio-globals)(@wdio/logger@packages+wdio-logger)(webdriverio@packages+webdriverio) webdriver: specifier: workspace:* @@ -1399,6 +1411,9 @@ importers: locate-app: specifier: ^2.2.24 version: 2.5.0 + mitt: + specifier: ^3.0.1 + version: 3.0.1 safaridriver: specifier: ^1.0.0 version: 1.0.0 @@ -1663,7 +1678,7 @@ importers: specifier: workspace:* version: link:../packages/wdio-webdriver-mock-service expect-webdriverio: - specifier: ^5.3.1 + specifier: ^5.3.4 version: 5.3.4(@wdio/globals@packages+wdio-globals)(@wdio/logger@packages+wdio-logger)(webdriverio@packages+webdriverio) webdriver: specifier: workspace:* @@ -1836,7 +1851,7 @@ importers: specifier: workspace:* version: link:../../../packages/wdio-utils expect-webdriverio: - specifier: ^5.3.1 + specifier: ^5.3.4 version: 5.3.4(@wdio/globals@packages+wdio-globals)(@wdio/logger@9.16.2)(webdriverio@packages+webdriverio) webdriver: specifier: workspace:* @@ -5085,20 +5100,20 @@ packages: '@surma/rollup-plugin-off-main-thread@2.2.3': resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==} - '@sveltejs/vite-plugin-svelte-inspector@4.0.1': - resolution: {integrity: sha512-J/Nmb2Q2y7mck2hyCX4ckVHcR5tu2J+MtBEQqpDrrgELZ2uvraQcK/ioCV61AqkdXFgriksOKIceDcQmqnGhVw==} + '@sveltejs/vite-plugin-svelte-inspector@3.0.1': + resolution: {integrity: sha512-2CKypmj1sM4GE7HjllT7UKmo4Q6L5xFRd7VMGEWhYnZ+wc6AUVU01IBd7yUi6WnFndEwWoMNOd6e8UjoN0nbvQ==} engines: {node: ^18.0.0 || ^20.0.0 || >=22} peerDependencies: - '@sveltejs/vite-plugin-svelte': ^5.0.0 - svelte: ^5.0.0 - vite: ^6.0.0 + '@sveltejs/vite-plugin-svelte': ^4.0.0-next.0||^4.0.0 + svelte: ^5.0.0-next.96 || ^5.0.0 + vite: ^5.0.0 - '@sveltejs/vite-plugin-svelte@5.1.0': - resolution: {integrity: sha512-wojIS/7GYnJDYIg1higWj2ROA6sSRWvcR1PO/bqEyFr/5UZah26c8Cz4u0NaqjPeVltzsVpt2Tm8d2io0V+4Tw==} + '@sveltejs/vite-plugin-svelte@4.0.2': + resolution: {integrity: sha512-Y9r/fWy539XlAC7+5wfNJ4zH6TygUYoQ0Eegzp0zDDqhJ54+92gOyOX1l4MO1cJSx0O+Gp13YePT5XEa3+kX0w==} engines: {node: ^18.0.0 || ^20.0.0 || >=22} peerDependencies: - svelte: ^5.0.0 - vite: ^6.0.0 + svelte: ^5.0.0-next.96 || ^5.0.0 + vite: ^5.0.0 '@svgr/babel-plugin-add-jsx-attribute@8.0.0': resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==} @@ -5879,6 +5894,10 @@ packages: resolution: {integrity: sha512-a7zDSNzpGgkb6mWrg9GWPmvh/sZFzaf86/iBjCv+n2DTY0+8v8NLruRQmWuCaQAlLVhM3XAqmB+fWLqxDhdvOA==} engines: {node: '>=18.20.0'} + '@wdio/dot-reporter@9.16.2': + resolution: {integrity: sha512-JzFegviZdpzgvt8w8uwI0pyJguIuJzfzlkkyWz1WUoqtilH4yrf5IYKzObnm3peh7iQ/y2J1SSeAjKr0Hr5xTg==} + engines: {node: '>=18.20.0'} + '@wdio/eslint@0.1.2': resolution: {integrity: sha512-mn3qJcCtMcTqcyGBDLl/TExJ4/uIrIdz/wk2WHChINpHnHd6vHdz1p5cc6SXeffgMmLM2SYqgANHcfSrh+Tp3w==} @@ -5900,6 +5919,17 @@ packages: resolution: {integrity: sha512-FLTF0VL6+o5BSTCO7yLSXocm3kUnu31zYwzdsz4n9s5YWt83sCtzGZlZpt7TaTzb3jVUfxuHNQDTb8UMkCu0lQ==} engines: {node: '>=18.20.0'} + '@wdio/reporter@9.16.2': + resolution: {integrity: sha512-th+APMRuK03OzpiJKnfhCwnXoJb57mRmP/NQYGc+k9GEF3Z3yPDD7LxnBlwPANGxt/hdzirQ6OvQyJYLwpmmuQ==} + engines: {node: '>=18.20.0'} + + '@wdio/runner@9.16.2': + resolution: {integrity: sha512-cETsJivOD2yzJfzwKi1n7NNXL3zF/yTcA+578fiu48iGVmhOJNhgW9sv4oVH/aDCt09PPUZw6DEBOT3mcKDSGw==} + engines: {node: '>=18.20.0'} + peerDependencies: + expect-webdriverio: ^5.3.2 + webdriverio: ^9.0.0 + '@wdio/types@9.16.2': resolution: {integrity: sha512-P86FvM/4XQGpJKwlC2RKF3I21TglPvPOozJGG9HoL0Jmt6jRF20ggO/nRTxU0XiWkRdqESUTmfA87bdCO4GRkQ==} engines: {node: '>=18.20.0'} @@ -8035,14 +8065,6 @@ packages: resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==} engines: {node: '>=12.0.0'} - expect-webdriverio@5.3.1: - resolution: {integrity: sha512-xK3ZKMCeyKCXlE2C9RILFOhI0hgdY3cy6EXWLI9+EsYLEwy/8+2tDPwrL6ZPQ8mSCiV259sJYhNZzCSD/2/jaA==} - engines: {node: '>=18 || >=20 || >=22'} - peerDependencies: - '@wdio/globals': ^9.0.0 - '@wdio/logger': ^9.0.0 - webdriverio: ^9.0.0 - expect-webdriverio@5.3.4: resolution: {integrity: sha512-FU+96C0nqeYTXrJcGLUDB6hPKKaSm1/tVHjFDE4EDHGCYvajAHCC2MBQJ5MomjCmp6lGMz36lDHeZj52LHylyA==} engines: {node: '>=18 || >=20 || >=22'} @@ -15587,7 +15609,7 @@ snapshots: '@cucumber/ci-environment': 10.0.1 '@cucumber/cucumber-expressions': 17.1.0 '@cucumber/gherkin': 28.0.0 - '@cucumber/gherkin-streams': 5.0.1(@cucumber/gherkin@28.0.0)(@cucumber/message-streams@4.0.1(@cucumber/messages@24.1.0))(@cucumber/messages@24.1.0) + '@cucumber/gherkin-streams': 5.0.1(@cucumber/gherkin@28.0.0)(@cucumber/message-streams@4.0.1(@cucumber/messages@26.0.1))(@cucumber/messages@24.1.0) '@cucumber/gherkin-utils': 9.0.0 '@cucumber/html-formatter': 21.6.0(@cucumber/messages@24.1.0) '@cucumber/message-streams': 4.0.1(@cucumber/messages@24.1.0) @@ -15627,7 +15649,7 @@ snapshots: yaml: 2.8.0 yup: 1.2.0 - '@cucumber/gherkin-streams@5.0.1(@cucumber/gherkin@28.0.0)(@cucumber/message-streams@4.0.1(@cucumber/messages@24.1.0))(@cucumber/messages@24.1.0)': + '@cucumber/gherkin-streams@5.0.1(@cucumber/gherkin@28.0.0)(@cucumber/message-streams@4.0.1(@cucumber/messages@26.0.1))(@cucumber/messages@24.1.0)': dependencies: '@cucumber/gherkin': 28.0.0 '@cucumber/message-streams': 4.0.1(@cucumber/messages@24.1.0) @@ -18435,18 +18457,27 @@ snapshots: magic-string: 0.25.9 string.prototype.matchall: 4.0.12 - '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.0(svelte@4.2.20)(vite@5.4.19(@types/node@20.19.2)(terser@5.43.1)))(svelte@4.2.20)(vite@5.4.19(@types/node@20.19.2)(terser@5.43.1))': + '@sveltejs/vite-plugin-svelte-inspector@3.0.1(@sveltejs/vite-plugin-svelte@4.0.2(svelte@4.2.20)(vite@5.4.19(@types/node@20.19.2)(terser@5.43.1)))(svelte@4.2.20)(vite@5.4.19(@types/node@20.19.2)(terser@5.43.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 5.1.0(svelte@4.2.20)(vite@5.4.19(@types/node@20.19.2)(terser@5.43.1)) + '@sveltejs/vite-plugin-svelte': 4.0.2(svelte@4.2.20)(vite@5.4.19(@types/node@20.19.2)(terser@5.43.1)) debug: 4.4.1(supports-color@8.1.1) svelte: 4.2.20 vite: 5.4.19(@types/node@20.19.2)(terser@5.43.1) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@5.1.0(svelte@4.2.20)(vite@5.4.19(@types/node@20.19.2)(terser@5.43.1))': + '@sveltejs/vite-plugin-svelte-inspector@3.0.1(@sveltejs/vite-plugin-svelte@4.0.2(svelte@4.2.20)(vite@5.4.19(@types/node@22.15.34)(terser@5.43.1)))(svelte@4.2.20)(vite@5.4.19(@types/node@22.15.34)(terser@5.43.1))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.0(svelte@4.2.20)(vite@5.4.19(@types/node@20.19.2)(terser@5.43.1)))(svelte@4.2.20)(vite@5.4.19(@types/node@20.19.2)(terser@5.43.1)) + '@sveltejs/vite-plugin-svelte': 4.0.2(svelte@4.2.20)(vite@5.4.19(@types/node@22.15.34)(terser@5.43.1)) + debug: 4.4.1(supports-color@8.1.1) + svelte: 4.2.20 + vite: 5.4.19(@types/node@22.15.34)(terser@5.43.1) + transitivePeerDependencies: + - supports-color + + '@sveltejs/vite-plugin-svelte@4.0.2(svelte@4.2.20)(vite@5.4.19(@types/node@20.19.2)(terser@5.43.1))': + dependencies: + '@sveltejs/vite-plugin-svelte-inspector': 3.0.1(@sveltejs/vite-plugin-svelte@4.0.2(svelte@4.2.20)(vite@5.4.19(@types/node@20.19.2)(terser@5.43.1)))(svelte@4.2.20)(vite@5.4.19(@types/node@20.19.2)(terser@5.43.1)) debug: 4.4.1(supports-color@8.1.1) deepmerge: 4.3.1 kleur: 4.1.5 @@ -18457,6 +18488,19 @@ snapshots: transitivePeerDependencies: - supports-color + '@sveltejs/vite-plugin-svelte@4.0.2(svelte@4.2.20)(vite@5.4.19(@types/node@22.15.34)(terser@5.43.1))': + dependencies: + '@sveltejs/vite-plugin-svelte-inspector': 3.0.1(@sveltejs/vite-plugin-svelte@4.0.2(svelte@4.2.20)(vite@5.4.19(@types/node@22.15.34)(terser@5.43.1)))(svelte@4.2.20)(vite@5.4.19(@types/node@22.15.34)(terser@5.43.1)) + debug: 4.4.1(supports-color@8.1.1) + deepmerge: 4.3.1 + kleur: 4.1.5 + magic-string: 0.30.17 + svelte: 4.2.20 + vite: 5.4.19(@types/node@22.15.34)(terser@5.43.1) + vitefu: 1.0.7(vite@5.4.19(@types/node@22.15.34)(terser@5.43.1)) + transitivePeerDependencies: + - supports-color + '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.27.7)': dependencies: '@babel/core': 7.27.7 @@ -19420,6 +19464,12 @@ snapshots: - bare-buffer - supports-color + '@wdio/dot-reporter@9.16.2': + dependencies: + '@wdio/reporter': 9.16.2 + '@wdio/types': 9.16.2 + chalk: 5.4.1 + '@wdio/eslint@0.1.2(@typescript-eslint/eslint-plugin@8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)': dependencies: '@eslint/js': 9.30.0 @@ -19436,9 +19486,9 @@ snapshots: - supports-color - typescript - '@wdio/globals@9.16.2(expect-webdriverio@5.3.1)(webdriverio@9.16.2(puppeteer-core@24.11.2))': + '@wdio/globals@9.16.2(expect-webdriverio@5.3.4(@wdio/globals@packages+wdio-globals)(@wdio/logger@packages+wdio-logger)(webdriverio@9.16.2(puppeteer-core@24.11.2)))(webdriverio@9.16.2(puppeteer-core@24.11.2))': dependencies: - expect-webdriverio: 5.3.1(@wdio/globals@9.16.2)(@wdio/logger@9.16.2)(webdriverio@9.16.2(puppeteer-core@24.11.2)) + expect-webdriverio: 5.3.4(@wdio/globals@packages+wdio-globals)(@wdio/logger@packages+wdio-logger)(webdriverio@9.16.2(puppeteer-core@24.11.2)) webdriverio: 9.16.2(puppeteer-core@24.11.2) '@wdio/globals@9.16.2(expect-webdriverio@5.3.4(@wdio/globals@packages+wdio-globals)(@wdio/logger@packages+wdio-logger)(webdriverio@packages+webdriverio))(webdriverio@9.16.2(puppeteer-core@24.11.2))': @@ -19464,6 +19514,33 @@ snapshots: dependencies: '@types/node': 20.19.2 + '@wdio/reporter@9.16.2': + dependencies: + '@types/node': 20.19.2 + '@wdio/logger': 9.16.2 + '@wdio/types': 9.16.2 + diff: 7.0.0 + object-inspect: 1.13.4 + + '@wdio/runner@9.16.2(expect-webdriverio@5.3.4(@wdio/globals@packages+wdio-globals)(@wdio/logger@packages+wdio-logger)(webdriverio@9.16.2(puppeteer-core@24.11.2)))(webdriverio@9.16.2(puppeteer-core@24.11.2))': + dependencies: + '@types/node': 20.19.2 + '@wdio/config': 9.16.2 + '@wdio/dot-reporter': 9.16.2 + '@wdio/globals': 9.16.2(expect-webdriverio@5.3.4(@wdio/globals@packages+wdio-globals)(@wdio/logger@packages+wdio-logger)(webdriverio@9.16.2(puppeteer-core@24.11.2)))(webdriverio@9.16.2(puppeteer-core@24.11.2)) + '@wdio/logger': 9.16.2 + '@wdio/types': 9.16.2 + '@wdio/utils': 9.16.2 + deepmerge-ts: 7.1.5 + expect-webdriverio: 5.3.4(@wdio/globals@packages+wdio-globals)(@wdio/logger@packages+wdio-logger)(webdriverio@9.16.2(puppeteer-core@24.11.2)) + webdriver: 9.16.2 + webdriverio: 9.16.2(puppeteer-core@24.11.2) + transitivePeerDependencies: + - bare-buffer + - bufferutil + - supports-color + - utf-8-validate + '@wdio/types@9.16.2': dependencies: '@types/node': 20.19.2 @@ -21948,16 +22025,6 @@ snapshots: expect-type@1.2.1: {} - expect-webdriverio@5.3.1(@wdio/globals@9.16.2)(@wdio/logger@9.16.2)(webdriverio@9.16.2(puppeteer-core@24.11.2)): - dependencies: - '@vitest/snapshot': 3.2.4 - '@wdio/globals': 9.16.2(expect-webdriverio@5.3.1)(webdriverio@9.16.2(puppeteer-core@24.11.2)) - '@wdio/logger': 9.16.2 - expect: 30.0.3 - jest-matcher-utils: 30.0.3 - lodash.isequal: 4.5.0 - webdriverio: 9.16.2(puppeteer-core@24.11.2) - expect-webdriverio@5.3.4(@wdio/globals@9.16.2)(@wdio/logger@9.16.2)(webdriverio@9.16.2(puppeteer-core@24.11.2)): dependencies: '@vitest/snapshot': 3.2.4 @@ -23518,7 +23585,7 @@ snapshots: jest-diff@29.7.0: dependencies: - chalk: 4.1.0 + chalk: 4.1.2 diff-sequences: 29.6.3 jest-get-type: 29.6.3 pretty-format: 29.7.0 @@ -25273,7 +25340,7 @@ snapshots: '@yarnpkg/parsers': 3.0.2 '@zkochan/js-yaml': 0.0.7 axios: 1.10.0 - chalk: 4.1.0 + chalk: 4.1.2 cli-cursor: 3.1.0 cli-spinners: 2.6.1 cliui: 8.0.1 @@ -25395,7 +25462,7 @@ snapshots: ora@5.3.0: dependencies: bl: 4.1.0 - chalk: 4.1.0 + chalk: 4.1.2 cli-cursor: 3.1.0 cli-spinners: 2.6.1 is-interactive: 1.0.0 @@ -28503,6 +28570,10 @@ snapshots: optionalDependencies: vite: 5.4.19(@types/node@20.19.2)(terser@5.43.1) + vitefu@1.0.7(vite@5.4.19(@types/node@22.15.34)(terser@5.43.1)): + optionalDependencies: + vite: 5.4.19(@types/node@22.15.34)(terser@5.43.1) + vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.2)(jsdom@26.1.0)(terser@5.43.1): dependencies: '@types/chai': 5.2.2 diff --git a/tests/package.json b/tests/package.json index ed13d6dbd..dfdf0789a 100644 --- a/tests/package.json +++ b/tests/package.json @@ -3,7 +3,7 @@ "private": true, "type": "module", "dependencies": { - "expect-webdriverio": "^5.3.1", + "expect-webdriverio": "^5.3.4", "webdriver": "workspace:*", "webdriverio": "workspace:*", "@wdio/cli": "workspace:*", diff --git a/tests/typings/jasmine/package.json b/tests/typings/jasmine/package.json index dcca6663f..9164c2d8a 100644 --- a/tests/typings/jasmine/package.json +++ b/tests/typings/jasmine/package.json @@ -25,7 +25,7 @@ "@wdio/static-server-service": "workspace:*", "@wdio/sumologic-reporter": "workspace:*", "@wdio/testingbot-service": "workspace:*", - "expect-webdriverio": "^5.3.1", + "expect-webdriverio": "^5.3.4", "webdriver": "workspace:*", "webdriverio": "workspace:*" }