🏡 index : quine-global/webdriverio.git

import path from 'node:path'
import { test, expect, vi, afterEach } from 'vitest'
import type { Capabilities } from '@wdio/types'

import { multiremote } from '../src/index.js'

vi.mock('fetch')
vi.mock('@wdio/logger', () => import(path.join(process.cwd(), '__mocks__', '@wdio/logger')))

const caps = (): Capabilities.MultiRemoteCapabilities => ({
    browserA: {
        logLevel: 'debug',
        capabilities: {
            browserName: 'chrome'
        }
    },
    browserB: {
        logLevel: 'debug',
        port: 4445,
        capabilities: {
            browserName: 'firefox'
        }
    }
})

test('should run command on all instances', async () => {
    const browser = await multiremote(caps())

    expect(browser.getInstance('browserA')).toBeDefined()
    expect(browser.getInstance('browserB')).toBeDefined()

    const result = await browser.execute(() => 'foobar')
    expect(result).toEqual(['foobar', 'foobar'])

    expect((vi.mocked(fetch).mock.calls[0][0] as any).pathname).toBe('/session')
    expect((vi.mocked(fetch).mock.calls[0][1] as any).method).toBe('POST')
    expect((vi.mocked(fetch).mock.calls[1][0] as any).pathname).toBe('/session')
    expect((vi.mocked(fetch).mock.calls[1][1] as any).method).toBe('POST')
    expect((vi.mocked(fetch).mock.calls[2][0] as any).pathname)
        .toBe('/session/foobar-123/execute/sync')
    expect((vi.mocked(fetch).mock.calls[2][1] as any).method).toBe('POST')
    expect((vi.mocked(fetch).mock.calls[3][0] as any).pathname)
        .toBe('/session/foobar-123/execute/sync')
    expect((vi.mocked(fetch).mock.calls[3][1] as any).method).toBe('POST')
})

test('should properly create stub instance', async () => {
    const params = caps()
    Object.values(params).forEach(cap => { cap.automationProtocol = './protocol-stub.js' })
    const browser = await multiremote(params, { automationProtocol: './protocol-stub.js' })
    expect(browser.$).toBeUndefined()
    expect(browser.options).toBeUndefined()
    expect(browser.commandList).toHaveLength(0)
    expect(browser.getInstance('browserA')).toBeDefined()
    expect(browser.getInstance('browserB')).toBeDefined()
    expect(browser.getInstance('browserA').$).toBeUndefined()
    expect(browser.getInstance('browserA').$).toBeUndefined()
})

test('should allow to call on elements', async () => {
    const browser = await multiremote(caps())

    const elem = await browser.$('#foo')
    expect(elem.getInstance('browserA')).toBeDefined()
    expect(elem.getInstance('browserB')).toBeDefined()
    expect(elem.getInstance('browserA').elementId).toBe('some-elem-123')
    expect(elem.getInstance('browserB').elementId).toBe('some-elem-123')

    // @ts-expect-error invalid params
    const result = await elem.getSize()
    expect(result).toEqual([{ width: 50, height: 30 }, { width: 50, height: 30 }])

    expect((vi.mocked(fetch).mock.calls[2][0] as any).pathname)
        .toEqual('/session/foobar-123/element')
    expect((vi.mocked(fetch).mock.calls[3][0] as any).pathname)
        .toEqual('/session/foobar-123/element')
    expect((vi.mocked(fetch).mock.calls[4][0] as any).pathname)
        .toEqual('/session/foobar-123/element/some-elem-123/rect')
    expect((vi.mocked(fetch).mock.calls[5][0] as any).pathname)
        .toEqual('/session/foobar-123/element/some-elem-123/rect')
})

test('should be able to fetch multiple elements', async () => {
    const browser = await multiremote(caps())

    const elems = await browser.$$('#foo')
    expect(elems).toHaveLength(3)

    // @ts-expect-error invalid params
    const size = await elems[0].getSize()
    expect(size).toEqual([{ width: 50, height: 30 }, { width: 50, height: 30 }])
})

test('should be able to add a command to and element in multiremote', async () => {
    const browser = await multiremote(caps())

    browser.addCommand('myCustomElementCommand', async function (this: WebdriverIO.MultiRemoteBrowser) {
        // @ts-expect-error invalid params
        const size = await this.getSize()
        return size.width
    }, true)

    const elem = await browser.$('#foo')

    // @ts-expect-error untyped custom command
    expect(await elem.browserA.myCustomElementCommand()).toBe(50)
    // @ts-expect-error untyped custom command
    expect(await elem.browserB.myCustomElementCommand()).toBe(50)
    // @ts-expect-error untyped custom command
    expect(await elem.myCustomElementCommand()).toEqual([50, 50])
})

test('should be able to overwrite command to and element in multiremote', async () => {
    const browser = await multiremote(caps())

    browser.overwriteCommand('getSize', async function (
        this: WebdriverIO.MultiRemoteBrowser,
        origCmd: any
    ) {
        let size = await origCmd()
        size = { width: size.width / 10, height: size.height / 10 }
        return size
    }, true)

    const elem = await browser.$('#foo')

    // @ts-expect-error invalid params
    const sizes = await elem.getSize()
    const sizeA = await elem.getInstance('browserA').getSize()
    const sizeB = await elem.getInstance('browserB').getSize()
    const result = { width: 5, height: 3 }

    expect(sizes).toEqual([result, result])
    expect(sizeA).toEqual(result)
    expect(sizeB).toEqual(result)
})

afterEach(() => {
    vi.mocked(fetch).mockClear()
})