update setup

This commit is contained in:
Christian Bromann 2023-06-12 23:56:11 +02:00
parent e9d5d5239b
commit 8cb10cdd52
No known key found for this signature in database
GPG key ID: 355B5D0EA83B4D19
18 changed files with 12735 additions and 18944 deletions

View file

@ -33,7 +33,7 @@
"memory": "8gb",
"storage": "32gb"
},
"postCreateCommand": "npm install && npm run setup-full",
"postCreateCommand": "npm install && npm run setup",
"waitFor": "postCreateCommand",
"postAttachCommand": {
"WebdriverIO Development Environment": "npm run watch",

View file

@ -58,7 +58,7 @@ jobs:
run: npm ci
- name: Release
run: |
npm run setup-full
npm run setup
npm run generate:typings
npx lerna publish ${{github.event.inputs.releaseType}} --exact --yes --dist-tag ${{github.event.inputs.distTag}}
npm run pushReleaseTag

View file

@ -31,7 +31,7 @@ jobs:
env:
DETECT_CHROMEDRIVER_VERSION: true
- name: Bootstrap Packages
run: npm run setup-full
run: npm run setup
env:
GITHUB_AUTH: ${{ secrets.GITHUB_TOKEN }}
- name: Dependency Check
@ -59,7 +59,7 @@ jobs:
env:
DETECT_CHROMEDRIVER_VERSION: true
- name: Bootstrap Packages
run: npm run setup-full
run: npm run setup
env:
GITHUB_AUTH: ${{ secrets.GITHUB_TOKEN }}
- name: Lint / Typings / Unit / Smoke / Component Tests
@ -94,7 +94,7 @@ jobs:
env:
DETECT_CHROMEDRIVER_VERSION: true
- name: Bootstrap Packages
run: npm run setup-full
run: npm run setup
env:
GITHUB_AUTH: ${{ secrets.GITHUB_TOKEN }}
- name: E2E Protocol Tests

1
.gitignore vendored
View file

@ -105,3 +105,4 @@ tests/.retry_succeeded
website/docs/Contribute.md
website/community/Resources.md
scripts/bidi/cddl
browserstack.err

View file

@ -20,7 +20,7 @@ tasks:
- name: Setup WebdriverIO Development Environment
init: |
npm install
npm run setup-full
npm run setup
gp sync-done installation
command: npm run watch
- name: Welcome Bash

View file

@ -93,7 +93,7 @@ You can immediately start working on the code using [a pre-setup Gitpod environm
```sh
$ npm install
$ npm run setup-full
$ npm run setup
```
The second command does two things:

View file

@ -1,7 +1,5 @@
import { vi } from 'vitest'
const Browserstack = {} as any
export const mockIsRunning = vi.fn().mockImplementation(() => true)
export const mockStart = vi.fn().mockImplementation((options, cb) => cb(null, null))
export const mockStop = vi.fn().mockImplementation((cb) => cb(null))
@ -12,9 +10,8 @@ export const mockLocal = vi.fn().mockImplementation(function (this: any) {
this.stop = mockStop
})
Browserstack.Local = class LocalMock {
export class Local {
public isRunning = mockIsRunning
public start = mockStart
public stop = mockStop
}
module.exports = Browserstack

31364
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -2,14 +2,15 @@
"name": "webdriverio-monorepo",
"private": true,
"type": "module",
"workspaces": [
"packages/*"
],
"scripts": {
"create": "node ./scripts/generateSubPackage",
"backport": "node ./scripts/backport.js",
"bootstrap-full": "npm run clean && lerna bootstrap --no-ci && npm run link",
"bootstrap": "run-p clean:* && lerna bootstrap --force-local && npm run link",
"build": "run-s clean:build generate compile copy",
"changelog": "node ./scripts/changelog.js",
"ci": "run-s setup-full test test:e2e",
"ci": "run-s setup test test:e2e",
"clean": "run-p clean-full:* clean:*",
"clean:build": "rimraf ./packages/*/build",
"clean:pkglock": "rimraf ./packages/*/package-lock.json",
@ -28,8 +29,7 @@
"generate:typings": "node --loader ts-node/esm ./scripts/type-generation/generate-all-typings.ts",
"link": "node ./scripts/link.js",
"pushReleaseTag": "node ./scripts/pushTags.js",
"setup-full": "run-s bootstrap-full build",
"setup": "run-s bootstrap build",
"setup": "run-s clean link build",
"docs": "run-s docs:*",
"docs:setup": "cd ./website && npm install && cd ..",
"docs:generate": "run-s clean:website generate:bidi && node --loader ts-node/esm ./scripts/docs-generation/generateDocs.ts",
@ -71,48 +71,48 @@
},
"devDependencies": {
"@cucumber/cucumber": "^9.1.2",
"@octokit/rest": "^19.0.7",
"@octokit/rest": "^19.0.11",
"@preact/preset-vite": "^2.5.0",
"@sveltejs/vite-plugin-svelte": "^2.2.0",
"@tsconfig/node18": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^2.4.1",
"@tsconfig/node18": "^2.0.1",
"@types/archiver": "^5.3.2",
"@types/cheerio": "^0.22.31",
"@types/ejs": "^3.1.2",
"@types/eslint": "^8.37.0",
"@types/eslint": "^8.40.1",
"@types/inquirer": "^9.0.3",
"@types/lodash.clonedeep": "^4.5.7",
"@types/lodash.zip": "^4.2.7",
"@types/node": "^20.1.1",
"@types/node": "^20.3.0",
"@types/shelljs": "^0.8.12",
"@types/split2": "^4.2.0",
"@types/unzipper": "^0.10.6",
"@types/uuid": "^9.0.1",
"@typescript-eslint/eslint-plugin": "^5.59.5",
"@typescript-eslint/parser": "^5.59.5",
"@typescript-eslint/utils": "^5.59.5",
"@types/uuid": "^9.0.2",
"@typescript-eslint/eslint-plugin": "^5.59.11",
"@typescript-eslint/parser": "^5.59.11",
"@typescript-eslint/utils": "^5.59.11",
"@vitejs/plugin-react": "^4.0.0",
"@vitejs/plugin-vue": "^4.2.1",
"@vitest/coverage-c8": "^0.32.0",
"aws-sdk": "^2.1374.0",
"c8": "^7.13.0",
"@vitejs/plugin-vue": "^4.2.3",
"@vitest/coverage-v8": "^0.32.0",
"aws-sdk": "^2.1396.0",
"c8": "^7.14.0",
"camelcase": "^7.0.1",
"cddl": "^0.8.4",
"cddl2ts": "^0.2.1",
"chalk": "^5.2.0",
"cheerio": "^1.0.0-rc.12",
"chromedriver": "^114.0.1",
"chromedriver": "^114.0.2",
"copyfiles": "^2.4.1",
"depcheck": "^1.4.3",
"ejs": "^3.1.9",
"ejs-lint": "^2.0.0",
"eslint": "^8.40.0",
"eslint": "^8.42.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-unicorn": "^47.0.0",
"eslint-plugin-wdio": "^8.8.7",
"husky": "^8.0.3",
"inquirer": "^9.2.2",
"jsdom": "^22.0.0",
"lerna": "^6.6.2",
"inquirer": "^9.2.7",
"jsdom": "^22.1.0",
"lerna": "^7.0.0",
"lerna-changelog": "^2.2.0",
"markdox": "^0.1.10",
"mime-types": "^2.1.35",
@ -120,14 +120,14 @@
"recast": "^0.23.2",
"recursive-readdir": "^2.2.3",
"request": "^2.88.2",
"rimraf": "^3.0.2",
"rimraf": "^5.0.1",
"shelljs": "^0.8.5",
"shx": "^0.3.4",
"tempy": "^3.0.0",
"ts-node": "^10.9.1",
"typescript": "^5.0.4",
"typescript": "^5.1.3",
"unzipper": "^0.10.14",
"url-join": "^5.0.0",
"vitest": "0.30.1"
"vitest": "^0.32.0"
}
}

View file

@ -6,7 +6,7 @@ import getFinder from '../../src/finder/index.js'
import edgeFinder from '../../src/finder/edge.js'
import { darwinGetAppPaths, darwinGetInstallations } from '../../src/finder/finder.js'
import systemProfiler from './systemProfiler.json' assert { type: 'json' }
const systemProfiler = await vi.importActual('./systemProfiler.json')
vi.mock('@wdio/utils', () => import(path.join(process.cwd(), '__mocks__', '@wdio/utils')))

View file

@ -1,7 +1,7 @@
import fs from 'node:fs'
import os from 'node:os'
import path from 'node:path'
import rimraf from 'rimraf'
import { rimraf } from 'rimraf'
import type { Attachment, TestResult } from 'allure-js-commons'
import { AllureGroup, AllureTest, AllureStep } from 'allure-js-commons'
// eslint-disable-next-line

View file

@ -1,20 +1,22 @@
import path from 'node:path'
import { describe, expect, it, vi, beforeEach } from 'vitest'
// @ts-expect-error mock feature
import Browserstack, { mockStart } from 'browserstack-local'
import logger from '@wdio/logger'
import got from 'got'
import fs from 'node:fs'
import os from 'node:os'
import path from 'node:path'
import { describe, expect, it, vi, beforeEach } from 'vitest'
// @ts-expect-error mock feature
import { Local, mockStart } from 'browserstack-local'
import got from 'got'
import logger from '@wdio/logger'
import type { Capabilities, Options } from '@wdio/types'
import BrowserstackLauncher from '../src/launcher.js'
import type { BrowserstackConfig } from '../src/types.js'
import * as utils from '../src/util.js'
import { version as bstackServiceVersion } from '../package.json' assert { type: 'json' }
vi.mock('@wdio/logger', () => import(path.join(process.cwd(), '__mocks__', '@wdio/logger')))
vi.mock('browserstack-local')
const pkg = await vi.importActual('../package.json') as any
const log = logger('test')
const error = new Error('I\'m an error!')
const sleep = (ms: number = 100) => new Promise((resolve) => setTimeout(resolve, ms))
@ -31,7 +33,6 @@ describe('onPrepare', () => {
key: '12345',
capabilities: []
}
const logInfoSpy = vi.spyOn(log, 'info').mockImplementation((string) => string)
vi.spyOn(utils, 'launchTestSession').mockImplementation(() => {})
vi.spyOn(utils, 'isBStackSession').mockImplementation(() => {return true})
@ -39,7 +40,7 @@ describe('onPrepare', () => {
const service = new BrowserstackLauncher({ testObservability: false } as any, caps, config)
service.onPrepare()
expect(logInfoSpy).toHaveBeenCalledWith('app is not defined in browserstack-service config, skipping ...')
expect(log.info).toHaveBeenCalledWith('app is not defined in browserstack-service config, skipping ...')
})
it('should not call local if browserstackLocal is undefined', () => {
@ -50,7 +51,7 @@ describe('onPrepare', () => {
})
service.onPrepare()
expect(logInfoSpy).toHaveBeenNthCalledWith(2, 'browserstackLocal is not enabled - skipping...')
expect(log.info).toHaveBeenNthCalledWith(2, 'browserstackLocal is not enabled - skipping...')
expect(service.browserstackLocal).toBeUndefined()
})
@ -65,7 +66,7 @@ describe('onPrepare', () => {
})
service.onPrepare()
expect(logInfoSpy).toHaveBeenNthCalledWith(2, 'browserstackLocal is not enabled - skipping...')
expect(log.info).toHaveBeenNthCalledWith(2, 'browserstackLocal is not enabled - skipping...')
expect(service.browserstackLocal).toBeUndefined()
})
@ -207,7 +208,7 @@ describe('onPrepare', () => {
})
it('should throw SevereServiceError if _validateApp fails', async () => {
const options: BrowserstackConfig = { app: 'bs://<app-id>' }
const options = { app: 'bs://<app-id>' } as BrowserstackConfig & Options.Testrunner
const service = new BrowserstackLauncher(options, caps, config)
const capabilities = { samsungGalaxy: { capabilities: {} } }
@ -221,7 +222,7 @@ describe('onPrepare', () => {
})
it('should throw SevereServiceError if fs.existsSync fails', async () => {
const options: BrowserstackConfig = { app: { path: '/path/to/app.apk', custom_id: 'custom_id' } }
const options = { app: { path: '/path/to/app.apk', custom_id: 'custom_id' } } as BrowserstackConfig & Options.Testrunner
const service = new BrowserstackLauncher(options, caps, config)
const capabilities = { samsungGalaxy: { capabilities: {} } }
@ -237,13 +238,13 @@ describe('onPrepare', () => {
})
it('should initialize the opts object, and spawn a new Local instance', async () => {
const service = new BrowserstackLauncher(options as any, caps, config)
const service = new BrowserstackLauncher(options as BrowserstackConfig & Options.Testrunner, caps, config)
await service.onPrepare(config, caps)
expect(service.browserstackLocal).toBeDefined()
})
it('should add the "browserstack.local" property to a multiremote capability if no "bstack:options"', async () => {
const service = new BrowserstackLauncher(options as any, caps, config)
const service = new BrowserstackLauncher(options as BrowserstackConfig & Options.Testrunner, caps, config)
const capabilities = { chromeBrowser: { capabilities: {} } }
await service.onPrepare(config, capabilities)
@ -254,7 +255,7 @@ describe('onPrepare', () => {
const service = new BrowserstackLauncher({
browserstackLocal: true,
opts: { localIdentifier: 'wdio1' }
}, caps, {
} as BrowserstackConfig & Options.Testrunner, caps, {
user: 'foobaruser',
key: '12345',
capabilities: []
@ -277,7 +278,7 @@ describe('onPrepare', () => {
const service = new BrowserstackLauncher({
browserstackLocal: true,
opts: { localIdentifier: 'wdio1' }
}, caps, {
} as BrowserstackConfig & Options.Testrunner, caps, {
user: 'foobaruser',
key: '12345',
capabilities: []
@ -300,7 +301,7 @@ describe('onPrepare', () => {
const service = new BrowserstackLauncher({
browserstackLocal: true,
opts: { localIdentifier: 'wdio1' }
}, caps, config)
} as BrowserstackConfig & Options.Testrunner, caps, config)
const capabilities = { chromeBrowser: { capabilities: { 'goog:chromeOptions': {} } } }
await service.onPrepare(config, capabilities)
@ -311,7 +312,7 @@ describe('onPrepare', () => {
const service = new BrowserstackLauncher({
browserstackLocal: true,
opts: { localIdentifier: 'wdio1' }
}, caps, config)
} as BrowserstackConfig & Options.Testrunner, caps, config)
const capabilities = [{ 'bstack:options': {} }, { 'bstack:options': {} }, { 'bstack:options': {} }]
await service.onPrepare(config, capabilities)
@ -338,7 +339,7 @@ describe('onPrepare', () => {
const service = new BrowserstackLauncher({
browserstackLocal: true,
opts: { localIdentifier: 'wdio1' }
}, caps, {
} as BrowserstackConfig & Options.Testrunner, caps, {
user: 'foobaruser',
key: '12345',
capabilities: []
@ -421,7 +422,7 @@ describe('onPrepare', () => {
it('should evaluate and set buildIdentifier from service options', async () => {
const caps: any = { chromeBrowser: { capabilities: { 'bstack:options': { buildName: 'browserstack wdio build', buildIdentifier: 'test ${BUILD_NUMBER}' } } } }
const service = new BrowserstackLauncher({ buildIdentifier: '#${BUILD_NUMBER}' }, caps, config)
const service = new BrowserstackLauncher({ buildIdentifier: '#${BUILD_NUMBER}' } as BrowserstackConfig & Options.Testrunner, caps, config)
const capabilities = { chromeBrowser: { capabilities: { 'bstack:options': { buildName: 'browserstack wdio build', buildIdentifier: 'test ${BUILD_NUMBER}' } } } }
vi.spyOn(service, '_getLocalBuildNumber').mockImplementation(() => { return '1' })
@ -431,7 +432,7 @@ describe('onPrepare', () => {
it('should add "browserstack.buildIdentifier" property in capabilities if no "bstack:options" and buildIdentifier present in capabilities', async () => {
const capabilities = [{ build: 'browserstack wdio build', 'browserstack.buildIdentifier': '#${BUILD_NUMBER}' }]
const service = new BrowserstackLauncher(options, capabilities, {
const service = new BrowserstackLauncher(options as BrowserstackConfig & Options.Testrunner, capabilities as Capabilities.RemoteCapability, {
user: 'foobaruser',
key: '12345',
capabilities: []
@ -439,16 +440,19 @@ describe('onPrepare', () => {
vi.spyOn(service, '_getLocalBuildNumber').mockImplementation(() => { return '1' })
await service.onPrepare(config, capabilities)
expect(capabilities).toEqual([
{ build: 'browserstack wdio build', 'browserstack.buildIdentifier': '#1', 'browserstack.local': true, 'browserstack.wdioService': bstackServiceVersion }
])
expect(capabilities).toEqual([{
build: 'browserstack wdio build',
'browserstack.buildIdentifier': '#1',
'browserstack.local': true,
'browserstack.wdioService': pkg.version
}])
})
it('should add the "browserstack.buildIdentifier" property in capabilities if no "bstack:options" and passing buildIdentifier in service options', async () => {
const capabilities = [{ build: 'browserstack wdio build' }]
const service = new BrowserstackLauncher({
buildIdentifier: '#${BUILD_NUMBER}',
}, capabilities, {
} as BrowserstackConfig & Options.Testrunner, capabilities as Capabilities.RemoteCapability, {
user: 'foobaruser',
key: '12345',
capabilities: []
@ -456,16 +460,18 @@ describe('onPrepare', () => {
vi.spyOn(service, '_getLocalBuildNumber').mockImplementation(() => { return '1' })
await service.onPrepare(config, capabilities)
expect(capabilities).toEqual([
{ build: 'browserstack wdio build', 'browserstack.buildIdentifier': '#1', 'browserstack.wdioService': bstackServiceVersion }
])
expect(capabilities).toEqual([{
build: 'browserstack wdio build',
'browserstack.buildIdentifier': '#1',
'browserstack.wdioService': pkg.version
}])
})
it('should not add "browserstack.buildIdentifier" property in capabilities if no "bstack:options" and "build" not present', async () => {
const capabilities = [{}]
const service = new BrowserstackLauncher({
buildIdentifier: '#${BUILD_NUMBER}',
}, capabilities, {
} as BrowserstackConfig & Options.Testrunner, capabilities as Capabilities.RemoteCapability, {
user: 'foobaruser',
key: '12345',
capabilities: []
@ -473,16 +479,14 @@ describe('onPrepare', () => {
vi.spyOn(service, '_getLocalBuildNumber').mockImplementation(() => { return '1' })
await service.onPrepare(config, capabilities)
expect(capabilities).toEqual([
{ 'browserstack.wdioService': bstackServiceVersion }
])
expect(capabilities).toEqual([{ 'browserstack.wdioService': pkg.version }])
})
it('should delete "browserstack.buildIdentifier" property from capabilities if no "bstack:options" and "build" not present', async () => {
const capabilities = [{ 'browserstack.buildIdentifier': '#${BUILD_NUMBER}' }]
const service = new BrowserstackLauncher({
buildIdentifier: '#${BUILD_NUMBER}',
}, capabilities, {
} as BrowserstackConfig & Options.Testrunner, capabilities as Capabilities.RemoteCapability, {
user: 'foobaruser',
key: '12345',
capabilities: []
@ -490,9 +494,7 @@ describe('onPrepare', () => {
vi.spyOn(service, '_getLocalBuildNumber').mockImplementation(() => { return '1' })
await service.onPrepare(config, capabilities)
expect(capabilities).toEqual([
{ 'browserstack.wdioService': bstackServiceVersion }
])
expect(capabilities).toEqual([{ 'browserstack.wdioService': pkg.version }])
})
it('should reject if local.start throws an error', () => {
@ -526,7 +528,7 @@ describe('onPrepare', () => {
describe('onComplete', () => {
it('should do nothing if browserstack local is turned on, but not running', () => {
const service = new BrowserstackLauncher({} as any, [{}] as any, {} as any)
service.browserstackLocal = new Browserstack.Local()
service.browserstackLocal = new Local()
const BrowserstackLocalIsRunningSpy = vi.spyOn(service.browserstackLocal, 'isRunning')
BrowserstackLocalIsRunningSpy.mockImplementationOnce(() => false)
service.onComplete()
@ -535,7 +537,7 @@ describe('onComplete', () => {
it('should kill the process if forcedStop is true', async () => {
const service = new BrowserstackLauncher({ forcedStop: true } as any, [{}] as any, {} as any)
service.browserstackLocal = new Browserstack.Local()
service.browserstackLocal = new Local()
service.browserstackLocal.pid = 102
const killSpy = vi.spyOn(process, 'kill').mockImplementationOnce((pid) => pid as any)
@ -546,7 +548,7 @@ describe('onComplete', () => {
it('should reject with an error, if local.stop throws an error', () => {
const service = new BrowserstackLauncher({} as any, [{ browserName: '' }] as any, {} as any)
service.browserstackLocal = new Browserstack.Local()
service.browserstackLocal = new Local()
const BrowserstackLocalStopSpy = vi.spyOn(service.browserstackLocal, 'stop')
BrowserstackLocalStopSpy.mockImplementationOnce((cb) => cb(error))
return expect(service.onComplete()).rejects.toThrow(error)
@ -555,7 +557,7 @@ describe('onComplete', () => {
it('should properly resolve if everything works', () => {
const service = new BrowserstackLauncher({} as any, [{}] as any, {} as any)
service.browserstackLocal = new Browserstack.Local()
service.browserstackLocal = new Local()
return expect(service.onComplete()).resolves.toBe(undefined)
.then(() => expect(service.browserstackLocal?.stop).toHaveBeenCalled())
})
@ -575,8 +577,8 @@ describe('constructor', () => {
new BrowserstackLauncher(options as any, caps, config)
expect(caps).toEqual([
{ 'browserstack.wdioService': bstackServiceVersion },
{ 'browserstack.wdioService': bstackServiceVersion }
{ 'browserstack.wdioService': pkg.version },
{ 'browserstack.wdioService': pkg.version }
])
})
@ -585,8 +587,8 @@ describe('constructor', () => {
new BrowserstackLauncher(options as any, caps, config)
expect(caps).toEqual([
{ 'bstack:options': { wdioService: bstackServiceVersion } },
{ 'bstack:options': { wdioService: bstackServiceVersion } }
{ 'bstack:options': { wdioService: pkg.version } },
{ 'bstack:options': { wdioService: pkg.version } }
])
})
@ -595,30 +597,30 @@ describe('constructor', () => {
new BrowserstackLauncher(options as any, caps, config)
expect(caps).toEqual([
{ 'bstack:options': { wdioService: bstackServiceVersion }, 'moz:firefoxOptions': {} },
{ 'bstack:options': { wdioService: bstackServiceVersion }, 'goog:chromeOptions': {} }
{ 'bstack:options': { wdioService: pkg.version }, 'moz:firefoxOptions': {} },
{ 'bstack:options': { wdioService: pkg.version }, 'goog:chromeOptions': {} }
])
})
it('should add the "wdioService" property to object of capabilities inside "bstack:options" if "bstack:options" present', async () => {
const caps: any = { browserA: { capabilities: { 'goog:chromeOptions': {}, 'bstack:options': {} } } }
new BrowserstackLauncher(options, caps, config)
new BrowserstackLauncher(options as BrowserstackConfig & Options.Testrunner, caps, config)
expect(caps).toEqual({ 'browserA': { 'capabilities': { 'bstack:options': { 'wdioService': bstackServiceVersion }, 'goog:chromeOptions': {} } } })
expect(caps).toEqual({ 'browserA': { 'capabilities': { 'bstack:options': { 'wdioService': pkg.version }, 'goog:chromeOptions': {} } } })
})
it('should add the "wdioService" property to object of capabilities inside "bstack:options" if any extension cap present', async () => {
const caps: any = { browserA: { capabilities: { 'goog:chromeOptions': {} } } }
new BrowserstackLauncher(options, caps, config)
new BrowserstackLauncher(options as BrowserstackConfig & Options.Testrunner, caps, config)
expect(caps).toEqual({ 'browserA': { 'capabilities': { 'bstack:options': { 'wdioService': bstackServiceVersion }, 'goog:chromeOptions': {} } } })
expect(caps).toEqual({ 'browserA': { 'capabilities': { 'bstack:options': { 'wdioService': pkg.version }, 'goog:chromeOptions': {} } } })
})
it('should add the "wdioService" property to object of capabilities inside "bstack:options" if any extension cap not present', async () => {
const caps: any = { browserA: { capabilities: {} } }
new BrowserstackLauncher(options, caps, config)
new BrowserstackLauncher(options as BrowserstackConfig & Options.Testrunner, caps, config)
expect(caps).toEqual({ 'browserA': { 'capabilities': { 'browserstack.wdioService': bstackServiceVersion } } })
expect(caps).toEqual({ 'browserA': { 'capabilities': { 'browserstack.wdioService': pkg.version } } })
})
it('update spec list if it is a rerun', async () => {
@ -626,7 +628,7 @@ describe('constructor', () => {
process.env.BROWSERSTACK_RERUN_TESTS = 'demo1.test.js,demo2.test.js'
const caps: any = [{ 'bstack:options': {} }, { 'bstack:options': {} }]
new BrowserstackLauncher(options, caps, config)
new BrowserstackLauncher(options as BrowserstackConfig & Options.Testrunner, caps, config)
expect(config.specs).toEqual(['demo1.test.js', 'demo2.test.js'])
@ -699,19 +701,19 @@ describe('_updateCaps', () => {
it('should update buildidentifier in caps object if bstack:options is present', () => {
const options: BrowserstackConfig = { browserstackLocal: true }
const caps = { chromeBrowser: { capabilities: { 'goog:chromeOptions': {}, 'bstack:options': { buildIdentifier: '123' } } } }
const service = new BrowserstackLauncher(options, caps, config)
const service = new BrowserstackLauncher(options as BrowserstackConfig & Options.Testrunner, caps, config)
service._updateCaps(caps, 'buildIdentifier', '#1')
expect(caps.chromeBrowser.capabilities['bstack:options']).toEqual({ 'wdioService': bstackServiceVersion, buildIdentifier: '#1' })
expect(caps.chromeBrowser.capabilities['bstack:options']).toEqual({ 'wdioService': pkg.version, buildIdentifier: '#1' })
})
it('should update buildidentifier in caps object if bstack:options is not present', () => {
const options: BrowserstackConfig = { browserstackLocal: true }
const caps = { chromeBrowser: { capabilities: {} } }
const service = new BrowserstackLauncher(options, caps, config)
const service = new BrowserstackLauncher(options as BrowserstackConfig & Options.Testrunner, caps, config)
service._updateCaps(caps, 'buildIdentifier', '#1')
expect(caps.chromeBrowser.capabilities).toEqual({ 'browserstack.wdioService': bstackServiceVersion, 'browserstack.buildIdentifier': '#1' })
expect(caps.chromeBrowser.capabilities).toEqual({ 'browserstack.wdioService': pkg.version, 'browserstack.buildIdentifier': '#1' })
})
it('should delete buildidentifier in caps array if value not passed in _updateCaps', () => {
@ -720,7 +722,7 @@ describe('_updateCaps', () => {
const service = new BrowserstackLauncher(options as any, caps as any, config)
service._updateCaps(caps as any, 'buildIdentifier')
expect(caps[0]['bstack:options']).toEqual({ 'wdioService': bstackServiceVersion })
expect(caps[0]['bstack:options']).toEqual({ 'wdioService': pkg.version })
})
it('should delete buildidentifier in caps object if value not passed in _updateCaps', () => {
@ -729,34 +731,34 @@ describe('_updateCaps', () => {
const service = new BrowserstackLauncher(options as any, caps as any, config)
service._updateCaps(caps as any, 'buildIdentifier')
expect(caps.chromeBrowser.capabilities['bstack:options']).toEqual({ 'wdioService': bstackServiceVersion })
expect(caps.chromeBrowser.capabilities['bstack:options']).toEqual({ 'wdioService': pkg.version })
})
it('should delete buildidentifier in caps object if value not passed in _updateCaps', () => {
const options: BrowserstackConfig = { browserstackLocal: true }
const caps = { chromeBrowser: { capabilities: { 'browserstack.buildIdentifier': '#1' } } }
const service = new BrowserstackLauncher(options, caps, config)
const service = new BrowserstackLauncher(options as BrowserstackConfig & Options.Testrunner, caps, config)
service._updateCaps(caps, 'buildIdentifier')
expect(caps.chromeBrowser.capabilities).toEqual({ 'browserstack.wdioService': bstackServiceVersion })
expect(caps.chromeBrowser.capabilities).toEqual({ 'browserstack.wdioService': pkg.version })
})
it('should delete buildidentifier in caps object if value not passed in _updateCaps', () => {
const options: BrowserstackConfig = { browserstackLocal: true }
const caps = [{ 'browserstack.buildIdentifier': '#1' }]
const service = new BrowserstackLauncher(options, caps, config)
const caps: any = [{ 'browserstack.buildIdentifier': '#1' }]
const service = new BrowserstackLauncher(options as BrowserstackConfig & Options.Testrunner, caps, config)
service._updateCaps(caps, 'buildIdentifier')
expect(caps[0]).toEqual({ 'browserstack.wdioService': bstackServiceVersion })
expect(caps[0]).toEqual({ 'browserstack.wdioService': pkg.version })
})
it('should update localIdentifier in caps object if extension cap is present', () => {
const options: BrowserstackConfig = { browserstackLocal: true, opts: { localIdentifier: 'wdio1' } }
const caps: any = { chromeBrowser: { capabilities: { 'goog:chromeOptions': {} } } }
const service = new BrowserstackLauncher(options, caps, config)
const service = new BrowserstackLauncher(options as BrowserstackConfig & Options.Testrunner, caps, config)
service._updateCaps(caps, 'localIdentifier', 'wdio1')
expect(caps.chromeBrowser.capabilities['bstack:options']).toEqual({ 'wdioService': bstackServiceVersion, localIdentifier: 'wdio1' })
expect(caps.chromeBrowser.capabilities['bstack:options']).toEqual({ 'wdioService': pkg.version, localIdentifier: 'wdio1' })
})
})
@ -804,21 +806,21 @@ describe('_validateApp', () => {
it('should throw error if appConfig is invalid format', async() => {
const options: BrowserstackConfig = { app: {} }
const service = new BrowserstackLauncher(options, caps, config)
const service = new BrowserstackLauncher(options as BrowserstackConfig & Options.Testrunner, caps, config)
try {
await service._validateApp(options.app)
await service._validateApp(options.app as any)
} catch (e: any){
expect(e.message).toEqual('[Invalid format] app should be string or an object')
}
})
it('should throw error if appConfig is invalid format', async() => {
const options: BrowserstackConfig = { app: { key1: '2' } }
const service = new BrowserstackLauncher(options, caps, config)
const options: BrowserstackConfig = { app: { key1: '2' } } as any
const service = new BrowserstackLauncher(options as BrowserstackConfig & Options.Testrunner, caps, config)
try {
await service._validateApp(options.app)
await service._validateApp(options.app as any)
} catch (e: any){
expect(e.message).toEqual(`[Invalid app property] supported properties are {id<string>, path<string>, custom_id<string>, shareable_id<string>}.
For more details please visit https://www.browserstack.com/docs/app-automate/appium/set-up-tests/specify-app ')`)
@ -834,30 +836,24 @@ describe('_uploadApp', () => {
key: '12345',
capabilities: []
}
vi.mock('got')
got.post = vi.fn().mockReturnValue({
json: () => Promise.resolve({ app_url: 'bs://<app-id>' })
})
it('should upload the app and return app_url', async() => {
got.post = vi.fn().mockReturnValue({
json: () => Promise.resolve({ app_url: 'bs://<app-id>' })
})
const service = new BrowserstackLauncher(options as any, caps, config)
const res = await service._uploadApp(options.app as any)
expect(res).toEqual({ app_url: 'bs://<app-id>' })
})
it('throw SevereServiceError if upload fails', async() => {
vi.mock('got', () => ({
post: vi.fn().mockImplementation(() => new Promise(() => {}))
}))
got.post = vi.fn().mockReturnValue({
json: () => Promise.reject({})
})
const service = new BrowserstackLauncher(options, caps, config)
const service = new BrowserstackLauncher(options as BrowserstackConfig & Options.Testrunner, caps, config)
try {
await service._uploadApp(options.app)
await service._uploadApp(options.app as any)
} catch (e: any) {
expect(got.post).toHaveBeenCalled()
expect(e.name).toEqual('SevereServiceError')
@ -949,7 +945,7 @@ describe('_handleBuildIdentifier', () => {
}]
const updatedcaps: any = [{
'bstack:options': {
wdioService: bstackServiceVersion
wdioService: pkg.version
}
}]
const service = new BrowserstackLauncher(options as any, caps, config)
@ -967,7 +963,7 @@ describe('_handleBuildIdentifier', () => {
}]
const updatedcaps: any = [{
'bstack:options': {
wdioService: bstackServiceVersion
wdioService: pkg.version
}
}]
const service = new BrowserstackLauncher(options as any, caps, config)
@ -979,7 +975,7 @@ describe('_handleBuildIdentifier', () => {
it('should not evaluate buildIdentifier if buildIdentifier is not present in the caps', async() => {
const caps: any = [{}]
const updatedcaps: any = [{ 'browserstack.wdioService': bstackServiceVersion }]
const updatedcaps: any = [{ 'browserstack.wdioService': pkg.version }]
const service = new BrowserstackLauncher(options as any, caps, config)
service._handleBuildIdentifier(caps)

View file

@ -103,7 +103,7 @@ describe('FileSystemPathService', () => {
const svc = new FileSystemPathService()
const error = await svc.loadFile(INDEX_PATH + '.tar.gz.non-existent')
.catch((err) => err) as Error
expect(error.message).toContain('Failed to load')
expect(error.message).toContain('Cannot find module')
})
})
})

View file

@ -4,25 +4,25 @@ import { TestStats } from '@wdio/reporter'
import WDIOJunitReporter from '../src/index.js'
import mochaRunnerLog from './__fixtures__/mocha-runner.json' assert { type: 'json' }
import cucumberRunnerLog from './__fixtures__/cucumber-runner.json' assert { type: 'json' }
import cucumberRunnerBrowserstackIosLog from './__fixtures__/cucumber-runner-browserstack-ios.json' assert { type: 'json' }
import cucumberRunnerBrowserstackAndroidLog from './__fixtures__/cucumber-runner-browserstack-android.json' assert { type: 'json' }
import cucumberRunnerBrowserstackAndroidLogMissingOS from './__fixtures__/cucumber-runner-browserstack-android-missing-os.json' assert { type: 'json' }
import suitesLog from './__fixtures__/suites.json' assert { type: 'json' }
import suitesWithNoErrorObjectLog from './__fixtures__/suites-with-no-error-object.json' assert { type: 'json' }
import featuresLog from './__fixtures__/cucumber-features.json' assert { type: 'json' }
import featuresWithFailingThenSkipStepLog from './__fixtures__/cucumber-features-with-failed-then-skipped-steps.json' assert { type: 'json' }
import featuresWithPendingStepLog from './__fixtures__/cucumber-features-with-pending-step.json' assert { type: 'json' }
import featuresWithErrorStepAndNoErrorObjectLog from './__fixtures__/cucumber-features-with-error-step-and-no-error-object.json' assert { type: 'json' }
import nestedSuites from './__fixtures__/nested-suites.json' assert { type: 'json' }
import unorderedFeatureAndScenarioWithError from './__fixtures__/cucumber-features-with-error-step-and-no-error-object-unordered.json' assert { type: 'json' }
import suitesWithFailedBeforeEachHookLog from './__fixtures__/suites-with-failed-before-each-hook.json' assert { type: 'json' }
import suitesWithFailedAfterEachHookLog from './__fixtures__/suites-with-failed-after-each-hook.json' assert { type: 'json' }
import suitesHooksLog from './__fixtures__/suites-hooks.json' assert { type: 'json' }
import suiteTestRetry from './__fixtures__/suite-test-retry.json' assert { type: 'json' }
import suitesMultipleLog from './__fixtures__/suites-multiple.json' assert { type: 'json' }
import suitesErrorLog from './__fixtures__/suites-error.json' assert { type: 'json' }
const mochaRunnerLog = (await vi.importActual('./__fixtures__/mocha-runner.json') as any).default
const cucumberRunnerLog = (await vi.importActual('./__fixtures__/cucumber-runner.json') as any).default
const cucumberRunnerBrowserstackIosLog = (await vi.importActual('./__fixtures__/cucumber-runner-browserstack-ios.json') as any).default
const cucumberRunnerBrowserstackAndroidLog = (await vi.importActual('./__fixtures__/cucumber-runner-browserstack-android.json') as any).default
const cucumberRunnerBrowserstackAndroidLogMissingOS = (await vi.importActual('./__fixtures__/cucumber-runner-browserstack-android-missing-os.json') as any).default
const suitesLog = (await vi.importActual('./__fixtures__/suites.json') as any).default
const suitesWithNoErrorObjectLog = (await vi.importActual('./__fixtures__/suites-with-no-error-object.json') as any).default
const featuresLog = (await vi.importActual('./__fixtures__/cucumber-features.json') as any).default
const featuresWithFailingThenSkipStepLog = (await vi.importActual('./__fixtures__/cucumber-features-with-failed-then-skipped-steps.json') as any).default
const featuresWithPendingStepLog = (await vi.importActual('./__fixtures__/cucumber-features-with-pending-step.json') as any).default
const featuresWithErrorStepAndNoErrorObjectLog = (await vi.importActual('./__fixtures__/cucumber-features-with-error-step-and-no-error-object.json') as any).default
const nestedSuites = (await vi.importActual('./__fixtures__/nested-suites.json') as any).default
const unorderedFeatureAndScenarioWithError = (await vi.importActual('./__fixtures__/cucumber-features-with-error-step-and-no-error-object-unordered.json') as any).default
const suitesWithFailedBeforeEachHookLog = (await vi.importActual('./__fixtures__/suites-with-failed-before-each-hook.json') as any).default
const suitesWithFailedAfterEachHookLog = (await vi.importActual('./__fixtures__/suites-with-failed-after-each-hook.json') as any).default
const suitesHooksLog = (await vi.importActual('./__fixtures__/suites-hooks.json') as any).default
const suiteTestRetry = (await vi.importActual('./__fixtures__/suite-test-retry.json') as any).default
const suitesMultipleLog = (await vi.importActual('./__fixtures__/suites-multiple.json') as any).default
const suitesErrorLog = (await vi.importActual('./__fixtures__/suites-error.json') as any).default
vi.mock('@wdio/reporter', () => import(path.join(process.cwd(), '__mocks__', '@wdio/reporter')))
@ -119,7 +119,7 @@ describe('wdio-junit-reporter', () => {
reporter = new WDIOJunitReporter({ stdout: true })
reporter.suites = { ...featuresLog } as any
const runner = { ...cucumberRunnerLog }
runner.specs = runner.specs.map(s => `file://${s}`)
runner.specs = runner.specs.map((s: string) => `file://${s}`)
// verifies the content of the report but omits format by stripping all whitespace and new lines
expect(reporter['_buildJunitXml'](runner as any).replace(/\s/g, '')).toMatchSnapshot()
@ -129,7 +129,7 @@ describe('wdio-junit-reporter', () => {
reporter = new WDIOJunitReporter({ stdout: true, addFileAttribute: true })
reporter.suites = { ...featuresLog } as any
const runner = { ...cucumberRunnerLog }
runner.specs = runner.specs.map(s => `file://${s}`)
runner.specs = runner.specs.map((s: string) => `file://${s}`)
// verifies the content of the report but omits format by stripping all whitespace and new lines
expect(reporter['_buildJunitXml'](runner as any).replace(/\s/g, '')).toMatchSnapshot()

View file

@ -35,7 +35,7 @@ export const config = {
grep: 'SKIPPED_GREP',
invertGrep: true,
require: ['ts-node/esm'],
expectationResultHandler: (actual, assertion) => {
expectationResultHandler: (_, assertion) => {
expectationResults += `expect(${typeof assertion.expected}).${assertion.matcherName}(${typeof assertion.actual})\n`
return fs.writeFile(path.resolve(__dirname, 'expectationResults.log'), expectationResults)
}

View file

@ -0,0 +1,19 @@
import path from 'node:path'
import url from 'node:url'
import fs from 'node:fs/promises'
import { config as baseConfig } from './config.js'
const __dirname = path.dirname(url.fileURLToPath(import.meta.url))
let expectationResults = ''
export const config = {
...baseConfig,
jasmineOpts: {
...baseConfig.jasmineOpts,
expectationResultHandler: (_, assertion) => {
expectationResults += `expect(${typeof assertion.expected}).${assertion.matcherName}(${typeof assertion.actual})\n`
return fs.writeFile(path.resolve(__dirname, 'expectationResults.log'), expectationResults)
}
}
}

View file

@ -8,6 +8,7 @@ import { SevereServiceError } from '../packages/node_modules/webdriverio/build/i
const __dirname = path.dirname(url.fileURLToPath(import.meta.url))
const baseConfig = path.resolve(__dirname, 'helpers', 'config.js')
const jasmineConfig = path.resolve(__dirname, 'helpers', 'configJasmine.js')
import launch from './helpers/launch.js'
import {
@ -111,7 +112,7 @@ const cjsTestrunner = async () => {
const jasmineTestrunner = async () => {
const logFile = path.resolve(__dirname, 'helpers', 'expectationResults.log')
await fs.rm(logFile, { force: true })
const { skippedSpecs } = await launch('jasmineTestrunner', baseConfig, {
const { skippedSpecs } = await launch('jasmineTestrunner', jasmineConfig, {
autoCompileOpts: { autoCompile: false },
specs: [
path.resolve(__dirname, 'jasmine', 'test.js'),

View file

@ -14,6 +14,7 @@ export default defineConfig({
],
coverage: {
enabled: true,
provider: 'v8',
exclude: [
'**/build/**',
'**/cjs/*.js',
@ -29,7 +30,7 @@ export default defineConfig({
statements: 92
},
globalSetup: [
'scripts/test/globalSetup.ts'
// 'scripts/test/globalSetup.ts'
]
}
})