🏡 index : quine-global/webdriverio.git

import { describe, it, expect, afterEach, beforeAll, vi } from 'vitest'
import type { CommandArgs } from '@wdio/type'
import process from 'node:process'
import { Status } from 'allure-js-commons'
import CompoundError from '../src/compoundError.js'
import {
    getTestStatus,
    isEmpty,
    isEachTypeHooks,
    getErrorFromFailedTest,
    isAllTypeHooks,
    getLinkByTemplate,
    findLast,
    isScreenshotCommand,
    getSuiteLabels,
    isBeforeEachTypeHook,
} from '../src/utils.js'
import { suiteStart } from './__fixtures__/suite.js'
import { linkPlaceholder } from '../src/constants.js'

describe('utils', () => {
    let processEmit: any
    beforeAll(() => {
        processEmit = process.emit.bind(process)
        process.emit = vi.fn() as any
    })

    afterEach(() => {
        process.emit = processEmit
    })

    describe('isScreenshotCommand', () => {
        it('isScreenshotCommand', () => {
            expect(isScreenshotCommand({ endpoint: '/session/id/screenshot' } as CommandArgs)).toEqual(true)
            expect(isScreenshotCommand({ endpoint: '/wdu/hub/session/id/screenshot' } as CommandArgs)).toEqual(true)
            expect(isScreenshotCommand({ endpoint: '/session/id/click' } as CommandArgs)).toEqual(false)
            expect(isScreenshotCommand({ command: 'takeScreenshot' } as CommandArgs)).toEqual(true)
            expect(isScreenshotCommand({ command: 'elementClick' } as CommandArgs)).toEqual(false)
            expect(isScreenshotCommand({ endpoint: '/session/id/element/id/screenshot' } as CommandArgs)).toEqual(true)
        })
    })

    describe('getTestStatus', () => {
        it('return  status for jasmine', () => {
            const config: any = { framework: 'jasmine' }
            expect(getTestStatus({} as any, config)).toEqual(Status.FAILED)
        })

        it('broken for test with no error', () => {
            const config: any = { framework: 'mocha' }
            expect(getTestStatus({} as any, config)).toEqual(Status.BROKEN)
        })

        it('failed for AssertionError', () => {
            const config: any = { framework: 'mocha' }
            const test = { error: { name: 'Error', message: 'AssertionError' } }
            expect(getTestStatus(test as any, config)).toEqual(Status.FAILED)
        })

        it('failed for AssertionError stacktrace', () => {
            const config: any = { framework: 'mocha' }
            const test = { error: { stack: 'AssertionError' } }
            expect(getTestStatus(test as any, config)).toEqual(Status.FAILED)
        })

        it('broken for not AssertionError', () => {
            const config: any = { framework: 'mocha' }
            const test = { error: { name: 'MyError' } }
            expect(getTestStatus(test as any, config)).toEqual(Status.BROKEN)
        })

        it('broken for error without stacktrace', () => {
            const config: any = { framework: 'mocha' }
            const test = { error: {} }
            expect(getTestStatus(test as any, config)).toEqual(Status.BROKEN)
        })

        it('failed status for not AssertionError stacktrace', () => {
            const config: any = { framework: 'mocha' }
            const test = { error: { stack: 'MyError stack trace' } }
            expect(getTestStatus(test as any, config)).toEqual(Status.BROKEN)
        })
    })

    it('isMochaEachHooks filter hook by title', () => {
        expect(isEachTypeHooks('"before all" hook')).toEqual(false)
        expect(isEachTypeHooks('"after all" hook')).toEqual(false)
        expect(isEachTypeHooks('"before each" hook')).toEqual(true)
        expect(isEachTypeHooks('"after each" hook')).toEqual(true)
    })

    it('isMochaBeforeEachHook filter hook by title', () => {
        expect(isBeforeEachTypeHook('"before all" hook')).toEqual(false)
        expect(isBeforeEachTypeHook('"after all" hook')).toEqual(false)
        expect(isBeforeEachTypeHook('"before each" hook')).toEqual(true)
        expect(isBeforeEachTypeHook('"after each" hook')).toEqual(false)
    })

    describe('isEmpty', () => {
        it('should filter empty objects', () => {
            expect(isEmpty({})).toEqual(true)
            expect(isEmpty([])).toEqual(true)
            expect(isEmpty(undefined)).toEqual(true)
            expect(isEmpty(null)).toEqual(true)
            expect(isEmpty('')).toEqual(true)
        })
    })

    describe('isMochaHooks', () => {
        it('should filter hook by title', () => {
            expect(isEachTypeHooks('"before all" hook')).toEqual(false)
            expect(isEachTypeHooks('"after all" hook')).toEqual(false)
            expect(isEachTypeHooks('"before each" hook')).toEqual(true)
            expect(isEachTypeHooks('"after each" hook')).toEqual(true)

            expect(isAllTypeHooks('"before all" hook')).toEqual(true)
            expect(isAllTypeHooks('"after all" hook')).toEqual(true)
            expect(isAllTypeHooks('"before each" hook')).toEqual(false)
            expect(isAllTypeHooks('"after each" hook')).toEqual(false)
        })
    })

    describe('getErrorFromFailedTest', () => {
        it('should handle test with no error object', () => {
            const testStat = {}
            expect(getErrorFromFailedTest(testStat as any)).toBeUndefined()
        })

        // wdio-mocha-framework returns a single 'error', while wdio-jasmine-framework returns an array of 'errors'
        it('should return just the error property when there is no errors property', () => {
            const testStat = {
                error: new Error('Everything is Broken Forever'),
            }
            expect(getErrorFromFailedTest(testStat as any)!.message).toBe(
                'Everything is Broken Forever'
            )
        })

        it('should return a single error when there is an errors array with one error', () => {
            const testStat = {
                errors: [new Error('Everything is Broken Forever')],
                error: new Error('Everything is Broken Forever'),
            }
            expect(getErrorFromFailedTest(testStat as any)!.message).toBe(
                'Everything is Broken Forever'
            )
        })

        it('should return a CompoundError of the errors when there is more than one error', () => {
            const testStat = {
                errors: [
                    new Error('Everything is Broken Forever'),
                    new Error('Additional things are broken'),
                ],
                error: new Error('Everything is Broken Forever'),
            }
            const error = getErrorFromFailedTest(
                testStat as any
            ) as CompoundError
            expect(error instanceof CompoundError).toBe(true)
            expect(error.innerErrors).toEqual(testStat.errors)
        })
    })

    describe('getLinkByTemplate', () => {
        const template = 'https://youtrack.jetbrains.com/issue/{}'
        const id = 'JIRA-42'
        it('should return link with task id', () => {
            const link = getLinkByTemplate(template, id)
            expect(link).toEqual(
                'https://youtrack.jetbrains.com/issue/JIRA-42'
            )
        })

        it('should return id if template is not a string', () => {
            expect(getLinkByTemplate(undefined, id)).toEqual(id)
            expect(getLinkByTemplate({} as any, id)).toEqual(id)
        })

        it('should throw error if template is invalid', () => {
            const template = 'foo'
            expect(() => getLinkByTemplate(template, id)).toThrow(
                `The link template "${template}" must contain ${linkPlaceholder} substring.`
            )
        })
    })

    describe('findLast', () => {
        const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]

        it('should return last matched element', () => {
            expect(findLast(arr, (el) => el % 2 === 0)).toEqual(8)

        })

        it('should return undefind when nothing matched', () => {
            expect(findLast(arr, (el) => el === 10)).toEqual(undefined)
        })
    })

    describe('getSuiteLabels', () => {
        describe('suite stats with tags', () => {
            it('returns allure labels', () => {
                expect(
                    getSuiteLabels({
                        ...suiteStart(),
                        tags: [
                            {
                                name: '@foo=bar',
                            }
                        ]
                    })
                ).toEqual([
                    {
                        name: 'foo',
                        value: 'bar',
                    },
                ])
            })
        })

        describe('suite stats with invalid tags', () => {
            it('returns empty array', () => {
                expect(
                    getSuiteLabels({
                        ...suiteStart(),
                        tags: [
                            {
                                name: 'foo bar',
                            },
                            {
                                name: 'foo,bar',
                            }
                        ]
                    })
                ).toEqual([])
            })
        })

        describe('suite stats without tags', () => {
            it('returns empty array', () => {
                expect(getSuiteLabels({ ...suiteStart(), tags: undefined })).toEqual(
                    []
                )
            })
        })
    })
})