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() // @ts-ignore test without paramater 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) })