🏡 index : quine-global/webdriverio.git

import { describe, it, expect, vi } from 'vitest'

import { saveScreenshot } from '../../src/node/saveScreenshot.js'
import { getContextManager } from '../../src/session/context.js'

vi.mock('node:fs/promises', () => ({
    default: {
        access: vi.fn().mockResolvedValue(undefined),
        writeFile: vi.fn()
    }
}))

vi.mock('../../src/session/context.js', () => ({
    getContextManager: vi.fn().mockReturnValue({
        getCurrentContext: vi.fn().mockResolvedValue('context'),
        findParentContext: vi.fn().mockResolvedValue({ data: 'bidi screenshot' })
    })
}))

const browserClassic = {
    isBidi: false,
    takeScreenshot: vi.fn().mockResolvedValue(btoa('classic screenshot'))
} as unknown as WebdriverIO.Browser

const browserBidi = {
    isBidi: true,
    $: vi.fn().mockReturnValue({
        getElement: vi.fn().mockResolvedValue({ elementId: 'elementId' })
    }),
    takeElementScreenshot: vi.fn().mockResolvedValue(btoa('bidi iframe screenshot')),
    browsingContextGetTree: vi.fn().mockResolvedValue({ contexts: [] }),
    browsingContextCaptureScreenshot: vi.fn().mockResolvedValue({ data: btoa('bidi screenshot') })
} as unknown as WebdriverIO.Browser

describe('saveScreenshot', () => {
    describe('WebDriver Classic mode', () => {
        it('should save a screenshot of the browser viewport', async () => {
            const screenshot = await saveScreenshot.call(browserClassic, 'screenshot.png')
            expect(screenshot.toString()).toBe('classic screenshot')
        })

        it('should fail if options are provided', async () => {
            await expect(saveScreenshot.call(browserClassic, 'screenshot.png', { fullPage: true })).rejects.toThrow()
        })
    })

    describe('WebDriver Bidi mode', () => {
        it('should save a screenshot of an iframe', async () => {
            const screenshot = await saveScreenshot.call(browserBidi, 'screenshot.png')
            expect(screenshot.toString()).toBe('bidi iframe screenshot')
        })

        it('should save a screenshot of the full page', async () => {
            const contextManager = getContextManager(browserBidi)
            vi.mocked(contextManager.findParentContext).mockReturnValue(undefined)
            const screenshot = await saveScreenshot.call(browserBidi, 'screenshot.png', { fullPage: true })
            expect(screenshot.toString()).toBe('bidi screenshot')
            expect(browserBidi.browsingContextCaptureScreenshot).toHaveBeenCalledWith({
                context: 'context',
                origin: 'document',
                format: {
                    type: 'image/png',
                    quality: undefined
                },
                clip: undefined
            })
        })

        it('should save a screenshot of a specific rectangle', async () => {
            const screenshot = await saveScreenshot.call(browserBidi, 'screenshot.png', { clip: { x: 10, y: 10, width: 100, height: 100 } })
            expect(screenshot.toString()).toBe('bidi screenshot')
            expect(browserBidi.browsingContextCaptureScreenshot).toHaveBeenCalledWith({
                context: 'context',
                origin: 'viewport',
                clip: {
                    type: 'box',
                    x: 10,
                    y: 10,
                    width: 100,
                    height: 100
                },
                format: {
                    type: 'image/png',
                    quality: undefined
                }
            })
        })

        it('should throw an error if the image format is invalid', async () => {
            // @ts-expect-error invalid format
            await expect(saveScreenshot.call(browserBidi, 'screenshot.png', { format: 'invalid' })).rejects.toThrow()
        })

        it('should throw an error if the file extension is invalid', async () => {
            await expect(saveScreenshot.call(browserBidi, 'screenshot.jpeg', { format: 'png' })).rejects.toThrow()
        })

        it('should throw an error if the file extension is invalid for JPEG format', async () => {
            await saveScreenshot.call(browserBidi, 'screenshot.jpeg')
            await expect(saveScreenshot.call(browserBidi, 'screenshot.exe', { format: 'jpeg' })).rejects.toThrow()
        })

        it('should throw an error if the quality is invalid', async () => {
            await expect(saveScreenshot.call(browserBidi, 'screenshot.png', { quality: 101 }))
                .rejects.toThrow(/Invalid quality, use a number between 0 and 100,/)
            await expect(saveScreenshot.call(browserBidi, 'screenshot.png', { quality: 50 }))
                .rejects.toThrow(/Invalid option "quality" for PNG format/)
        })

        it('should throw an error if the clip is invalid', async () => {
            // @ts-expect-error invalid clip
            await expect(saveScreenshot.call(browserBidi, 'screenshot.png', { clip: { x: 'invalid' } })).rejects.toThrow()
        })
    })
})