import path from 'node:path' import { describe, it, expect, vi, afterEach } from 'vitest' import logger from '@wdio/logger' import type { Capabilities } from '@wdio/types' import TestingBotLauncher from '../src/launcher.js' import type { TestingbotOptions } from '../src/types.js' vi.mock('testingbot-tunnel-launcher') vi.mock('@wdio/logger', () => import(path.join(process.cwd(), '__mocks__', '@wdio/logger'))) const log = logger('') describe('wdio-testingbot-service', () => { const execute = vi.fn() afterEach(() => { execute.mockReset() }) it('onPrepare: tbTunnel is undefined', async () => { const options = { tbTunnel: undefined } as any const tbLauncher = new TestingBotLauncher(options) const caps = {} as any await tbLauncher.onPrepare({} as any, caps) expect(tbLauncher.tbTunnelOpts).toBeUndefined() expect(tbLauncher.tunnel).toBeUndefined() expect(options.protocol).toBeUndefined() expect(options.hostname).toBeUndefined() expect(options.port).toBeUndefined() expect(options.path).toBeUndefined() }) it('onPrepare', async () => { const options: TestingbotOptions = { tbTunnel: true, tbTunnelOpts: { tunnelIdentifier: 'some options', apiKey: 'user', apiSecret: 'key', } } const config: any = { user: 'user', key: 'key' } const caps = [{}] as any const tbLauncher = new TestingBotLauncher(options) await tbLauncher.onPrepare(config, caps) expect(tbLauncher.tbTunnelOpts).toMatchObject({ apiKey: 'user', apiSecret: 'key', tunnelIdentifier: 'some options' }) await new Promise((resolve) => setTimeout(resolve, 100)) expect(vi.mocked(log.info).mock.calls[0][0]) .toContain('TestingBot tunnel successfully started after') }) it('should merge tunnelIdentifier in tb:options', async () => { const options: TestingbotOptions = { tbTunnel: true, tbTunnelOpts: { apiKey: 'user', apiSecret: 'key', tunnelIdentifier: 'my-tunnel' } } const config: any = { user: 'user', key: 'key' } const caps = [{ 'tb:options': { build: 'unit-test', } }] as any const tbLauncher = new TestingBotLauncher(options) await tbLauncher.onPrepare(config, caps) expect(caps).toEqual([{ 'tb:options': { 'tunnel-identifier': 'my-tunnel', build: 'unit-test', } }]) }) it('should merge tunnelIdentifier in tb:options in multiremote', async () => { const options: TestingbotOptions = { tbTunnel: true, tbTunnelOpts: { apiKey: 'user', apiSecret: 'key', tunnelIdentifier: 'my-tunnel' } } const config: any = { user: 'user', key: 'key' } const caps: Capabilities.RequestedMultiremoteCapabilities = { browserA: { capabilities: { 'tb:options': { build: 'unit-test', } } } as any, browserB: { capabilities: { 'tb:options': { build: 'other-unit-test', } } } as any } const tbLauncher = new TestingBotLauncher(options) await tbLauncher.onPrepare(config, caps as any) expect(caps).toEqual({ browserA: { capabilities: { 'tb:options': { 'tunnel-identifier': 'my-tunnel', build: 'unit-test', } } }, browserB: { capabilities: { 'tb:options': { 'tunnel-identifier': 'my-tunnel', build: 'other-unit-test', } } } }) }) it('should merge tunnelIdentifier in tb:options in parallel multiremote', async () => { const options: TestingbotOptions = { tbTunnel: true, tbTunnelOpts: { apiKey: 'user', apiSecret: 'key', tunnelIdentifier: 'my-tunnel' } } const config: any = { user: 'user', key: 'key' } const caps: Capabilities.RequestedMultiremoteCapabilities[] = [{ browserA: { capabilities: { 'tb:options': { build: 'unit-test', } } } as any, browserB: { capabilities: { 'tb:options': { build: 'other-unit-test', } } } as any }, { browserC: { capabilities: { 'tb:options': { build: 'unit-test', } } } as any, browserD: { capabilities: { 'tb:options': { build: 'other-unit-test', } } } as any }] const tbLauncher = new TestingBotLauncher(options) await tbLauncher.onPrepare(config, caps as any) expect(caps).toEqual([{ browserA: { capabilities: { 'tb:options': { 'tunnel-identifier': 'my-tunnel', build: 'unit-test', } } }, browserB: { capabilities: { 'tb:options': { 'tunnel-identifier': 'my-tunnel', build: 'other-unit-test', } } } }, { browserC: { capabilities: { 'tb:options': { 'tunnel-identifier': 'my-tunnel', build: 'unit-test', } } }, browserD: { capabilities: { 'tb:options': { 'tunnel-identifier': 'my-tunnel', build: 'other-unit-test', } } } }]) }) it('should add tunnelIdentifier in tb:options', async () => { const options: TestingbotOptions = { tbTunnel: true, tbTunnelOpts: { apiKey: 'user', apiSecret: 'key', } } const config: any = { user: 'user', key: 'key' } const caps = [{ 'tb:options': { build: 'unit-test', } }] as any const tbLauncher = new TestingBotLauncher(options) await tbLauncher.onPrepare(config, caps) expect(Object.keys(caps[0]['tb:options'])).toContain('tunnel-identifier') expect(Object.keys(caps[0]['tb:options'])).toContain('build') }) it('should add tunnelIdentifier in tb:options using multiremote', async () => { const options: TestingbotOptions = { tbTunnel: true, tbTunnelOpts: { apiKey: 'user', apiSecret: 'key', } } const config: any = { user: 'user', key: 'key' } const caps: Capabilities.RequestedMultiremoteCapabilities = { browserA: { capabilities: {} }, browserB: { capabilities: { 'tb:options': { build: 'other-unit-test', } } } } const tbLauncher = new TestingBotLauncher(options) await tbLauncher.onPrepare(config, caps as any) expect(Object.keys((caps.browserA.capabilities as WebdriverIO.Capabilities)['tb:options'] as any)) .toContain('tunnel-identifier') expect(Object.keys((caps.browserB.capabilities as WebdriverIO.Capabilities)['tb:options'] as any)) .toContain('build') }) it('onComplete', () => { const tbLauncher = new TestingBotLauncher({}) tbLauncher.tunnel = { close: (resolve: any) => resolve('tunnel closed') } return expect(tbLauncher.onComplete()).resolves.toEqual('tunnel closed') }) it('onComplete: no tunnel', () => { const tbLauncher = new TestingBotLauncher({}) tbLauncher.tunnel = undefined expect(tbLauncher.onComplete()).toBeUndefined() }) })