import path from 'node:path'
import { expect, test, vi, beforeEach } from 'vitest'
import puppeteer from 'puppeteer-core'
import DevToolsService from '../src/index.js'
import { setUnsupportedCommand } from '../src/utils.js'
import logger from '@wdio/logger'
vi.mock('ws')
vi.mock('puppeteer-core')
vi.mock('lighthouse/lighthouse-core/fraggle-rock/gather/session')
vi.mock('@wdio/logger', () => import(path.join(process.cwd(), '__mocks__', '@wdio/logger')))
vi.mock('../src/commands', () => {
class CommandHandlerMock {
cdp = vi.fn()
_initCommand = vi.fn()
_beforeCmd = vi.fn()
_afterCmd = vi.fn()
enablePerformanceAudits = vi.fn()
disablePerformanceAudits = vi.fn()
setThrottlingProfile = vi.fn()
checkPWA = vi.fn()
getCoverageReport = vi.fn()
_logCoverage = vi.fn()
}
return { default: CommandHandlerMock }
})
vi.mock('../src/auditor', () => {
const updateCommandsMock = vi.fn()
return {
default: class {
traceEvents: any
logs: any
updateCommands = updateCommandsMock
constructor (traceEvents: any, logs: any) {
this.traceEvents = traceEvents
this.logs = logs
}
}
}
})
vi.mock('../src/utils', async () => {
let wasCalled = false
return {
findCDPInterface: vi.fn().mockImplementation(() => {
if (!wasCalled) {
wasCalled = true
return 42
}
throw new Error('boom')
}),
setUnsupportedCommand: vi.fn(),
getLighthouseDriver: vi.fn()
}
})
const sessionMock = { send: vi.fn() }
const log = logger('')
let browser: WebdriverIO.Browser
let multiBrowser: WebdriverIO.MultiRemoteBrowser
beforeEach(() => {
browser = {
sessionId: vi.fn(),
getPuppeteer: vi.fn(() => puppeteer.connect({})),
addCommand: vi.fn(),
emit: vi.fn(),
getUrl: vi.fn()
} as any
multiBrowser = {
instances: ['1', '2'],
getInstance: () => {
return {
sessionId: vi.fn(),
getPuppeteer: vi.fn(() => puppeteer.connect({})),
addCommand: vi.fn(),
emit: vi.fn(),
getUrl: vi.fn()
}
},
addCommand: vi.fn(),
} as any
sessionMock.send.mockClear()
vi.mocked(log.error).mockClear()
})
test('if not supported by browser', async () => {
const service = new DevToolsService({})
service['_browser'] = {
sessionId: vi.fn(),
addCommand: vi.fn(),
getPuppeteer: vi.fn(() => Promise.reject(new Error('ups')))
} as any
await service._setupHandler()
expect(setUnsupportedCommand).toBeCalledTimes(1)
expect(vi.mocked(service['_browser']!.addCommand!).mock.calls).toHaveLength(0)
})
test('if supported by browser', async () => {
const service = new DevToolsService({
coverageReporter: {
enable: true
}
})
service['_browser'] = browser
await service._setupHandler()
expect(service['_browser']?.addCommand).toBeCalledWith(
'enablePerformanceAudits', expect.any(Function))
expect(service['_browser']?.addCommand).toBeCalledWith(
'disablePerformanceAudits', expect.any(Function))
expect(service['_browser']?.addCommand).toBeCalledWith(
'checkPWA', expect.any(Function))
})
test('beforeCommand', async () => {
const service = new DevToolsService({})
service['_browser'] = browser
await service._setupHandler()
service.beforeCommand()
expect(service['_command'][0]._beforeCmd).toBeCalledTimes(1)
})
test('afterCommand: switchToWindow', async () => {
const service = new DevToolsService({})
service['_browser'] = browser
await service._setupHandler()
service._setupHandler = vi.fn()
await service.afterCommand('switchToWindow')
expect(service._setupHandler).toBeCalledTimes(1)
expect(service['_command'][0]._afterCmd).toBeCalledTimes(1)
})
test('_enablePerformanceAudits: throws if network or cpu properties have wrong types', () => {
const service = new DevToolsService({})
service['_browser'] = browser
expect(
() => service._enablePerformanceAudits({ networkThrottling: 'super fast 3g' } as any)
).toThrow(/Network throttling profile/)
expect(
() => service._enablePerformanceAudits({ networkThrottling: 'Good 3G', cpuThrottling: '34' } as any)
).toThrow(/CPU throttling rate needs to be typeof number/)
})
test('_enablePerformanceAudits', async () => {
const service = new DevToolsService({})
service['_browser'] = browser
await service._setupHandler()
service._enablePerformanceAudits()
expect(service['_command'][0].enablePerformanceAudits).toBeCalledTimes(1)
})
test('_enablePerformanceAudits for multiremote', async () => {
const service = new DevToolsService({})
service['_browser'] = multiBrowser
await service._setupHandler()
service._enablePerformanceAudits()
expect(service['_command'].length).toBe(2)
expect(service['_command'][0].enablePerformanceAudits).toBeCalledTimes(1)
expect(service['_command'][1].enablePerformanceAudits).toBeCalledTimes(1)
})
test('_disablePerformanceAudits', async () => {
const service = new DevToolsService({})
service['_browser'] = browser
await service._setupHandler()
service._enablePerformanceAudits({
networkThrottling: 'Regular 2G',
cpuThrottling: 42,
cacheEnabled: true,
formFactor: 'mobile'
})
service._disablePerformanceAudits()
expect(service['_command'][0].disablePerformanceAudits).toBeCalledTimes(1)
})
test('_disablePerformanceAudits for multiremote', async () => {
const service = new DevToolsService({})
service['_browser'] = multiBrowser
await service._setupHandler()
service._enablePerformanceAudits({
networkThrottling: 'Regular 2G',
cpuThrottling: 42,
cacheEnabled: true,
formFactor: 'mobile'
})
service._disablePerformanceAudits()
expect(service['_command'][0].disablePerformanceAudits).toBeCalledTimes(1)
expect(service['_command'][1].disablePerformanceAudits).toBeCalledTimes(1)
})
test('_setThrottlingProfile', async () => {
const service = new DevToolsService({})
service['_browser'] = browser
await service._setupHandler()
await service._setThrottlingProfile('Good 3G', 4, true)
expect(service['_command'][0].setThrottlingProfile).toBeCalledTimes(1)
})
test('_setThrottlingProfile for multiremote', async () => {
const service = new DevToolsService({})
service['_browser'] = multiBrowser
await service._setupHandler()
await service._setThrottlingProfile('Good 3G', 4, true)
expect(service['_command'][0].setThrottlingProfile).toBeCalledTimes(1)
expect(service['_command'][1].setThrottlingProfile).toBeCalledTimes(1)
})
test('_checkPWA', async () => {
const service = new DevToolsService({})
service['_browser'] = browser
await service._setupHandler()
await service._checkPWA()
expect(service['_command'][0].checkPWA).toBeCalledTimes(1)
})
test('_checkPWA for multiremote', async () => {
const service = new DevToolsService({})
service['_browser'] = multiBrowser
await service._setupHandler()
await service._checkPWA()
expect(service['_command'][0].checkPWA).toBeCalledTimes(1)
expect(service['_command'][1].checkPWA).toBeCalledTimes(1)
})
test('before hook', async () => {
const service = new DevToolsService({})
service._setupHandler = vi.fn()
service.before({}, [], browser)
expect(service._setupHandler).toBeCalledTimes(1)
})
test('onReload hook', async () => {
const service = new DevToolsService({})
service['_browser'] = browser
service._setupHandler = vi.fn()
;(service['_browser'] as any).puppeteer = 'suppose to be reset after reload' as any
service.onReload()
expect(service._setupHandler).toBeCalledTimes(1)
})