🏡 index : quine-global/webdriverio.git

import path from 'node:path'
import { expect, test, vi, beforeEach, afterEach } from 'vitest'
import logger from '@wdio/logger'
import type { EventEmitter } from 'node:events'

import JasmineReporter from '../src/reporter.js'

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

let jasmineReporter: JasmineReporter
let runnerReporter: EventEmitter

const PARAMS = {
    cid: '0-2',
    capabilities: { browserName: 'foobar' },
    specs: ['/foo/bar.test.js'],
    jasmineOpts: {}
}

beforeEach(() => {
    runnerReporter = { emit: vi.fn() } as any
    jasmineReporter = new JasmineReporter(runnerReporter, PARAMS)
})

test('suiteStarted', () => {
    jasmineReporter.suiteStarted({ id: '23', description: 'some test suite', fullName: 'foobar' } as any)

    expect(vi.mocked(runnerReporter.emit).mock.calls[0][0]).toBe('suite:start')
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].cid).toBe('0-2')
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].uid).toBe('some test suite23')
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].title).toBe('some test suite')
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].type).toBe('suite')
})

test('specStarted', () => {
    jasmineReporter.suiteStarted({ id: '23', description: 'some test suite', fullName: 'foobar' } as any)
    jasmineReporter.specStarted({ id: '24', description: 'some test spec', fullName: 'foobar' } as any)

    expect(vi.mocked(runnerReporter.emit).mock.calls[1][0]).toBe('test:start')
    expect(vi.mocked(runnerReporter.emit).mock.calls[1][1].cid).toBe('0-2')
    expect(vi.mocked(runnerReporter.emit).mock.calls[1][1].uid).toBe('some test spec24')
    expect(vi.mocked(runnerReporter.emit).mock.calls[1][1].title).toBe('some test spec')
    expect(vi.mocked(runnerReporter.emit).mock.calls[1][1].type).toBe('test')
    expect(jasmineReporter['_parent'][0].tests).toBe(1)
})

test('specStarted without root describe', () => {
    jasmineReporter.specStarted({ id: '24', description: 'some test spec', fullName: 'foobar' } as any)
    expect(jasmineReporter['_parent']).toHaveLength(0)
    expect(log.warn).toBeCalledTimes(1)
})

test('specDone', () => {
    jasmineReporter.suiteStarted({ id: '23', description: 'some test suite', fullName: 'foobar' } as any)
    jasmineReporter.specStarted({ id: '24', description: 'some test spec', fullName: 'foobar' } as any)
    vi.mocked(runnerReporter.emit).mockReset()
    jasmineReporter.specDone({
        id: '24',
        description: 'some test spec',
        failedExpectations: [],
        status: 'passed',
        fullName: 'foobar'
    } as any)

    expect(vi.mocked(runnerReporter.emit).mock.calls[0][0]).toBe('test:pass')
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].cid).toBe('0-2')
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].uid).toBe('some test spec24')
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].pending).toBe(false)
    expect(vi.mocked(runnerReporter.emit).mock.calls[1][0]).toBe('test:end')
    expect(vi.mocked(runnerReporter.emit).mock.calls[1][1].uid).toBe('some test spec24')

    vi.mocked(runnerReporter.emit).mockReset()
    jasmineReporter.specDone({
        id: '25',
        description: 'some failing test spec',
        failedExpectations: [new Error('foobar') as any],
        status: 'failed',
        fullName: 'foobar'
    } as any)
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][0]).toBe('test:fail')
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].cid).toBe('0-2')
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].uid).toBe('some failing test spec25')
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].pending).toBe(false)
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].error.message).toBe('foobar')
    expect(vi.mocked(runnerReporter.emit).mock.calls[1][0]).toBe('test:end')
    expect(vi.mocked(runnerReporter.emit).mock.calls[1][1].uid).toBe('some failing test spec25')

    vi.mocked(runnerReporter.emit).mockReset()
    jasmineReporter.specDone({
        id: '26',
        description: 'some pending test spec',
        failedExpectations: [],
        status: 'pending',
        pendingReason: 'for no reason',
        fullName: 'foobar'
    } as any)
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][0]).toBe('test:pending')
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].cid).toBe('0-2')
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].uid).toBe('some pending test spec26')
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].pending).toBe(true)
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].pendingReason).toBe('for no reason')
    expect(vi.mocked(runnerReporter.emit).mock.calls[1][0]).toBe('test:end')
    expect(vi.mocked(runnerReporter.emit).mock.calls[1][1].uid).toBe('some pending test spec26')

    vi.mocked(runnerReporter.emit).mockReset()
    jasmineReporter.specDone({
        id: '27',
        description: 'some excluded test spec',
        failedExpectations: [],
        status: 'excluded',
        fullName: 'foobar'
    } as any)
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][0]).toBe('test:pending')
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].cid).toBe('0-2')
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].uid).toBe('some excluded test spec27')
    expect(vi.mocked(runnerReporter.emit).mock.calls[0][1].pending).toBe(true)
    expect(vi.mocked(runnerReporter.emit).mock.calls[1][0]).toBe('test:end')
    expect(vi.mocked(runnerReporter.emit).mock.calls[1][1].uid).toBe('some excluded test spec27')
})

test('specDone should pass multiple failed expectations as errors', () => {
    jasmineReporter.suiteStarted({ id: '23', description: 'some test suite', fullName: 'foobar' } as any)
    jasmineReporter.specStarted({ id: '24', description: 'some test spec', fullName: 'foobar' } as any)
    jasmineReporter.specDone({
        id: '24',
        description: 'some test spec',
        failedExpectations: [
            { message: 'I failed' },
            { message: 'I failed too!' }
        ] as any,
        status: 'failed',
        fullName: 'foobar'
    } as any)

    expect(vi.mocked(runnerReporter.emit).mock.calls[2][0]).toBe('test:fail')
    // We still assign the first failedExpectation to 'error' for backwards compatibility
    expect(vi.mocked(runnerReporter.emit).mock.calls[2][1].error.message).toBe('I failed')
    expect(vi.mocked(runnerReporter.emit).mock.calls[2][1].errors.length).toBe(2)
    expect(vi.mocked(runnerReporter.emit).mock.calls[2][1].errors[0].message).toBe('I failed')
    expect(vi.mocked(runnerReporter.emit).mock.calls[2][1].errors[1].message).toBe('I failed too!')
})

test('suiteDone', () => {
    jasmineReporter.suiteStarted({ id: '23', description: 'some test suite', fullName: 'foobar' } as any)
    jasmineReporter.specStarted({ id: '24', description: 'some test spec', fullName: 'foobar' } as any)
    jasmineReporter.suiteDone({ id: '23', description: 'some test suite', fullName: 'foobar' } as any)
    expect(vi.mocked(runnerReporter.emit).mock.calls[2][0]).toBe('suite:end')

    /**
     * check run time errors in suites
     */
    jasmineReporter.suiteStarted({ id: '25', description: 'some error prone suite', fullName: 'foobar' } as any)
    jasmineReporter.suiteDone({
        id: '25',
        description: 'some error prone suite',
        failedExpectations: [new Error('foobar') as any],
        fullName: 'foobar'
    } as any)
    expect(vi.mocked(runnerReporter.emit).mock.calls[3][0]).toBe('suite:start')
    expect(vi.mocked(runnerReporter.emit).mock.calls[4][0]).toBe('test:start')
    expect(vi.mocked(runnerReporter.emit).mock.calls[4][1].title).toBe('<unknown test>')
    expect(vi.mocked(runnerReporter.emit).mock.calls[5][0]).toBe('test:fail')
    expect(vi.mocked(runnerReporter.emit).mock.calls[5][1].error.message).toBe('foobar')
    expect(vi.mocked(runnerReporter.emit).mock.calls[6][0]).toBe('test:end')
    expect(vi.mocked(runnerReporter.emit).mock.calls[7][0]).toBe('suite:end')
})

test('getFailedCount', () => {
    jasmineReporter.suiteStarted({ id: '23', description: 'some test suite', fullName: 'foobar' } as any)
    jasmineReporter.specStarted({ id: '24', description: 'some test spec', fullName: 'foobar' } as any)
    jasmineReporter.specDone({
        id: '24',
        description: 'some test spec',
        failedExpectations: [new Error('foobar') as any],
        status: 'failed',
        fullName: 'foobar'
    } as any)
    jasmineReporter.suiteDone({ id: '23', description: 'some test suite', fullName: 'foobar' } as any)
    expect(jasmineReporter.getFailedCount()).toBe(1)
})

test('do not clean stack option', () => {
    const error = new Error('foobar')
    error.stack += '\n\tat foobar (/foo/bar/node_modules/package/test.js)'
    const error2 = new Error('foobar2')
    error2.stack += '\n\tat foobar (/foo/bar/node_modules/package/test.js)'
    const event = { id: '24', description: 'some test spec', failedExpectations: [error as any], status: 'failed', fullName: 'foobar' }
    const event2 = { id: '24', description: 'some test spec', failedExpectations: [error2 as any], status: 'failed', fullName: 'foobar' }
    const dirtyRunnerReporter: EventEmitter = { emit: vi.fn() } as any
    const dirtyJasmineReporter = new JasmineReporter(dirtyRunnerReporter, Object.assign({ cleanStack: false }, PARAMS))
    jasmineReporter.specDone(event as any)
    dirtyJasmineReporter.specDone(event2 as any)
    expect(
        vi.mocked(dirtyRunnerReporter.emit).mock.calls[0][1].error.stack.split('\n').length
    ).toBeGreaterThan(
        vi.mocked(runnerReporter.emit).mock.calls[0][1].error.stack.split('\n').length
    )
})

test('cleanStack should return if no stack is given', () => {
    const error = { message: 'foobar' }
    expect(jasmineReporter.cleanStack(error as any)).toEqual(error)
})

afterEach(() => {
    vi.mocked(runnerReporter.emit).mockClear()
})