import path from 'node:path'
import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'
import logger from '@wdio/logger'
import PercyHandler from '../src/Percy/Percy-Handler.js'
import PercyCaptureMap from '../src/Percy/PercyCaptureMap.js'
import * as PercySDK from '../src/Percy/PercySDK.js'
import type { Capabilities } from '@wdio/types'
import * as PercyLogger from '../src/Percy/PercyLogger.js'
import type { BeforeCommandArgs, AfterCommandArgs } from '@wdio/reporter'
const log = logger('test')
let percyHandler: PercyHandler
let browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser
let caps: Capabilities.RemoteCapability
vi.mock('got')
vi.mock('@wdio/logger', () => import(path.join(process.cwd(), '__mocks__', '@wdio/logger')))
vi.useFakeTimers().setSystemTime(new Date('2020-01-01'))
vi.mock('uuid', () => ({ v4: () => '123456789' }))
const PercyLoggerSpy = vi.spyOn(PercyLogger.PercyLogger, 'logToFile')
PercyLoggerSpy.mockImplementation(() => {})
beforeEach(() => {
vi.mocked(log.info).mockClear()
vi.mocked(fetch).mockClear()
vi.mocked(fetch).mockResolvedValue(Response.json({ value: {
automation_session: {
browser_url: 'https://www.browserstack.com/automate/builds/1/sessions/2'
}
} }))
browser = {
sessionId: 'session123',
config: {},
capabilities: {
device: '',
os: 'OS X',
os_version: 'Catalina',
browserName: 'chrome'
},
instances: ['browserA', 'browserB'],
isMultiremote: false,
browserA: {
sessionId: 'session456',
capabilities: { 'bstack:options': {
device: '',
os: 'Windows',
osVersion: 10,
browserName: 'chrome'
} }
},
getInstance: vi.fn().mockImplementation((browserName: string) => browser[browserName]),
browserB: {},
execute: vi.fn(),
executeAsync: async () => { 'done' },
getUrl: () => { return 'https://www.google.com/'},
on: vi.fn(),
} as unknown as WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser
caps = {
browserName: 'chrome',
'bstack:options': {
os: 'OS X',
osVersion: 'Catalina',
accessibility: true
} } as Capabilities.RemoteCapability
percyHandler = new PercyHandler('manual', browser, caps, false, 'framework')
})
it('should initialize correctly', () => {
percyHandler = new PercyHandler('manual', browser, caps, false, 'framework')
expect(percyHandler['_isAppAutomate']).toEqual(false)
expect(percyHandler['_capabilities']).toEqual(caps)
expect(percyHandler['_framework']).toEqual('framework')
expect(percyHandler['_percyScreenshotCounter']).toEqual(0)
})
describe('_setSessionName', () => {
beforeEach(() => {
percyHandler = new PercyHandler('manual', browser, caps, false, 'framework')
})
it('sets sessionName property', async () => {
percyHandler._setSessionName('1234')
expect(percyHandler['_sessionName']).toEqual('1234')
})
})
describe('teardown', () => {
beforeEach(() => {
percyHandler = new PercyHandler('manual', browser, caps, false, 'framework')
})
it('resolves promise if _percyScreenshotCounter is 0', async () => {
percyHandler.teardown().then(() => {
expect(percyHandler['_percyScreenshotCounter']).toEqual(0)
}).catch((err: any) => {
expect(percyHandler['_percyScreenshotCounter']).not.equal(0)
})
})
})
describe('afterScenario', () => {
let percyAutoCaptureSpy: any
let percyHandler: PercyHandler
beforeEach(() => {
percyHandler = new PercyHandler('manual', browser, caps, false, 'framework')
percyHandler.before()
percyAutoCaptureSpy = vi.spyOn(PercyHandler.prototype, 'percyAutoCapture')
})
it('should not call percyAutoCapture', async () => {
await percyHandler.afterScenario()
expect(percyAutoCaptureSpy).not.toBeCalled()
})
it('should call percyAutoCapture', async () => {
percyHandler['_percyAutoCaptureMode'] = 'testcase'
await percyHandler.afterScenario()
expect(percyAutoCaptureSpy).toBeCalledTimes(1)
})
afterEach(() => {
percyAutoCaptureSpy.mockClear()
})
})
describe('afterTest', () => {
let percyAutoCaptureSpy: any
let percyHandler: PercyHandler
beforeEach(() => {
percyHandler = new PercyHandler('manual', browser, caps, false, 'framework')
percyHandler.before()
percyAutoCaptureSpy = vi.spyOn(PercyHandler.prototype, 'percyAutoCapture')
})
it('should not call percyAutoCapture', async () => {
await percyHandler.afterTest()
expect(percyAutoCaptureSpy).not.toBeCalled()
})
it('should call percyAutoCapture', async () => {
percyHandler['_percyAutoCaptureMode'] = 'testcase'
await percyHandler.afterTest()
expect(percyAutoCaptureSpy).toBeCalledTimes(1)
})
afterEach(() => {
percyAutoCaptureSpy.mockClear()
})
})
describe('percyAutoCapture', () => {
let percyScreenshotSpy: any
let percyScreenshotAppSpy: any
beforeEach(() => {
percyHandler = new PercyHandler('auto', browser, caps, false, 'framework')
percyHandler._setSessionName('1234')
percyHandler.before()
percyScreenshotSpy = vi.spyOn(PercySDK, 'screenshot').mockImplementation(() => Promise.resolve())
percyScreenshotAppSpy = vi.spyOn(PercySDK, 'screenshotApp').mockImplementation(() => Promise.resolve())
})
it('does not call Percy Selenium Screenshot', async () => {
await percyHandler.percyAutoCapture(null, null)
expect(percyScreenshotSpy).not.toBeCalled()
})
it('calls Percy Selenium Screenshot', async () => {
await percyHandler.percyAutoCapture('keys', null)
expect(percyScreenshotSpy).toBeCalledTimes(1)
})
it('calls Percy Appium Screenshot', async () => {
percyHandler = new PercyHandler('auto', browser, caps, true, 'framework')
await percyHandler.percyAutoCapture('keys', null)
expect(percyScreenshotAppSpy).toBeCalledTimes(1)
})
afterEach(() => {
percyScreenshotSpy.mockClear()
percyScreenshotAppSpy.mockClear()
})
})
describe('browserCommand', () => {
let percyAutoCaptureSpy: any
let percyHandler: PercyHandler
beforeEach(() => {
percyHandler = new PercyHandler('auto', browser, caps, false, 'framework')
percyHandler.before()
percyAutoCaptureSpy = vi.spyOn(PercyHandler.prototype, 'deferCapture')
})
it('should not call percyAutoCapture if no browser endpoint', async () => {
const args = {}
await percyHandler.browserAfterCommand(args as BeforeCommandArgs & AfterCommandArgs)
expect(percyAutoCaptureSpy).not.toBeCalled()
})
it('should call percyAutoCapture for event type keys', async () => {
const args = {
endpoint: 'actions',
body: {
actions: [{
type: 'key'
}]
}
}
await percyHandler.browserAfterCommand(args as BeforeCommandArgs & AfterCommandArgs)
expect(percyAutoCaptureSpy).toBeCalledTimes(1)
})
it('should call percyAutoCapture for event type click', async () => {
const args = {
endpoint: 'click'
}
await percyHandler.browserAfterCommand(args as BeforeCommandArgs & AfterCommandArgs)
expect(percyAutoCaptureSpy).toBeCalledTimes(1)
})
it('should call percyAutoCapture for event type screenshot', async () => {
const args = {
endpoint: 'screenshot'
}
await percyHandler.browserAfterCommand(args as BeforeCommandArgs & AfterCommandArgs)
expect(percyAutoCaptureSpy).toBeCalledTimes(1)
})
afterEach(() => {
percyAutoCaptureSpy.mockClear()
})
})
describe('percyCaptureMap', () => {
let percyAutoCaptureMapGetNameSpy: any
let percyAutoCaptureMapIncrementSpy: any
let percyHandler: PercyHandler
beforeEach(() => {
percyHandler = new PercyHandler('auto', browser, caps, false, 'framework')
percyHandler.before()
percyAutoCaptureMapGetNameSpy = vi.spyOn(PercyCaptureMap.prototype, 'getName')
percyAutoCaptureMapIncrementSpy = vi.spyOn(PercyCaptureMap.prototype, 'increment')
})
it('should call getName method of PercyCaptureMap', async () => {
await percyHandler.percyAutoCapture('keys', null)
await percyHandler.percyAutoCapture('keys', null)
expect(percyAutoCaptureMapGetNameSpy).toBeCalledTimes(2)
})
it('should call getName method of PercyCaptureMap', async () => {
await percyHandler.percyAutoCapture('click', null)
await percyHandler.percyAutoCapture('click', null)
expect(percyAutoCaptureMapIncrementSpy).toBeCalledTimes(2)
})
afterEach(() => {
percyAutoCaptureMapGetNameSpy.mockClear()
percyAutoCaptureMapIncrementSpy.mockClear()
})
})