diff --git a/__mocks__/mocha.ts b/__mocks__/mocha.ts new file mode 100644 index 000000000..940e9a67e --- /dev/null +++ b/__mocks__/mocha.ts @@ -0,0 +1,50 @@ +import { vi } from 'vitest' + +export default class MochaMock { + loadFiles = vi.fn() + loadFilesAsync = vi.fn() + reporter = vi.fn() + fullTrace = vi.fn() + addFile = vi.fn() + run = vi.fn() + + mockFailureCount: number + suite: { on: any } + runner: { + on: any + suite: any + test: any + } + + constructor (private mochaOpts: any) { + this.suite = { + on: vi.fn() + } + + this.runner = { + on: vi.fn(), + suite: { + beforeAll: vi.fn(), + beforeEach: vi.fn(), + afterEach: vi.fn(), + afterAll: vi.fn(), + suites: [{ 'title': 'first suite' }] + }, + test: { 'title': 'first test' } + } + + this.mockFailureCount = mochaOpts.mockFailureCount || 0 + this.run = vi.fn().mockImplementation((cb) => { + if (mochaOpts.mockRuntimeError) { + throw mochaOpts.mockRuntimeError + } + + cb(this.mockFailureCount) + return this.runner + }) + } + + static Runner = vi.fn().mockImplementation(function (total) { + return { grep: vi.fn(), total } + }) +} diff --git a/packages/wdio-mocha-framework/tests/__mocks__/randomModule.js b/__mocks__/randomModule.js similarity index 100% rename from packages/wdio-mocha-framework/tests/__mocks__/randomModule.js rename to __mocks__/randomModule.js diff --git a/package-lock.json b/package-lock.json index 45f1a76e2..9b9976095 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,50 +7,50 @@ "name": "webdriverio-monorepo", "hasInstallScript": true, "devDependencies": { - "@cucumber/cucumber": "^8.0.0-rc.1", + "@cucumber/cucumber": "^8.2.1", "@octokit/rest": "^19.0.3", - "@tsconfig/node12": "^1.0.9", + "@tsconfig/node16": "^1.0.2", "@types/archiver": "^5.3.1", "@types/cheerio": "^0.22.31", "@types/eslint": "^8.4.2", "@types/fs-extra": "^9.0.13", - "@types/lodash.clonedeep": "^4.5.6", - "@types/lodash.isobject": "^3.0.6", - "@types/lodash.isplainobject": "^4.0.6", - "@types/lodash.merge": "^4.6.6", - "@types/lodash.zip": "^4.2.6", + "@types/lodash.clonedeep": "^4.5.7", + "@types/lodash.isobject": "^3.0.7", + "@types/lodash.isplainobject": "^4.0.7", + "@types/lodash.merge": "^4.6.7", + "@types/lodash.zip": "^4.2.7", "@types/node": "^18.0.0", "@types/split2": "^3.2.1", "@types/uuid": "^8.3.4", - "@typescript-eslint/eslint-plugin": "^5.22.0", - "@typescript-eslint/parser": "^5.22.0", - "@typescript-eslint/utils": "^5.14.0", - "aws-sdk": "^2.1127.0", - "c8": "^7.11.2", + "@typescript-eslint/eslint-plugin": "^5.26.0", + "@typescript-eslint/parser": "^5.26.0", + "@typescript-eslint/utils": "^5.26.0", + "aws-sdk": "^2.1142.0", + "c8": "^7.11.3", "camelcase": "^6.3.0", - "cheerio": "^1.0.0-rc.10", + "cheerio": "^1.0.0-rc.11", "copyfiles": "^2.4.1", - "del": "^6.0.0", + "del": "^6.1.1", "depcheck": "^1.4.3", - "ejs": "^3.1.6", - "eslint": "^8.15.0", + "ejs": "^3.1.8", + "eslint": "^8.16.0", "eslint-plugin-unicorn": "^42.0.0", "husky": "^8.0.1", - "inquirer": "^8.2.1", + "inquirer": "^8.2.4", "lerna": "^5.0.0", "lerna-changelog": "^2.2.0", "markdox": "^0.1.10", - "mime-types": "^2.1.34", + "mime-types": "^2.1.35", "npm-run-all": "^4.1.5", "recursive-readdir": "^2.2.2", "request": "^2.88.2", "rimraf": "^3.0.2", "shelljs": "^0.8.5", - "tempy": "^1.0.1", - "ts-node": "^10.7.0", - "typescript": "^4.6.2", - "url-join": "^4.0.1", - "vitest": "^0.12.4" + "tempy": "^3.0.0", + "ts-node": "^10.8.0", + "typescript": "^4.7.2", + "url-join": "^5.0.0", + "vitest": "^0.12.9" } }, "node_modules/@babel/code-frame": { @@ -4422,12 +4422,30 @@ } }, "node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "dev": true, + "dependencies": { + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/css-select": { @@ -11597,19 +11615,30 @@ } }, "node_modules/tempy": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz", - "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.0.0.tgz", + "integrity": "sha512-B2I9X7+o2wOaW4r/CWMkpOO9mdiTRCxXNgob6iGvPmfPWgH/KyUD6Uy5crtWBxIBe3YrNZKR2lSzv1JJKWD4vA==", "dev": true, "dependencies": { - "del": "^6.0.0", - "is-stream": "^2.0.0", + "is-stream": "^3.0.0", "temp-dir": "^2.0.0", - "type-fest": "^0.16.0", - "unique-string": "^2.0.0" + "type-fest": "^2.12.2", + "unique-string": "^3.0.0" }, "engines": { - "node": ">=10" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11625,12 +11654,12 @@ } }, "node_modules/tempy/node_modules/type-fest": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.16.0.tgz", + "integrity": "sha512-qpaThT2HQkFb83gMOrdKVsfCN7LKxP26Yq+smPzY1FqoHRjqmjqHXA7n5Gkxi8efirtbeEUxzfEdePthQWCuHw==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -12045,15 +12074,18 @@ } }, "node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", "dev": true, "dependencies": { - "crypto-random-string": "^2.0.0" + "crypto-random-string": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/universal-user-agent": { @@ -12119,10 +12151,13 @@ } }, "node_modules/url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", - "dev": true + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", + "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } }, "node_modules/url/node_modules/punycode": { "version": "1.3.2", @@ -16237,10 +16272,21 @@ } }, "crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "dev": true, + "requires": { + "type-fest": "^1.0.1" + }, + "dependencies": { + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true + } + } }, "css-select": { "version": "5.1.0", @@ -21622,18 +21668,23 @@ "dev": true }, "tempy": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz", - "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.0.0.tgz", + "integrity": "sha512-B2I9X7+o2wOaW4r/CWMkpOO9mdiTRCxXNgob6iGvPmfPWgH/KyUD6Uy5crtWBxIBe3YrNZKR2lSzv1JJKWD4vA==", "dev": true, "requires": { - "del": "^6.0.0", - "is-stream": "^2.0.0", + "is-stream": "^3.0.0", "temp-dir": "^2.0.0", - "type-fest": "^0.16.0", - "unique-string": "^2.0.0" + "type-fest": "^2.12.2", + "unique-string": "^3.0.0" }, "dependencies": { + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true + }, "temp-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", @@ -21641,9 +21692,9 @@ "dev": true }, "type-fest": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.16.0.tgz", + "integrity": "sha512-qpaThT2HQkFb83gMOrdKVsfCN7LKxP26Yq+smPzY1FqoHRjqmjqHXA7n5Gkxi8efirtbeEUxzfEdePthQWCuHw==", "dev": true } } @@ -21966,12 +22017,12 @@ } }, "unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", "dev": true, "requires": { - "crypto-random-string": "^2.0.0" + "crypto-random-string": "^4.0.0" } }, "universal-user-agent": { @@ -22035,9 +22086,9 @@ } }, "url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", + "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", "dev": true }, "util": { diff --git a/package.json b/package.json index 50de657ec..15c137f6e 100644 --- a/package.json +++ b/package.json @@ -59,49 +59,49 @@ "postinstall:vulnerabilities": "node ./.husky/postinstall.js" }, "devDependencies": { - "@cucumber/cucumber": "^8.0.0-rc.1", + "@cucumber/cucumber": "^8.2.1", "@octokit/rest": "^19.0.3", - "@tsconfig/node12": "^1.0.9", + "@tsconfig/node16": "^1.0.2", "@types/archiver": "^5.3.1", "@types/cheerio": "^0.22.31", "@types/eslint": "^8.4.2", "@types/fs-extra": "^9.0.13", - "@types/lodash.clonedeep": "^4.5.6", - "@types/lodash.isobject": "^3.0.6", - "@types/lodash.isplainobject": "^4.0.6", - "@types/lodash.merge": "^4.6.6", - "@types/lodash.zip": "^4.2.6", + "@types/lodash.clonedeep": "^4.5.7", + "@types/lodash.isobject": "^3.0.7", + "@types/lodash.isplainobject": "^4.0.7", + "@types/lodash.merge": "^4.6.7", + "@types/lodash.zip": "^4.2.7", "@types/node": "^18.0.0", "@types/split2": "^3.2.1", "@types/uuid": "^8.3.4", - "@typescript-eslint/eslint-plugin": "^5.22.0", - "@typescript-eslint/parser": "^5.22.0", - "@typescript-eslint/utils": "^5.14.0", - "aws-sdk": "^2.1127.0", - "c8": "^7.11.2", + "@typescript-eslint/eslint-plugin": "^5.26.0", + "@typescript-eslint/parser": "^5.26.0", + "@typescript-eslint/utils": "^5.26.0", + "aws-sdk": "^2.1142.0", + "c8": "^7.11.3", "camelcase": "^6.3.0", - "cheerio": "^1.0.0-rc.10", + "cheerio": "^1.0.0-rc.11", "copyfiles": "^2.4.1", - "del": "^6.0.0", + "del": "^6.1.1", "depcheck": "^1.4.3", - "ejs": "^3.1.6", - "eslint": "^8.15.0", + "ejs": "^3.1.8", + "eslint": "^8.16.0", "eslint-plugin-unicorn": "^42.0.0", "husky": "^8.0.1", - "inquirer": "^8.2.1", + "inquirer": "^8.2.4", "lerna": "^5.0.0", "lerna-changelog": "^2.2.0", "markdox": "^0.1.10", - "mime-types": "^2.1.34", + "mime-types": "^2.1.35", "npm-run-all": "^4.1.5", "recursive-readdir": "^2.2.2", "request": "^2.88.2", "rimraf": "^3.0.2", "shelljs": "^0.8.5", - "tempy": "^1.0.1", - "ts-node": "^10.7.0", - "typescript": "^4.6.2", - "url-join": "^4.0.1", - "vitest": "^0.12.4" + "tempy": "^3.0.0", + "ts-node": "^10.8.0", + "typescript": "^4.7.2", + "url-join": "^5.0.0", + "vitest": "^0.12.9" } } diff --git a/packages/esm.mjs b/packages/esm.mjs new file mode 100644 index 000000000..7397ea0aa --- /dev/null +++ b/packages/esm.mjs @@ -0,0 +1,3 @@ +import * as foo from '@wdio/devtools-service' + +console.log(foo); diff --git a/packages/wdio-mocha-framework/package.json b/packages/wdio-mocha-framework/package.json index 940f34a3c..3791568be 100644 --- a/packages/wdio-mocha-framework/package.json +++ b/packages/wdio-mocha-framework/package.json @@ -22,11 +22,11 @@ "url": "https://github.com/webdriverio/webdriverio/issues" }, "dependencies": { - "@types/mocha": "^9.0.0", + "@types/mocha": "^9.1.1", "@wdio/logger": "7.19.0", "@wdio/types": "7.20.7", "@wdio/utils": "7.20.7", - "expect-webdriverio": "^3.0.0", + "expect-webdriverio": "^3.4.0", "mocha": "^10.0.0" }, "devDependencies": { diff --git a/packages/wdio-mocha-framework/src/index.ts b/packages/wdio-mocha-framework/src/index.ts index 66b802854..0ac8f529d 100644 --- a/packages/wdio-mocha-framework/src/index.ts +++ b/packages/wdio-mocha-framework/src/index.ts @@ -1,13 +1,14 @@ import path from 'node:path' -import Mocha, { Runner } from 'mocha' import { format } from 'node:util' +import Mocha, { Runner } from 'mocha' import logger from '@wdio/logger' import { runTestInFiberContext, executeHooksWithArgs } from '@wdio/utils' +import { setOptions } from 'expect-webdriverio' import type { Capabilities, Services } from '@wdio/types' -import { loadModule } from './utils' -import { INTERFACES, EVENTS, NOOP, MOCHA_TIMEOUT_MESSAGE, MOCHA_TIMEOUT_MESSAGE_REPLACEMENT } from './constants' +import { loadModule } from './utils.js' +import { INTERFACES, EVENTS, NOOP, MOCHA_TIMEOUT_MESSAGE, MOCHA_TIMEOUT_MESSAGE_REPLACEMENT } from './constants.js' import type { MochaConfig, MochaOpts as MochaOptsImport, FrameworkMessage, FormattedMessage, MochaContext, MochaError } from './types' import type { EventEmitter } from 'node:events' import type ExpectWebdriverIO from 'expect-webdriverio' @@ -68,11 +69,6 @@ class MochaAdapter { mocha.suite.on('pre-require', this.preRequire.bind(this)) await this._loadFiles(mochaOpts) - /** - * import and set options for `expect-webdriverio` assertion lib once - * the framework was initiated so that it can detect the environment - */ - const { setOptions } = require('expect-webdriverio') setOptions({ wait: this._config.waitforTimeout, // ms to wait for expectation to succeed interval: this._config.waitforInterval, // interval between attempts @@ -150,7 +146,7 @@ class MochaAdapter { require = [require] } - this.requireExternalModules([...compilers, ...require], context) + return this.requireExternalModules([...compilers, ...require], context) } preRequire ( @@ -182,7 +178,7 @@ class MochaAdapter { this._cid ) }) - this.options(options, { context, file, mocha, options }) + return this.options(options, { context, file, mocha, options }) } /** @@ -295,9 +291,9 @@ class MochaAdapter { } requireExternalModules (modules: string[], context: MochaContext) { - modules.forEach(module => { + return modules.map((module) => { if (!module) { - return + return Promise.resolve() } module = module.replace(/.*:/, '') @@ -306,7 +302,7 @@ class MochaAdapter { module = path.join(process.cwd(), module) } - loadModule(module, context) + return loadModule(module, context) }) } diff --git a/packages/wdio-mocha-framework/src/utils.ts b/packages/wdio-mocha-framework/src/utils.ts index 38dff9858..9aa532445 100644 --- a/packages/wdio-mocha-framework/src/utils.ts +++ b/packages/wdio-mocha-framework/src/utils.ts @@ -4,7 +4,7 @@ export function loadModule (name: string, context: MochaContext) { try { // @ts-ignore module.context = context - require(name) + return import(name) } catch (err: any) { throw new Error(`Module ${name} can't get loaded. Are you sure you have installed it?\n` + 'Note: if you\'ve installed WebdriverIO globally you need to install ' + diff --git a/packages/wdio-mocha-framework/tests/.eslintrc b/packages/wdio-mocha-framework/tests/.eslintrc deleted file mode 100644 index 55f121d15..000000000 --- a/packages/wdio-mocha-framework/tests/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "env": { - "jest": true - } -} diff --git a/packages/wdio-mocha-framework/tests/__mocks__/mocha.ts b/packages/wdio-mocha-framework/tests/__mocks__/mocha.ts deleted file mode 100644 index 399603473..000000000 --- a/packages/wdio-mocha-framework/tests/__mocks__/mocha.ts +++ /dev/null @@ -1,48 +0,0 @@ -export default class MochaMock { - loadFiles = jest.fn() - loadFilesAsync = jest.fn() - reporter = jest.fn() - fullTrace = jest.fn() - addFile = jest.fn() - run = jest.fn() - - mockFailureCount: number - suite: { on: jest.Mock } - runner: { - on: jest.Mock - suite: any - test: any - } - - constructor (private mochaOpts) { - this.suite = { - on: jest.fn() - } - - this.runner = { - on: jest.fn(), - suite: { - beforeAll: jest.fn(), - beforeEach: jest.fn(), - afterEach: jest.fn(), - afterAll: jest.fn(), - suites: [{ 'title': 'first suite' }] - }, - test: { 'title': 'first test' } - } - - this.mockFailureCount = mochaOpts.mockFailureCount || 0 - this.run = jest.fn().mockImplementation((cb) => { - if (mochaOpts.mockRuntimeError) { - throw mochaOpts.mockRuntimeError - } - - cb(this.mockFailureCount) - return this.runner - }) - } - - static Runner = jest.fn().mockImplementation(function (total) { - return { grep: jest.fn(), total } - }) -} diff --git a/packages/wdio-mocha-framework/tests/__snapshots__/adapter.test.ts.snap b/packages/wdio-mocha-framework/tests/__snapshots__/adapter.test.ts.snap index eed3582c8..69831d4e7 100644 --- a/packages/wdio-mocha-framework/tests/__snapshots__/adapter.test.ts.snap +++ b/packages/wdio-mocha-framework/tests/__snapshots__/adapter.test.ts.snap @@ -1,14 +1,14 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Vitest Snapshot v1 -exports[`formatMessage should do nothing if no error or params are given 1`] = ` -Object { +exports[`formatMessage > should do nothing if no error or params are given 1`] = ` +{ "type": "foobar", } `; -exports[`formatMessage should format an error message 1`] = ` -Object { - "error": Object { +exports[`formatMessage > should format an error message 1`] = ` +{ + "error": { "actual": undefined, "expected": undefined, "message": "uups", @@ -19,10 +19,10 @@ Object { } `; -exports[`formatMessage should format an error message with timeout error 1`] = ` -Object { +exports[`formatMessage > should format an error message with timeout error 1`] = ` +{ "duration": undefined, - "error": Object { + "error": { "actual": undefined, "expected": undefined, "message": "The execution in the test \\"parentfoo barfoo\\" took too long. Try to reduce the run time or increase your timeout for test specs (https://webdriver.io/docs/timeouts).", @@ -38,8 +38,8 @@ Object { } `; -exports[`formatMessage should format payload 1`] = ` -Object { +exports[`formatMessage > should format payload 1`] = ` +{ "context": "some context", "currentTest": "current test", "duration": undefined, diff --git a/packages/wdio-mocha-framework/tests/adapter.test.ts b/packages/wdio-mocha-framework/tests/adapter.test.ts index 8ed8da08d..471cb1efa 100644 --- a/packages/wdio-mocha-framework/tests/adapter.test.ts +++ b/packages/wdio-mocha-framework/tests/adapter.test.ts @@ -1,3 +1,4 @@ +import { describe, test, expect, vi, beforeEach, afterEach } from 'vitest' import path from 'node:path' import Mocha from 'mocha' import logger from '@wdio/logger' @@ -8,14 +9,18 @@ import MochaAdapterFactory, { MochaAdapter } from '../src' import { loadModule } from '../src/utils' import { EVENTS } from '../src/constants' -jest.mock('../src/utils', () => ({ - loadModule: jest.fn() +vi.mock('mocha') +vi.mock('@wdio/utils') +vi.mock('@wdio/logger', () => import(path.join(process.cwd(), '__mocks__', '@wdio/logger'))) +vi.mock('expect-webdriverio') +vi.mock('../src/utils', () => ({ + loadModule: vi.fn() })) const wdioReporter = { - write: jest.fn(), - emit: jest.fn(), - on: jest.fn() + write: vi.fn(), + emit: vi.fn(), + on: vi.fn() } as const const adapterFactory = (config: any) => new MochaAdapter( '0-2', @@ -58,7 +63,7 @@ test('should properly set up mocha', async () => { expect(adapter['_mocha']!.reporter).toBeCalled() expect(adapter['_mocha']!.fullTrace).toBeCalled() expect(adapter['_mocha']!.run).toBeCalled() - expect((executeHooksWithArgs as jest.Mock).mock.calls).toHaveLength(1) + expect(vi.mocked(executeHooksWithArgs).mock.calls).toHaveLength(1) // @ts-ignore outdated types const runner = adapter['_mocha']!['runner'] @@ -96,7 +101,7 @@ test('should throw runtime error if spec could not be loaded', async () => { test('options', () => { // @ts-ignore params not needed for test scenario const adapter = adapterFactory() - adapter.requireExternalModules = jest.fn() + adapter.requireExternalModules = vi.fn() adapter.options({ require: ['foo/bar.js'], compilers: ['the/compiler.js'] @@ -119,7 +124,7 @@ test('preRequire', () => { expect(runTestInFiberContext).toBeCalledWith( false, 'beforeHook123', expect.any(Function), 'afterHook123', expect.any(Function), 'teardown', '0-2') - const hookArgsFn = (runTestInFiberContext as jest.Mock).mock.calls[0][2] + const hookArgsFn = vi.mocked(runTestInFiberContext).mock.calls[0][2] expect(hookArgsFn({ test: { foo: 'bar', parent: { title: 'parent' } } })) .toEqual([{ foo: 'bar', parent: 'parent' }, { test: { foo: 'bar', parent: { title: 'parent' } } }]) }) @@ -143,11 +148,11 @@ test('wrapHook if successful', async () => { const adapter = adapterFactory(config) const wrappedHook = adapter.wrapHook('beforeAll' as any) - ;(executeHooksWithArgs as jest.Mock).mockImplementation((...args) => Promise.resolve(args)) + vi.mocked(executeHooksWithArgs).mockImplementation((...args: any[]) => Promise.resolve(args)) await wrappedHook() - expect((executeHooksWithArgs as jest.Mock).mock.calls[0][0]).toBe('beforeAll') - expect((executeHooksWithArgs as jest.Mock).mock.calls[0][1]).toBe('somehook') - expect((executeHooksWithArgs as jest.Mock).mock.calls[0][2][0].type).toBe('beforeAll') + 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] as any)[0].type).toBe('beforeAll') }) test('wrapHook if failing', async () => { @@ -155,15 +160,15 @@ test('wrapHook if failing', async () => { const adapter = adapterFactory(config) const wrappedHook = adapter.wrapHook('beforeAll' as any) - ;(executeHooksWithArgs as jest.Mock).mockImplementation(() => Promise.reject(new Error('uuuups'))) + vi.mocked(executeHooksWithArgs).mockImplementation(() => Promise.reject(new Error('uuuups'))) await wrappedHook() - expect((executeHooksWithArgs as jest.Mock).mock.calls[0][0]) + expect(vi.mocked(executeHooksWithArgs).mock.calls[0][0]) .toBe('beforeAll') - expect((executeHooksWithArgs as jest.Mock).mock.calls[0][1]) + expect(vi.mocked(executeHooksWithArgs).mock.calls[0][1]) .toBe('somehook') - expect((executeHooksWithArgs as jest.Mock).mock.calls[0][2][0].type) + expect((vi.mocked(executeHooksWithArgs).mock.calls[0][2] as any)[0].type) .toBe('beforeAll') - expect((logger('').error as jest.Mock).mock.calls[0][0] + expect(vi.mocked(logger('').error).mock.calls[0][0] .startsWith('Error in beforeAll hook: uuuups')).toBe(true) }) @@ -186,7 +191,7 @@ test('prepareMessage', async () => { expect(result.type).toBe('afterSuite') expect(result.title).toBe('first suite') expect(result.duration).toBeDefined() - expect(result.duration >= 5000 && result.duration <= 5020).toBeTruthy() + expect(result.duration! >= 5000 && result.duration! <= 5020).toBeTruthy() }) describe('formatMessage', () => { @@ -471,7 +476,7 @@ describe('loadFiles', () => { const adapter = adapterFactory({}) adapter['_hasTests'] = false adapter['_mocha']! = { - loadFilesAsync: jest.fn(), + loadFilesAsync: vi.fn(), suite: 1 // mochaRunner.total } as any await adapter._loadFiles({}) @@ -482,12 +487,12 @@ describe('loadFiles', () => { const adapter = adapterFactory({}) adapter['_hasTests'] = false adapter['_mocha']! = { - loadFilesAsync: jest.fn(), + loadFilesAsync: vi.fn(), options: { grep: 'regexp foo' }, suite: 0 // mochaRunner.total } as any await adapter._loadFiles({ grep: 'foo', invert: 'invert' as any }) - expect((Mocha.Runner as any as jest.Mock).mock.results[0].value.grep).toBeCalledWith('regexp foo', 'invert') + expect(vi.mocked(Mocha.Runner).mock.results[0].value.grep).toBeCalledWith('regexp foo', 'invert') expect(adapter['_hasTests']).toBe(false) }) @@ -496,7 +501,7 @@ describe('loadFiles', () => { // @ts-ignore test scenario delete adapter['_hasTests'] adapter['_mocha']! = { - loadFilesAsync: jest.fn().mockImplementation( + loadFilesAsync: vi.fn().mockImplementation( () => Promise.reject(new Error('foo')) ), } as any @@ -520,8 +525,8 @@ describe('hasTests', () => { }) afterEach(() => { - (Mocha.Runner as any as jest.Mock).mockClear() - ;(runTestInFiberContext as jest.Mock).mockReset() - ;(executeHooksWithArgs as jest.Mock).mockReset() - ;(setOptions as jest.Mock).mockClear() + vi.mocked(Mocha.Runner).mockClear() + vi.mocked(runTestInFiberContext).mockReset() + vi.mocked(executeHooksWithArgs).mockReset() + vi.mocked(setOptions).mockClear() }) diff --git a/packages/wdio-mocha-framework/tests/utils.test.ts b/packages/wdio-mocha-framework/tests/utils.test.ts index 442503399..61b4716e7 100644 --- a/packages/wdio-mocha-framework/tests/utils.test.ts +++ b/packages/wdio-mocha-framework/tests/utils.test.ts @@ -1,17 +1,21 @@ +import path from 'node:path' +import { test, expect, vi, afterAll } from 'vitest' import { loadModule } from '../src/utils' declare global { var foo: string | undefined } -test('loadModule with existing package', () => { - loadModule('randomModule', { foo: 'bar' } as any) +vi.mock('randomModule', () => import(path.join(process.cwd(), '__mocks__', 'randomModule'))) + +test('loadModule with existing package', async () => { + await loadModule('randomModule', { foo: 'bar' } as any) expect(global.foo).toBe('bar') }) -test('loadModule with non existing package', () => { - expect(() => loadModule('nonExistingModule', { foo: 'bar' } as any)) - .toThrow('Module nonExistingModule can\'t get loaded') +test('loadModule with non existing package', async () => { + await expect(() => loadModule('nonExistingModule', { foo: 'bar' } as any)) + .rejects.toThrow('Failed to load nonExistingModule') }) afterAll(() => {