/// import path from 'node:path' import { describe, expect, it, vi, beforeEach, afterEach, beforeAll, afterAll } from 'vitest' import logger from '@wdio/logger' import type { StdLog } from '../src/index.js' import InsightsHandler from '../src/insights-handler.js' import * as utils from '../src/util.js' import * as bstackLogger from '../src/bstackLogger.js' import { TESTOPS_SCREENSHOT_ENV } from '../src/constants.js' const log = logger('test') let insightsHandler: InsightsHandler let browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser vi.mock('fetch') vi.mock('@wdio/logger', () => import(path.join(process.cwd(), '__mocks__', '@wdio/logger'))) vi.useFakeTimers().setSystemTime(new Date('2020-01-01')) vi.mock('uuid', () => ({ v4: () => '123456789' })) const bstackLoggerSpy = vi.spyOn(bstackLogger.BStackLogger, 'logToFile') bstackLoggerSpy.mockImplementation(() => {}) beforeEach(() => { vi.mocked(log.info).mockClear() vi.mocked(fetch).mockClear() vi.mocked(fetch).mockReturnValue(Promise.resolve(Response.json({ automation_session: { browser_url: 'https://www.browserstack.com/automate/builds/1/sessions/2' } }))) browser = { sessionId: 'session123', config: {}, capabilities: { device: '', os: 'OS X', os_version: 'Sierra', browserName: 'chrome' }, instances: ['browserA', 'browserB'], isMultiremote: false, browserA: { sessionId: 'session456', capabilities: { 'bstack:options': { device: '', os: 'Windows', osVersion: 10, browserName: 'chrome' } } }, getInstance: vi.fn().mockImplementation((browserName: string) => browser[browserName]), browserB: {}, execute: vi.fn(), on: vi.fn(), } as unknown as WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser insightsHandler = new InsightsHandler(browser, 'framework') }) it('should initialize correctly', () => { insightsHandler = new InsightsHandler(browser, 'framework') expect(insightsHandler['_tests']).toEqual({}) expect(insightsHandler['_hooks']).toEqual({}) expect(insightsHandler['_commands']).toEqual({}) expect(insightsHandler['_framework']).toEqual('framework') }) describe('before', () => { const isBrowserstackSessionSpy = vi.spyOn(utils, 'isBrowserstackSession') beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'framework') isBrowserstackSessionSpy.mockClear() }) it('calls isBrowserstackSession', () => { insightsHandler.before() expect(isBrowserstackSessionSpy).toBeCalledTimes(1) }) it('isBrowserstackSession returns true', () => { isBrowserstackSessionSpy.mockReturnValue(true) insightsHandler.before() expect(isBrowserstackSessionSpy).toBeCalledTimes(1) }) }) describe('beforeScenario', () => { let insightsHandler: InsightsHandler beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'framework') vi.spyOn(utils, 'getUniqueIdentifierForCucumber').mockReturnValue('test title') insightsHandler['getTestRunDataForCucumber'] = vi.fn() insightsHandler['_tests'] = {} }) it('sendTestRunEventForCucumber called', () => { insightsHandler.beforeScenario({ pickle: { name: 'pickle-name', tags: [] }, gherkinDocument: { uri: '', feature: { name: 'feature-name', description: '' } } } as any) expect(insightsHandler['getTestRunDataForCucumber']).toBeCalledTimes(1) }) }) describe('afterScenario', () => { let insightsHandler: InsightsHandler beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'framework') insightsHandler['getTestRunDataForCucumber'] = vi.fn() insightsHandler['_tests'] = {} }) it('sendTestRunEventForCucumber called', () => { insightsHandler.afterScenario({ pickle: { name: 'pickle-name', tags: [] }, gherkinDocument: { uri: '', feature: { name: 'feature-name', description: '' } } } as any) expect(insightsHandler['getTestRunDataForCucumber']).toBeCalledTimes(1) }) }) describe('beforeStep', () => { let insightsHandler: InsightsHandler beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'framework') vi.spyOn(utils, 'getUniqueIdentifierForCucumber').mockReturnValue('test title') insightsHandler['getHierarchy'] = vi.fn().mockImplementation(() => { return [] }) }) it('update test data', () => { insightsHandler['_tests'] = { 'test title': { uuid: 'uuid', startedAt: '', finishedAt: '', feature: { name: 'name', path: 'path', description: 'description' }, scenario: { name: 'name' } } } insightsHandler.beforeStep({ id: 'step_id', text: 'this is step', keyword: 'Given' } as any, {} as any) expect(insightsHandler['_tests']).toEqual({ 'test title': { uuid: 'uuid', startedAt: '', finishedAt: '', feature: { name: 'name', path: 'path', description: 'description' }, scenario: { name: 'name' }, steps: [{ id: 'step_id', text: 'this is step', keyword: 'Given', started_at: '2020-01-01T00:00:00.000Z' }] } }) }) it('add test data', () => { insightsHandler['_tests'] = { } insightsHandler.beforeStep({ id: 'step_id', text: 'this is step', keyword: 'Given' } as any, {} as any) expect(insightsHandler['_tests']).toEqual({ 'test title': { steps: [{ id: 'step_id', text: 'this is step', keyword: 'Given', started_at: '2020-01-01T00:00:00.000Z' }] } }) }) }) describe('afterStep', () => { let insightsHandler: InsightsHandler beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'framework') vi.spyOn(utils, 'getUniqueIdentifierForCucumber').mockReturnValue('test title') insightsHandler['getHierarchy'] = vi.fn().mockImplementation(() => { return [] }) }) it('update test data - passed case', () => { insightsHandler['_tests'] = { 'test title': { uuid: 'uuid', startedAt: '', finishedAt: '', feature: { name: 'name', path: 'path', description: 'description' }, scenario: { name: 'name' } } } insightsHandler.afterStep({ id: 'step_id', text: 'this is step', keyword: 'Given' } as any, {} as any, { passed: true, duration: 10, error: undefined }) expect(insightsHandler['_tests']).toEqual({ 'test title': { uuid: 'uuid', startedAt: '', finishedAt: '', feature: { name: 'name', path: 'path', description: 'description' }, scenario: { name: 'name' }, steps: [{ id: 'step_id', text: 'this is step', keyword: 'Given', 'result': 'PASSED', duration: 10, failure: undefined, finished_at: '2020-01-01T00:00:00.000Z' }] } }) }) it('update test data - step present', () => { insightsHandler['_tests'] = { 'test title': { uuid: 'uuid', startedAt: '', finishedAt: '', feature: { name: 'name', path: 'path', description: 'description' }, scenario: { name: 'name' }, steps: [{ id: 'step_id' }] } } insightsHandler.afterStep({ id: 'step_id', text: 'this is step', keyword: 'Given' } as any, {} as any, { passed: true, duration: 10, error: undefined }) expect(insightsHandler['_tests']).toEqual({ 'test title': { uuid: 'uuid', startedAt: '', finishedAt: '', feature: { name: 'name', path: 'path', description: 'description' }, scenario: { name: 'name' }, steps: [{ id: 'step_id', result: 'PASSED', duration: 10, failure: undefined, finished_at: '2020-01-01T00:00:00.000Z' }] } }) }) it('add test data', () => { insightsHandler['_tests'] = { } insightsHandler.afterStep({ id: 'step_id', text: 'this is step', keyword: 'Given' } as any, {} as any, { passed: true, duration: 10, error: undefined }) expect(insightsHandler['_tests']).toEqual({ 'test title': { steps: [] } }) }) it('failed case', () => { insightsHandler['_tests'] = { 'test title': { uuid: 'uuid', startedAt: '', finishedAt: '', feature: { name: 'name', path: 'path', description: 'description' }, scenario: { name: 'name' }, steps: [{ id: 'step_id' }] } } insightsHandler.afterStep({ id: 'step_id', text: 'this is step', keyword: 'Given' } as any, {} as any, { passed: false, duration: 10, error: 'this is a error' }) expect(insightsHandler['_tests']).toEqual({ 'test title': { uuid: 'uuid', startedAt: '', finishedAt: '', feature: { name: 'name', path: 'path', description: 'description' }, scenario: { name: 'name' }, steps: [{ id: 'step_id', result: 'FAILED', duration: 10, failure: 'this is a error', finished_at: '2020-01-01T00:00:00.000Z' }] } }) }) }) describe('attachHookData', () => { let insightsHandler: InsightsHandler beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'framework') }) it('add hooks data in test', () => { insightsHandler['_hooks'] = {} insightsHandler['attachHookData']({ currentTest: { title: 'test', parent: { title: 'parent' } } } as any, 'hook_id') expect(insightsHandler['_hooks']).toEqual({ 'parent - test': ['hook_id'] }) }) it('push hooks data in test', () => { insightsHandler['_hooks'] = { 'parent - test': ['hook_id_old'] } insightsHandler['attachHookData']({ currentTest: { title: 'test', parent: { title: 'parent' } } } as any, 'hook_id') expect(insightsHandler['_hooks']).toEqual({ 'parent - test': ['hook_id_old', 'hook_id'] }) }) it('add hook data in test from suite tests', () =>{ insightsHandler['_hooks'] = {} insightsHandler['attachHookData']({ test: { parent: { tests: [{ title: 'test', parent: 'parent' }], } } } as any, 'hook_id_from_test') expect(insightsHandler['_hooks']).toEqual({ 'parent - test': ['hook_id_from_test'] }) }) }) describe('setHooksFromSuite', () => { let insightsHandler: InsightsHandler beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'framework') insightsHandler['_hooks'] = {} }) it('should return false if parent is null', () => { const result = insightsHandler['setHooksFromSuite'](null, 'hook_id') expect(result).toEqual(false) expect(insightsHandler['_hooks']).toEqual({}) }) it('should add hook data from nested suite tests', () => { const result = insightsHandler['setHooksFromSuite']({ suites: [{ tests: [{ title: 'test inside suite', parent: 'parent' }], }], } as any, 'hook_id_from_test') expect(result).toEqual(true) expect(insightsHandler['_hooks']).toEqual({ 'parent - test inside suite': ['hook_id_from_test'] }) }) }) describe('getHierarchy', () => { let insightsHandler beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'framework') }) it('return array of getHierarchy when context present', () => { expect(insightsHandler['getHierarchy']({ ctx: { test: { parent: { title: 'test 2', parent: { title: 'test 1' } } } } } as any)).toEqual(['test 1', 'test 2']) }) it('return empty array when no context present', () => { expect(insightsHandler['getHierarchy']({} as any)).toEqual([]) }) }) describe('getTestRunId', function () { let insightsHandler: InsightsHandler beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'framework') }) it('should return if null context', () => { expect(insightsHandler['getTestRunId'](null)).toEqual(undefined) }) it('return test id from current test', () => { const identifier = 'parent title - some title' insightsHandler['_tests'] = { [identifier]: { uuid: '1234' } } expect(insightsHandler['getTestRunId']({ currentTest: { title: 'some title', parent: 'parent title' } })).toEqual('1234') }) it('return test id from test', () => { const identifier = 'parent title - child title' insightsHandler['_tests'] = { [identifier]: { uuid: 'some_uuid' } } expect(insightsHandler['getTestRunId']({ test: { parent: { tests: [{ title: 'child title', parent: 'parent title' }] }, } })).toEqual('some_uuid') }) }) describe('getTestRunIdFromSuite', function () { let insightsHandler: InsightsHandler beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'framework') }) it('should return null if parent null', function () { expect(insightsHandler['getTestRunIdFromSuite'](null)).toEqual(undefined) }) it('should return test run id from nested suite', () => { insightsHandler['_tests'] = { ['suite title - nested test title']: { uuid: 'some_nested_uuid' } } expect(insightsHandler['getTestRunIdFromSuite']({ tests: [], suites: [{ tests: [{ title: 'nested test title', parent: 'suite title' }] }] })).toEqual('some_nested_uuid') }) }) describe('beforeTest', () => { let insightsHandler: InsightsHandler describe('mocha', () => { beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'mocha') insightsHandler['getRunData'] = vi.fn().mockImplementation(() => { return [] }) vi.spyOn(utils, 'getUniqueIdentifier').mockReturnValue('test title') insightsHandler['_tests'] = {} insightsHandler['_hooks'] = { 'test title': ['hook_id'] } }) it('update test data', async () => { await insightsHandler.beforeTest({ parent: 'parent', title: 'test' } as any) expect(insightsHandler['_tests']).toEqual({ 'test title': { uuid: '123456789', startedAt: '2020-01-01T00:00:00.000Z' } }) expect(insightsHandler['getRunData']).toBeCalledTimes(1) }) }) describe('jasmine', () => { beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'jasmine') insightsHandler['getRunData'] = vi.fn().mockImplementation(() => { return [] }) insightsHandler['_tests'] = {} }) it('shouldn\'t update test data', async () => { await insightsHandler.beforeTest({ parent: 'parent', fullName: 'parent test' } as any) expect(insightsHandler['_tests']).toEqual({}) expect(insightsHandler['getRunData']).toBeCalledTimes(0) }) }) }) describe('beforeHook', () => { let insightsHandler: InsightsHandler describe('mocha', () => { beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'mocha') insightsHandler['getRunData'] = vi.fn().mockImplementation(() => { return [] }) insightsHandler['attachHookData'] = vi.fn().mockImplementation(() => { return [] }) insightsHandler['_tests'] = {} insightsHandler['_framework'] = 'mocha' }) beforeEach(() => { vi.mocked(insightsHandler['getRunData']).mockClear() vi.mocked(insightsHandler['attachHookData']).mockClear() vi.spyOn(utils, 'getUniqueIdentifier').mockReturnValue('parent - test') }) it('update hook data', async () => { await insightsHandler.beforeHook({ parent: 'parent', title: 'test' } as any, {} as any) expect(insightsHandler['_tests']).toEqual({ 'parent - test': { uuid: '123456789', startedAt: '2020-01-01T00:00:00.000Z' } }) expect(insightsHandler['getRunData']).toBeCalledTimes(1) }) }) describe('cucumber', () => { beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'cucumber') insightsHandler['processCucumberHook'] = vi.fn().mockImplementation(() => { return [] }) insightsHandler['_framework'] = 'cucumber' }) it('should call cucumber hook processor', async () => { await insightsHandler.beforeHook(undefined as any, {} as any) expect(insightsHandler['processCucumberHook']).toBeCalledTimes(1) }) }) }) describe('afterHook', () => { let insightsHandler: InsightsHandler describe('mocha', () => { beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'mocha') insightsHandler['getRunData'] = vi.fn().mockImplementation(() => { return [] }) insightsHandler['attachHookData'] = vi.fn().mockImplementation(() => { return [] }) vi.spyOn(utils, 'getUniqueIdentifier').mockReturnValue('test title') vi.spyOn(utils, 'getUniqueIdentifierForCucumber').mockReturnValue('test title') vi.mocked(insightsHandler['getRunData']).mockClear() vi.mocked(insightsHandler['attachHookData']).mockClear() }) it('add hook data', async () => { insightsHandler['_tests'] = {} await insightsHandler.afterHook({ parent: 'parent', title: 'test' } as any, {} as any) expect(insightsHandler['_tests']).toEqual({ 'test title': { finishedAt: '2020-01-01T00:00:00.000Z', } }) expect(insightsHandler['getRunData']).toBeCalledTimes(1) }) it('update hook data', async () => { insightsHandler['_tests'] = { 'test title': {} } await insightsHandler.afterHook({ parent: 'parent', title: 'test' } as any, {} as any) expect(insightsHandler['_tests']).toEqual({ 'test title': { finishedAt: '2020-01-01T00:00:00.000Z', } }) expect(insightsHandler['getRunData']).toBeCalledTimes(1) }) }) describe('cucumber', () => { beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'cucumber') insightsHandler['processCucumberHook'] = vi.fn().mockImplementation(() => { return [] }) }) it('should call cucumber hook processor', async () => { await insightsHandler.afterHook(undefined as any, {} as any) expect(insightsHandler['processCucumberHook']).toBeCalledTimes(1) }) }) }) describe('getIntegrationsObject', () => { let insightsHandler: InsightsHandler let getPlatformVersionSpy beforeAll(() => { getPlatformVersionSpy = vi.spyOn(utils, 'getPlatformVersion').mockImplementation(() => { return 'some version' }) }) beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'framework') insightsHandler['_platformMeta'] = { caps: {}, sessionId: '', browserName: '', browserVersion: '', platformName: '', product: '' } }) it('return hash', () => { const integrationsObject = insightsHandler['getIntegrationsObject']() expect(integrationsObject).toBeInstanceOf(Object) expect(integrationsObject.platform_version).toEqual('some version') }) it('should fetch latest details', () => { const existingSessionId = browser.sessionId const existingOs = browser.capabilities.os browser.sessionId = 'session-new' browser.capabilities.os = 'Windows' const integrationsObject = insightsHandler['getIntegrationsObject']() expect(integrationsObject.session_id).toEqual('session-new') expect(integrationsObject.capabilities.os).toEqual('Windows') browser.sessionId = existingSessionId browser.capabilities.os = existingOs }) afterAll(() => { getPlatformVersionSpy.mockReset() }) }) describe('browserCommand', () => { let insightsHandler: InsightsHandler let uploadEventDataSpy let commandSpy beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'framework') insightsHandler['getIdentifier'] = vi.fn().mockImplementation(() => { return 'test title' }) insightsHandler['_tests'] = { 'test title': { 'uuid': 'uuid' } } insightsHandler['_commands'] = { 's_m_e': {} as any } uploadEventDataSpy = vi.spyOn(insightsHandler['listener'], 'onScreenshot').mockImplementation(() => { return [] as any }) commandSpy = vi.spyOn(utils, 'isScreenshotCommand') }) it('client:beforeCommand', () => { insightsHandler.browserCommand('client:beforeCommand', {} as any, {} as any) expect(uploadEventDataSpy).toBeCalledTimes(0) }) it('client:afterCommand - test not defined', () => { insightsHandler.browserCommand('client:afterCommand', { sessionId: 's', method: 'm', endpoint: 'e', result: {} } as any, undefined) expect(uploadEventDataSpy).toBeCalledTimes(0) }) it('client:afterCommand - screenshot', () => { process.env[TESTOPS_SCREENSHOT_ENV] = 'true' commandSpy.mockImplementation(() => { return true }) insightsHandler.browserCommand('client:afterCommand', { sessionId: 's', method: 'm', endpoint: 'e', result: { value: 'random' } } as any, {} as any) expect(uploadEventDataSpy).toBeCalled() delete process.env[TESTOPS_SCREENSHOT_ENV] }) it('return if test not in _tests', () => { insightsHandler.browserCommand('client:afterCommand', { sessionId: 's', method: 'm', endpoint: 'e', result: { value: 'random' } } as any, {} as any) insightsHandler['_tests'] = { 'test title not there': { 'uuid': 'uuid' } } expect(uploadEventDataSpy).toBeCalledTimes(0) }) it('return if command not in _commands', () => { insightsHandler['_commands'] = { 'command not here': {} } insightsHandler.browserCommand('client:afterCommand', { sessionId: 's', method: 'm', endpoint: 'e', result: { value: 'random' } }, {}) expect(uploadEventDataSpy).toBeCalledTimes(0) }) }) describe('getIdentifier', () => { let insightsHandler: InsightsHandler let getUniqueIdentifierSpy let getUniqueIdentifierForCucumberSpy beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'framework') insightsHandler['_tests'] = { 'test title': { 'uuid': 'uuid' } } getUniqueIdentifierSpy = vi.spyOn(utils, 'getUniqueIdentifier') getUniqueIdentifierForCucumberSpy = vi.spyOn(utils, 'getUniqueIdentifierForCucumber') }) it('non cucumber', () => { insightsHandler['getIdentifier']({ parent: 'parent', title: 'title' } as any) expect(getUniqueIdentifierSpy).toBeCalledTimes(1) }) it('cucumber', () => { insightsHandler['getIdentifier']({ pickle: { uri: 'uri', astNodeIds: ['9', '8'] } } as any) expect(getUniqueIdentifierForCucumberSpy).toBeCalledTimes(1) }) afterEach(() => { getUniqueIdentifierSpy.mockReset() getUniqueIdentifierForCucumberSpy.mockReset() }) }) describe('getCucumberHookType', function () { it('should return BEFORE_ALL', function () { expect(insightsHandler['getCucumberHookType'](undefined)).toEqual('BEFORE_ALL') }) it('should return AFTER_ALL', function () { insightsHandler['_cucumberData'].scenariosStarted = true expect(insightsHandler['getCucumberHookType'](undefined)).toEqual('AFTER_ALL') }) it('should return BEFORE_EACH', function () { expect(insightsHandler['getCucumberHookType']({ id: '1', hookId: '2' })).toEqual('BEFORE_EACH') }) it('should return AFTER_EACH', function () { insightsHandler['_cucumberData'].scenariosStarted = true insightsHandler['_cucumberData'].stepsStarted = true expect(insightsHandler['getCucumberHookType']({ id: '1', hookId: '2' })).toEqual('AFTER_EACH') }) it('should return null if step hook', function () { Object.assign(insightsHandler['_cucumberData'], { scenariosStarted: true, stepsStarted: true, steps: [{}] }) expect(insightsHandler['getCucumberHookType']({ id: '1', hookId: '2' })).toEqual(null) }) }) describe('getCucumberHookUniqueId', function () { let insightsHandler: InsightsHandler beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'framework') }) it('should return hookId for each hooks', function () { expect(insightsHandler['getCucumberHookUniqueId']('BEFORE_EACH', { id: '1', hookId: '2' })).toBe('2') }) it('should return unique id with feature for all hooks', function () { Object.assign(insightsHandler['_cucumberData'], { uri: 'filename', feature: { name: 'some name' } }) const hookUniqueId = 'AFTER_ALL for filename:some name' expect(insightsHandler['getCucumberHookUniqueId']('AFTER_ALL', undefined)).toBe(hookUniqueId) }) }) describe('appendTestItemLog', function () { let insightsHandler: InsightsHandler let sendDataSpy const logObj: StdLog = { timestamp: new Date().toISOString(), level: 'INFO', message: 'some log', kind: 'TEST_LOG', http_response: {} } let testLogObj: StdLog beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'mocha') sendDataSpy = vi.spyOn(insightsHandler['listener'], 'logCreated').mockImplementation(() => { return [] as any }) testLogObj = { ...logObj } }) it('should upload with current test uuid for log', function () { InsightsHandler['currentTest'] = { uuid: 'some_uuid' } insightsHandler['appendTestItemLog'](testLogObj) expect(testLogObj.test_run_uuid).toBe('some_uuid') expect(sendDataSpy).toBeCalledTimes(1) }) it('should upload with current hook uuid for log', function () { insightsHandler['_currentHook'] = { uuid: 'some_uuid' } insightsHandler['appendTestItemLog'](testLogObj) expect(testLogObj.hook_run_uuid).toBe('some_uuid') expect(sendDataSpy).toBeCalledTimes(1) }) it('should not upload log if hook is finished', function () { InsightsHandler['currentTest'] = {} insightsHandler['_currentHook'] = { uuid: 'some_uuid', finished: true } insightsHandler['appendTestItemLog'](testLogObj) expect(testLogObj.hook_run_uuid).toBe(undefined) expect(testLogObj.test_run_uuid).toBe(undefined) expect(sendDataSpy).toBeCalledTimes(0) }) }) describe('processCucumberHook', function () { let insightsHandler: InsightsHandler let sendHookRunEventSpy, cucumberHookTypeSpy, cucumberHookUniqueIdSpy beforeEach(() => { insightsHandler = new InsightsHandler(browser, 'mocha') sendHookRunEventSpy = vi.spyOn(insightsHandler, 'getHookRunDataForCucumber').mockImplementation(() => { return [] as any }) cucumberHookTypeSpy = vi.spyOn(insightsHandler, 'getCucumberHookType') cucumberHookTypeSpy.mockImplementation(() => { return 'hii' }) cucumberHookUniqueIdSpy = vi.spyOn(insightsHandler, 'getCucumberHookUniqueId') }) it('should not update if no hook type', function () { cucumberHookTypeSpy.mockReturnValue(null) insightsHandler['processCucumberHook'](undefined, { event: 'before' }) expect(sendHookRunEventSpy).toBeCalledTimes(0) }) it ('should send data for before event', function () { cucumberHookTypeSpy.mockReturnValue('BEFORE_ALL') InsightsHandler['currentTest'].uuid = 'test_uuid' insightsHandler['processCucumberHook'](undefined, { event: 'before', hookUUID: 'hook_uuid' }) expect(sendHookRunEventSpy).toBeCalledWith(expect.objectContaining({ uuid: 'hook_uuid', testRunId: 'test_uuid', hookType: 'BEFORE_ALL' }), 'HookRunStarted') }) it('should send data for after event', function () { cucumberHookTypeSpy.mockReturnValue('AFTER_ALL') cucumberHookUniqueIdSpy.mockReturnValue('hook_unique_id') const hookObj = { uuid: 'hook_uuid' } const resultObj = { passed: true } insightsHandler['_tests']['hook_unique_id'] = hookObj insightsHandler['processCucumberHook'](undefined, { event: 'after' }, resultObj as any) expect(sendHookRunEventSpy).toBeCalledWith(hookObj, 'HookRunFinished', resultObj) }) }) describe('sendCBTInfo', () => { beforeAll(() => { insightsHandler = new InsightsHandler(browser, 'framework') }) it('should not call cbtSessionCreated', () => { const cbtSessionCreatedSpy = vi.spyOn(insightsHandler['listener'], 'cbtSessionCreated').mockImplementation(() => { return [] as any }) insightsHandler.sendCBTInfo() expect(cbtSessionCreatedSpy).toBeCalledTimes(0) }) it('should call cbtSessionCreated', () => { insightsHandler.currentTestId = 'abc' const cbtSessionCreatedSpy = vi.spyOn(insightsHandler['listener'], 'cbtSessionCreated').mockImplementation(() => { return [] as any }) insightsHandler.sendCBTInfo() expect(cbtSessionCreatedSpy).toBeCalled() }) }) describe('flushCBTDataQueue', () => { beforeAll(() => { insightsHandler = new InsightsHandler(browser, 'framework') }) it('flushCBTDataQueue should not call cbtSessionCreated', () => { insightsHandler.cbtQueue = [{ uuid: 'abc', integrations: {} }] const cbtSessionCreatedSpy = vi.spyOn(insightsHandler['listener'], 'cbtSessionCreated').mockImplementation(() => { return [] as any }) insightsHandler.flushCBTDataQueue() expect(cbtSessionCreatedSpy).toBeCalledTimes(0) }) it('flushCBTDataQueue should call cbtSessionCreated', () => { insightsHandler.currentTestId = 'abc' insightsHandler.cbtQueue = [{ uuid: 'abc', integrations: {} }] const cbtSessionCreatedSpy = vi.spyOn(insightsHandler['listener'], 'cbtSessionCreated').mockImplementation(() => { return [] as any }) insightsHandler.flushCBTDataQueue() expect(cbtSessionCreatedSpy).toBeCalled() }) }) describe('hasTestStepFailures for ignoreHooksStatus feature', () => { beforeAll(() => { insightsHandler = new InsightsHandler(browser, 'cucumber') }) it('should return false when world.pickle is null/undefined', () => { const world = null as any const result = insightsHandler.hasTestStepFailures(world) expect(result).toBe(false) }) it('should return false when world.pickle exists but no test data found', () => { const world = { pickle: { name: 'Test scenario' } } as any const result = insightsHandler.hasTestStepFailures(world) expect(result).toBe(false) }) it('should return false when test data exists but no steps', () => { const world = { pickle: { name: 'Test scenario' } } as any // Mock the uniqueId generation and add test data without steps const uniqueId = 'test-unique-id' vi.doMock('../src/util.js', () => ({ getUniqueIdentifierForCucumber: vi.fn().mockReturnValue(uniqueId) })) insightsHandler['_tests'][uniqueId] = { uuid: 'test-uuid', startedAt: '2020-01-01T00:00:00.000Z' // No steps property } const result = insightsHandler.hasTestStepFailures(world) expect(result).toBe(false) }) it('should return false when test data exists with steps but none failed', () => { const world = { pickle: { name: 'Test scenario' } } as any const uniqueId = 'test-unique-id-pass' vi.doMock('../src/util.js', () => ({ getUniqueIdentifierForCucumber: vi.fn().mockReturnValue(uniqueId) })) insightsHandler['_tests'][uniqueId] = { uuid: 'test-uuid', startedAt: '2020-01-01T00:00:00.000Z', steps: [ { id: 'step1', text: 'Step 1', result: 'PASSED' }, { id: 'step2', text: 'Step 2', result: 'PASSED' }, { id: 'step3', text: 'Step 3', result: 'SKIPPED' } ] } const result = insightsHandler.hasTestStepFailures(world) expect(result).toBe(false) }) it('should return true when test data exists with at least one failed step', () => { const world = { pickle: { name: 'Test scenario' } } as any const uniqueId = 'test-unique-id-fail' const getUniqueIdentifierForCucumberSpy = vi.spyOn(utils, 'getUniqueIdentifierForCucumber') getUniqueIdentifierForCucumberSpy.mockReturnValue(uniqueId) insightsHandler['_tests'][uniqueId] = { uuid: 'test-uuid', startedAt: '2020-01-01T00:00:00.000Z', steps: [ { id: 'step1', text: 'Step 1', result: 'PASSED' }, { id: 'step2', text: 'Step 2', result: 'FAILED' }, { id: 'step3', text: 'Step 3', result: 'PASSED' } ] } const result = insightsHandler.hasTestStepFailures(world) expect(result).toBe(true) getUniqueIdentifierForCucumberSpy.mockRestore() }) it('should return true when multiple steps failed', () => { const world = { pickle: { name: 'Test scenario' } } as any const uniqueId = 'test-unique-id-multi-fail' const getUniqueIdentifierForCucumberSpy = vi.spyOn(utils, 'getUniqueIdentifierForCucumber') getUniqueIdentifierForCucumberSpy.mockReturnValue(uniqueId) insightsHandler['_tests'][uniqueId] = { uuid: 'test-uuid', startedAt: '2020-01-01T00:00:00.000Z', steps: [ { id: 'step1', text: 'Step 1', result: 'FAILED' }, { id: 'step2', text: 'Step 2', result: 'PASSED' }, { id: 'step3', text: 'Step 3', result: 'FAILED' } ] } const result = insightsHandler.hasTestStepFailures(world) expect(result).toBe(true) getUniqueIdentifierForCucumberSpy.mockRestore() }) it('should handle empty steps array', () => { const world = { pickle: { name: 'Test scenario' } } as any const uniqueId = 'test-unique-id-empty' vi.doMock('../src/util.js', () => ({ getUniqueIdentifierForCucumber: vi.fn().mockReturnValue(uniqueId) })) insightsHandler['_tests'][uniqueId] = { uuid: 'test-uuid', startedAt: '2020-01-01T00:00:00.000Z', steps: [] } const result = insightsHandler.hasTestStepFailures(world) expect(result).toBe(false) }) }) describe('hasTestStepFailures and ignoreHooksStatus integration', () => { let testInsightsHandler: InsightsHandler beforeEach(() => { testInsightsHandler = new InsightsHandler(browser, 'cucumber', {}, { testObservabilityOptions: { ignoreHooksStatus: true } }) }) it('should test hasTestStepFailures method directly', () => { // Test that hasTestStepFailures correctly identifies step failures const world = { pickle: { name: 'Test scenario' } } as any const uniqueId = 'test-unique-id-for-step-failures' const getUniqueIdentifierForCucumberSpy = vi.spyOn(utils, 'getUniqueIdentifierForCucumber') getUniqueIdentifierForCucumberSpy.mockReturnValue(uniqueId) // Test: No steps - should return false testInsightsHandler['_tests'][uniqueId] = { uuid: 'test-uuid', startedAt: '2020-01-01T00:00:00.000Z', steps: undefined } expect(testInsightsHandler.hasTestStepFailures(world)).toBe(false) // Test: Empty steps - should return false testInsightsHandler['_tests'][uniqueId].steps = [] expect(testInsightsHandler.hasTestStepFailures(world)).toBe(false) // Test: All steps passed - should return false testInsightsHandler['_tests'][uniqueId].steps = [ { id: 'step1', text: 'Step 1', result: 'PASSED' }, { id: 'step2', text: 'Step 2', result: 'PASSED' } ] expect(testInsightsHandler.hasTestStepFailures(world)).toBe(false) // Test: One step failed - should return true testInsightsHandler['_tests'][uniqueId].steps = [ { id: 'step1', text: 'Step 1', result: 'PASSED' }, { id: 'step2', text: 'Step 2', result: 'FAILED' } ] expect(testInsightsHandler.hasTestStepFailures(world)).toBe(true) // Test: Multiple steps failed - should return true testInsightsHandler['_tests'][uniqueId].steps = [ { id: 'step1', text: 'Step 1', result: 'FAILED' }, { id: 'step2', text: 'Step 2', result: 'FAILED' } ] expect(testInsightsHandler.hasTestStepFailures(world)).toBe(true) // Test: Mixed results with failure - should return true testInsightsHandler['_tests'][uniqueId].steps = [ { id: 'step1', text: 'Step 1', result: 'PASSED' }, { id: 'step2', text: 'Step 2', result: 'FAILED' }, { id: 'step3', text: 'Step 3', result: 'PASSED' } ] expect(testInsightsHandler.hasTestStepFailures(world)).toBe(true) getUniqueIdentifierForCucumberSpy.mockRestore() }) it('should verify ignoreHooksStatus configuration is properly set', () => { // Test that the configuration is correctly passed through expect(testInsightsHandler['_options']?.testObservabilityOptions?.ignoreHooksStatus).toBe(true) const testInsightsHandlerDisabled = new InsightsHandler(browser, 'cucumber', {}, { testObservabilityOptions: { ignoreHooksStatus: false } }) expect(testInsightsHandlerDisabled['_options']?.testObservabilityOptions?.ignoreHooksStatus).toBe(false) const testInsightsHandlerDefault = new InsightsHandler(browser, 'cucumber', {}, {}) expect(testInsightsHandlerDefault['_options']?.testObservabilityOptions?.ignoreHooksStatus).toBeUndefined() }) })