🏡 index : quine-global/webdriverio.git

import FirefoxProfile from 'firefox-profile'

import { describe, expect, test, vi } from 'vitest'
import Launcher from '../src/launcher.js'

vi.mock('firefox-profile')

describe('Firefox profile service', () => {
    describe('onPrepare', () => {
        test('should return when no firefoxProfile set in the config', async () => {
            const options = {}
            const capabilities = [{}]

            const service = new Launcher(options)
            await service.onPrepare({} as never, capabilities)

            expect(capabilities).toEqual([{}])
        })

        test('should set preferences with no extensions - modern', async () => {
            const options = {
                'browser.startup.homepage': 'https://webdriver.io',
            }
            const capabilities: WebdriverIO.Capabilities[] = [{
                browserName : 'firefox',
            }]

            const service = new Launcher(options)
            await service.onPrepare({} as never, capabilities)

            expect(service['_profile']!.setPreference).toHaveBeenCalledTimes(1)
            expect(service['_profile']!.setPreference).toHaveBeenCalledWith('browser.startup.homepage', 'https://webdriver.io')
            expect(service['_profile']!.updatePreferences).toHaveBeenCalled()
            expect(service['_profile']!.addExtensions).not.toHaveBeenCalled()

            expect(capabilities[0]['moz:firefoxOptions']).toEqual({ profile : 'foobar' })
        })

        test('should amend firefox capabilities', async () => {
            const options = {
                'browser.startup.homepage': 'https://webdriver.io',
            }
            const capabilities: WebdriverIO.Capabilities[] = [{
                browserName : 'firefox',
                'moz:firefoxOptions': {
                    args: ['-headless']
                }
            }]

            const service = new Launcher(options)
            await service.onPrepare({} as never, capabilities)

            expect(service['_profile']!.setPreference).toHaveBeenCalledTimes(1)
            expect(service['_profile']!.setPreference).toHaveBeenCalledWith('browser.startup.homepage', 'https://webdriver.io')
            expect(service['_profile']!.updatePreferences).toHaveBeenCalled()
            expect(service['_profile']!.addExtensions).not.toHaveBeenCalled()

            expect(capabilities[0]['moz:firefoxOptions']).toEqual({ args: ['-headless'], profile : 'foobar' })
        })

        test('should set preferences with extensions', async () => {
            const options = { extensions : ['/foo/bar.xpi'] }
            const capabilities: WebdriverIO.Capabilities[] = [{ browserName : 'firefox' }]

            const service = new Launcher(options)
            await service.onPrepare({} as never, capabilities)

            expect(capabilities[0]['moz:firefoxOptions']).toEqual({ profile : 'foobar' })
            expect(vi.mocked(service['_profile']!.addExtensions).mock.calls[0][0]).toBe(options.extensions)
        })

        test('should not set capabilities when not firefox browser', async () => {
            const options = {
                'browser.startup.homepage': 'https://webdriver.io',
            }
            const capabilities: WebdriverIO.Capabilities[] = [{
                browserName : 'firefox',
            }, {
                browserName : 'chrome'
            }]

            const service = new Launcher(options)
            await service.onPrepare({} as never, capabilities)

            expect(capabilities[0]['moz:firefoxOptions']).toEqual({ profile : 'foobar' })
            expect(capabilities[1]).not.toHaveProperty('moz:firefoxOptions')
        })

        test('should set capabilities when in multiremote', async () => {
            const options = {
                'browser.startup.homepage': 'https://webdriver.io',
            }
            // @ts-expect-error
            const capabilities: WebdriverIO.MultiRemoteCapabilities = {
                firefox : {
                    capabilities : {
                        browserName : 'firefox',
                    }
                }
            }

            const service = new Launcher(options)
            await service.onPrepare({} as never, capabilities)

            expect(capabilities.firefox.capabilities['moz:firefoxOptions']).toEqual({ profile : 'foobar' })
        })

        test('should set capabilities when in parallel multiremote', async () => {
            const options = {
                'browser.startup.homepage': 'https://webdriver.io',
            }

            const capabilities: WebdriverIO.MultiremoteConfig['capabilities'] = [{
                firefox0 : {
                    capabilities : {
                        browserName : 'firefox',
                    }
                }
            }, {
                firefox1 : {
                    capabilities : {
                        browserName : 'firefox',
                    }
                }
            }]

            const service = new Launcher(options)
            await service.onPrepare({} as never, capabilities)

            expect(capabilities[0].firefox0.capabilities['moz:firefoxOptions']).toEqual({ profile : 'foobar' })
            expect(capabilities[1].firefox1.capabilities['moz:firefoxOptions']).toEqual({ profile : 'foobar' })
        })

        test('should not set capabilities when an object and not firefox', async () => {
            const options = {
                'browser.startup.homepage': 'https://webdriver.io',
            }
            // @ts-expect-error
            const capabilities: WebdriverIO.MultiRemoteCapabilities = {
                foo : {
                    capabilities: {
                        browserName : 'chrome',
                    }
                }
            }

            const service = new Launcher(options)
            await service.onPrepare({} as never, capabilities)
            expect(capabilities.foo.capabilities).not.toHaveProperty('moz:firefoxOptions')
        })

        test('should set proxy', async () => {
            const options = {
                extensions : ['/foo/bar.xpi'],
                'browser.startup.homepage': 'https://webdriver.io',
                proxy : { proxyType: 'direct' as const }
            }
            const capabilities: WebdriverIO.Capabilities[] = [{
                browserName : 'firefox',
            }]

            const service = new Launcher(options)
            await service.onPrepare({} as never, capabilities)

            expect(service['_profile']!.setProxy).toHaveBeenCalledTimes(1)
            expect(service['_profile']!.setProxy).toHaveBeenCalledWith(options.proxy)

            expect(service['_profile']!.setPreference).toHaveBeenCalledTimes(1)
            expect(service['_profile']!.setPreference).toHaveBeenCalledWith('browser.startup.homepage', 'https://webdriver.io')
            expect(service['_profile']!.updatePreferences).toHaveBeenCalled()
        })

        test('should load from directory if profileDirectory is set', async () => {
            const options = {
                profileDirectory: '/tmp/firefox-profile'
            }
            const capabilities: WebdriverIO.Capabilities[] = [{
                browserName : 'firefox',
            }]

            const service = new Launcher(options)
            await service.onPrepare({} as never, capabilities)

            expect(FirefoxProfile.copy).toHaveBeenCalledWith(options.profileDirectory, expect.any(Function))
        })

        test('should not continue if profile could not be created', async () => {
            const options = {
                profileDirectory: '/tmp/firefox-profile'
            }
            const capabilities: WebdriverIO.Capabilities[] = [{
                browserName : 'firefox',
            }]

            vi.mocked(FirefoxProfile.copy).mockImplementationOnce(((_: string, cb: Function) => cb()) as any)
            const service = new Launcher(options)
            await service.onPrepare({} as never, capabilities)
            // no assertion needed as we return early and no failure due to
            // undefined profile is checked
        })
    })

    test('should return when no firefoxProfile set in the config', async () => {
        const service = new Launcher({})
        service['_setPreferences']()
        service['_buildExtension']([])
    })
})