import path from 'node:path'
import { log } from 'node:console'
import { describe, it, expect, afterEach, beforeEach, beforeAll, afterAll, vi } from 'vitest'
import type { Label, Parameter, Link, Attachment } from 'allure-js-commons'
import { LabelName } from 'allure-js-commons'
import { Status, LinkType, Stage } from 'allure-js-commons'
import { temporaryDirectory } from 'tempy'
import AllureReporter from '../src/reporter.js'
import { TYPE } from '../src/types.js'
* this is not a real package and only used to utilize helper
* methods without having to ignore them for test coverage
*/
import { clean, getResults, mapBy } from './helpers/wdio-allure-helper.js'
import { runnerEnd, runnerStart } from './__fixtures__/runner.js'
import { suiteEnd, suiteStart } from './__fixtures__/suite.js'
import {
testFailed, testPending, testStart, testFailedWithMultipleErrors, testFailedWithMultipleErrorsAndStacksNotContainingMessages,
hookStart, hookFailed,
testFailedWithAssertionErrorFromExpectWebdriverIO, eachHookFailed, eachHookStart
} from './__fixtures__/testState.js'
import {
commandStart, commandEnd, commandEndScreenShot, commandStartScreenShot
} from './__fixtures__/command.js'
import type { AfterCommandArgs, BeforeCommandArgs } from '@wdio/reporter'
vi.mock('@wdio/reporter', () => import(path.join(process.cwd(), '__mocks__', '@wdio/reporter')))
let processOn: any
beforeAll(() => {
processOn = process.on.bind(process)
process.on = vi.fn()
})
afterAll(() => {
process.on = processOn
})
describe('Passing tests', () => {
const outputDir = temporaryDirectory()
let allureResult: Record<string, any>
let allureContainer: Record<string, any>
let allureEnvInfo: Record<string, any>
beforeAll(() => {
const reporter = new AllureReporter({
outputDir,
issueLinkTemplate: 'https://example.org/issues/{}',
tmsLinkTemplate: 'https://example.org/tests/{}',
reportedEnvironmentVars:{
jenkins: '1.2.3',
OS: 'Mocked'
}
})
const step = {
step: {
attachment: {
content: 'baz',
name: 'attachment'
},
status: Status.FAILED,
title: 'foo'
}
}
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.addLabel({ name: 'customLabel', value: 'Label' })
reporter.addStory({ storyName: 'Story' })
reporter.addFeature({ featureName: 'foo' })
reporter.addSeverity({ severity: 'baz' })
reporter.addIssue({ issue: '1' })
reporter.addTestId({ testId: '2' })
reporter.addDescription({ description: 'functions', descriptionType: TYPE.HTML })
reporter.addAttachment({ name: 'My attachment', content: '99thoughtz', type: 'text/plain' })
reporter.addArgument({ name: 'os', value: 'osx' })
reporter.startStep('bar')
reporter.endStep(Status.PASSED)
reporter.addStep(step)
reporter.onTestPass()
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results, containers, environmentInfo } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(containers).toHaveLength(1)
expect(Object.values(environmentInfo)).toHaveLength(2)
allureResult = results[0]
allureContainer = containers[0]
allureEnvInfo = environmentInfo
})
afterAll(() => {
clean(outputDir)
})
it('should report one suite', () => {
expect(allureContainer.name).toEqual('A passing Suite')
})
it('should detect passed test case', () => {
expect(allureResult.name).toEqual('should can do something')
expect(allureResult.status).toEqual(Status.PASSED)
})
it('should detect analytics labels in test case', () => {
const labels = mapBy<Label>(allureResult.labels, 'name')
const languages = labels[LabelName.LANGUAGE]
const frameworks = labels[LabelName.FRAMEWORK]
expect(languages).toHaveLength(1)
expect(languages[0].value).toEqual('javascript')
expect(frameworks).toHaveLength(1)
expect(frameworks[0].value).toEqual('wdio')
})
it('should add browser name as test argument', () => {
const params = mapBy<Parameter>(allureResult.parameters, 'name')
const browsers = params.browser
expect(browsers).toHaveLength(1)
expect(browsers[0].value).toEqual('chrome-68')
})
it('should add label, story, feature, severity, issue, testId, thread and package labels', () => {
const labels = mapBy<Label>(allureResult.labels, 'name')
const customLabels = labels.customLabel
const features = labels[LabelName.FEATURE]
const stories = labels[LabelName.STORY]
const severities = labels[LabelName.SEVERITY]
const threads = labels[LabelName.THREAD]
const packages = labels[LabelName.PACKAGE]
expect(features).toHaveLength(2)
expect(features).toEqual(expect.arrayContaining([
{ name: LabelName.FEATURE, value: 'A passing Suite' },
{ name: LabelName.FEATURE, value: 'foo' }
]))
expect(customLabels).toHaveLength(1)
expect(customLabels[0].value).toEqual('Label')
expect(stories).toHaveLength(1)
expect(stories[0].value).toEqual('Story')
expect(severities).toHaveLength(1)
expect(severities[0].value).toEqual('baz')
expect(threads).toHaveLength(1)
expect(threads[0].value).toEqual(testStart().cid)
expect(packages).toHaveLength(1)
expect(packages[0].value).toEqual('foo.bar.test.js')
})
it('should add issue and tms links', () => {
const links = mapBy<Link>(allureResult.links, 'type')
const issues = links[LinkType.ISSUE]
const tms = links[LinkType.TMS]
expect(issues).toHaveLength(1)
expect(issues[0].url).toEqual('https://example.org/issues/1')
expect(tms).toHaveLength(1)
expect(tms[0].url).toEqual('https://example.org/tests/2')
})
it('should contain environment variables', () => {
expect(allureEnvInfo).toEqual({
jenkins: '1.2.3',
OS: 'Mocked'
})
})
it('should start end custom step', () => {
const customStep = allureResult.steps.find((step: any) => step.name === 'bar')
expect(customStep.status).toEqual(Status.PASSED)
expect(customStep.stage).toEqual(Stage.FINISHED)
})
it('should add custom step', () => {
const customStep = allureResult.steps.find((step: any) => step.name === 'foo')
expect(customStep.status).toEqual(Status.FAILED)
expect(customStep.stage).toEqual(Stage.FINISHED)
expect(customStep.attachments).toHaveLength(1)
})
it('should add attachment', () => {
expect(allureResult.attachments).toHaveLength(1)
expect(allureResult.attachments[0].name).toEqual('My attachment')
})
it('should add additional argument', () => {
const params = mapBy<Parameter>(allureResult.parameters, 'name')
const osParams = params.os
expect(osParams).toHaveLength(1)
expect(osParams[0].value).toEqual('osx')
})
it('should have testCaseId equal to historyId', () => {
expect(allureResult.testCaseId).toEqual(allureResult.historyId)
})
})
describe('Failed tests', () => {
let outputDir: any
beforeEach(() => {
outputDir = temporaryDirectory()
})
afterEach(() => {
clean(outputDir)
})
it('should detect failed test case', () => {
const reporter = new AllureReporter({ outputDir })
const runnerEvent = runnerStart()
delete runnerEvent.capabilities.browserName
delete runnerEvent.capabilities.version
reporter.onRunnerStart(runnerEvent)
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onTestFail(testFailed())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
const browserParameter = results[0].parameters.find(
(param: Parameter) => param.name === 'browser',
)
expect(results[0].name).toEqual('should can do something')
expect(results[0].status).toEqual(Status.FAILED)
expect(results[0].parameters).toHaveLength(1)
expect(results[0].historyId).toEqual('607cb53d8a84b61120bbab44d5f01694')
expect(browserParameter.value).toEqual(testStart().cid)
})
it('should detect failed test case onTestRetry', () => {
const reporter = new AllureReporter({ outputDir })
const runnerEvent = runnerStart()
delete runnerEvent.capabilities.browserName
delete runnerEvent.capabilities.version
reporter.onRunnerStart(runnerEvent)
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onTestRetry(testFailed())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
const browserParameter = results[0].parameters.find((param: Parameter) => param.name === 'browser')
expect(results[0].name).toEqual('should can do something')
expect(results[0].status).toEqual(Status.FAILED)
expect(results[0].parameters).toHaveLength(1)
expect(results[0].historyId).toEqual('607cb53d8a84b61120bbab44d5f01694')
expect(browserParameter.value).toEqual(testStart().cid)
})
it('should detect failed test case onTestRetry', () => {
const reporter = new AllureReporter({ outputDir })
const runnerEvent = runnerStart()
delete runnerEvent.capabilities.browserName
delete runnerEvent.capabilities.version
reporter.onRunnerStart(runnerEvent)
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onTestRetry(testFailed())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
const browserParameter = results[0].parameters.find((param: Parameter) => param.name === 'browser')
expect(results[0].name).toEqual('should can do something')
expect(results[0].status).toEqual(Status.FAILED)
expect(results[0].parameters).toHaveLength(1)
expect(results[0].historyId).toEqual('607cb53d8a84b61120bbab44d5f01694')
expect(browserParameter.value).toEqual(testStart().cid)
})
it('should detect failed test case without start event', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onTestFail(testFailed())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].name).toEqual('should can do something')
expect(results[0].status).toEqual(Status.FAILED)
expect(results[0].historyId).toEqual('2838a547ee87e372fadb8927d9efaad3')
})
it('should detect failed test case with multiple errors', () => {
const reporter = new AllureReporter({ outputDir })
const runnerEvent = runnerStart()
runnerEvent.config.framework = 'jasmine'
delete runnerEvent.capabilities.browserName
delete runnerEvent.capabilities.version
reporter.onRunnerStart(runnerEvent)
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onTestFail(testFailedWithMultipleErrors())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].name).toEqual('should can do something')
expect(results[0].status).toEqual(Status.FAILED)
const { message } = results[0].statusDetails
const lines = message.split('\n')
expect(lines[0]).toBe('CompoundError: One or more errors occurred. ---')
expect(lines[2].trim()).toBe('ReferenceError: All is Dust')
expect(lines[5].trim()).toBe('InternalError: Abandon Hope')
})
it('should detect failed test case with multiple errors whose stacks do not contain error messages', () => {
const reporter = new AllureReporter({ outputDir })
const runnerEvent = runnerStart()
runnerEvent.config.framework = 'jasmine'
delete runnerEvent.capabilities.browserName
delete runnerEvent.capabilities.version
reporter.onRunnerStart(runnerEvent)
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onTestFail(testFailedWithMultipleErrorsAndStacksNotContainingMessages())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].name).toEqual('should can do something')
expect(results[0].status).toEqual(Status.FAILED)
const { message } = results[0].statusDetails
const lines = message.split('\n')
expect(lines[0]).toBe('CompoundError: One or more errors occurred. ---')
expect(lines[2].trim()).toBe('ReferenceError: All is Dust')
expect(lines[4].trim()).toBe('stack trace of ReferenceError')
expect(lines[7].trim()).toBe('InternalError: Abandon Hope')
expect(lines[9].trim()).toBe('stack trace of InternalError')
})
it('should detect failed test case with Assertion failed from expect-webdriverIO', () => {
const reporter = new AllureReporter({ outputDir })
const runnerEvent = runnerStart()
delete runnerEvent.capabilities.browserName
delete runnerEvent.capabilities.version
reporter.onRunnerStart(runnerEvent)
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onTestFail(testFailedWithAssertionErrorFromExpectWebdriverIO())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].name).toEqual('should can do something')
expect(results[0].status).toEqual(Status.FAILED)
const { message } = results[0].statusDetails
const lines = message.split('\n')
expect(lines[0]).toBe('Expect $(`login-app`).$(`<fn>`).$(`<fn>`).$(`<fn>`) to be displayed')
expect(lines[1].trim()).toBe('Expected: "displayed"')
expect(lines[2].trim()).toBe('Received: "not displayed"')
})
})
describe('Pending tests', () => {
let outputDir: any
afterEach(() => {
clean(outputDir)
})
it('should detect started pending test case', () => {
outputDir = temporaryDirectory()
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onTestSkip(testPending())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].name).toEqual('should can do something')
expect(results[0].status).toEqual(Status.SKIPPED)
expect(results[0].stage).toEqual(Stage.PENDING)
expect(results[0].historyId).toEqual('2838a547ee87e372fadb8927d9efaad3')
})
it('should detect not started pending test case', () => {
outputDir = temporaryDirectory()
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onTestSkip(testPending())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].name).toEqual('should can do something')
expect(results[0].status).toEqual(Status.SKIPPED)
expect(results[0].stage).toEqual(Stage.PENDING)
expect(results[0].historyId).toEqual('2838a547ee87e372fadb8927d9efaad3')
})
it('should detect not started pending test case after completed test', () => {
outputDir = temporaryDirectory()
const reporter = new AllureReporter({ outputDir })
let passed = testStart()
passed = {
...passed,
title: passed.title + '2',
uid: passed.uid + '2',
fullTitle: passed.fullTitle + '2'
}
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(passed)
reporter.onTestPass()
reporter.onTestSkip(testPending())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(2)
const passedResult = results.find((result: any) => result.status === Status.PASSED)
const skippedResult = results.find((result: any) => result.status === Status.SKIPPED)
expect(passedResult.name).toEqual(passed.title)
expect(passedResult.stage).toEqual(Stage.FINISHED)
expect(skippedResult.name).toEqual('should can do something')
expect(skippedResult.stage).toEqual(Stage.PENDING)
})
})
describe('Hook reporting', () => {
let outputDir: any
beforeEach(() => {
outputDir = temporaryDirectory()
})
afterEach(() => {
clean(outputDir)
})
it('should report failed all hook', () => {
const reporter = new AllureReporter({ outputDir })
const runnerEvent = runnerStart()
delete runnerEvent.capabilities.browserName
delete runnerEvent.capabilities.version
reporter.onRunnerStart(runnerEvent)
reporter.onSuiteStart(suiteStart())
reporter.onHookStart(hookStart())
reporter.onHookEnd(hookFailed())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results, containers } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(containers[0].befores[0].steps[0].name).toEqual(
'"before all" hook for "should login with valid credentials"',
)
expect(results[0].status).toEqual(Status.BROKEN)
})
it('should report failed before each hook', () => {
const reporter = new AllureReporter({ outputDir })
const runnerEvent = runnerStart()
delete runnerEvent.capabilities.browserName
delete runnerEvent.capabilities.version
reporter.onRunnerStart(runnerEvent)
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onHookStart(eachHookStart())
reporter.onHookEnd(eachHookFailed())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results, containers } = getResults(outputDir)
expect(results).toHaveLength(2)
expect(containers[0].befores[0].steps).toHaveLength(1)
expect(['should can do something', 'My Login application'].includes(results[0].name)).toBeTruthy()
expect(containers[0].befores[0].status).toEqual(Status.BROKEN)
const hookCase = containers[0].befores[0].steps.find(((tc: any) => tc.name === '"before each" hook'))
expect(hookCase).toBeDefined()
expect(hookCase.status).toEqual(Status.BROKEN)
expect(containers[0].befores[0].steps[0]).toBeDefined()
expect(containers[0].befores[0].steps[0].name).toEqual('"before each" hook')
expect(containers[0].befores[0].steps[0].status).toEqual(Status.BROKEN)
})
it('should report failed before each hook with disableMochaHooks', () => {
const reporter = new AllureReporter({ outputDir, disableMochaHooks: true })
const runnerEvent = runnerStart()
delete runnerEvent.capabilities.browserName
delete runnerEvent.capabilities.version
reporter.onRunnerStart(runnerEvent)
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onHookStart(eachHookStart())
reporter.onHookEnd(eachHookFailed())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results, containers } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].name).toEqual('should can do something')
expect(containers[0].befores[0].status).toEqual(Status.BROKEN)
expect(containers[0].befores[0].steps[0].name).toEqual(
'"before each" hook',
)
expect(containers[0].befores[0].steps[0].status).toEqual(Status.BROKEN)
})
})
describe('Allure ID', () => {
const outputDir = temporaryDirectory()
let allureResult: Record<string, any>
beforeAll(() => {
const reporter = new AllureReporter({
outputDir
})
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.addAllureId({ id: 'explicitly set allureId' })
reporter.onTestPass()
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
allureResult = results[0]
})
afterAll(() => {
clean(outputDir)
})
it('explicitly set allureId overrides testCaseId ', () => {
const labels = mapBy<Label>(allureResult.labels, 'name')
const allureId = labels[LabelName.AS_ID]
expect(allureId).toHaveLength(1)
expect(allureId[0].value).toEqual('explicitly set allureId')
expect(allureResult.testCaseId).toEqual(undefined)
})
})
const assertionResults: any = {
webdriver: {
commandTitle: 'GET /session/:sessionId/element',
screenshotTitle: 'GET /session/:sessionId/screenshot'
},
devtools: {
commandTitle: 'getTitle',
screenshotTitle: 'takeScreenshot'
}
}
describe('command reporting', () => {
let outputDir: any
beforeEach(() => {
outputDir = temporaryDirectory()
})
afterEach(() => {
clean(outputDir)
})
it('should not add step if no tests started', () => {
const allureOptions = {
stdout: true,
outputDir
}
const reporter = new AllureReporter(allureOptions)
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onBeforeCommand(commandStart(false))
reporter.onAfterCommand(commandEnd(false))
reporter.onTestSkip(testPending())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].steps).toHaveLength(0)
})
it('should not add step if isMultiremote = true', () => {
const allureOptions = {
stdout: true,
outputDir
}
const reporter = new AllureReporter(allureOptions)
reporter.onRunnerStart(Object.assign(runnerStart(), { isMultiremote: true }))
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onBeforeCommand(commandStart(false))
reporter.onAfterCommand(commandEnd(false))
reporter.onTestSkip(testPending())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].steps).toHaveLength(0)
})
it('should not end step if it was not started', () => {
const allureOptions = {
stdout: true,
outputDir
}
const reporter = new AllureReporter(allureOptions)
reporter.onRunnerStart(Object.assign(runnerStart(), { isMultiremote: true }))
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onAfterCommand(commandEnd(false))
reporter.onTestSkip(testPending())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].steps).toHaveLength(0)
})
it('should not add step if disableWebdriverStepsReporting = true', () => {
const allureOptions = {
stdout: true,
outputDir,
disableWebdriverStepsReporting: true
}
const reporter = new AllureReporter(allureOptions)
reporter.onRunnerStart(Object.assign(runnerStart(),))
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onBeforeCommand(commandStart(false))
reporter.onAfterCommand(commandEnd(false))
reporter.onTestSkip(testPending())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].steps).toHaveLength(0)
})
it('should add step from command', () => {
const allureOptions = {
stdout: true,
outputDir,
}
const reporter = new AllureReporter(allureOptions)
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onBeforeCommand(commandStart(false))
reporter.onAfterCommand(commandEnd(false))
reporter.onTestSkip(testPending())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].steps).toHaveLength(1)
expect(results[0].steps[0].name).toEqual(assertionResults['webdriver'].commandTitle)
expect(results[0].steps[0].status).toEqual(Status.PASSED)
expect(results[0].steps[0].attachments).toEqual(
[{
name: 'Request',
type: 'application/json',
source: expect.any(String),
},
{
name: 'Response',
type: 'application/json',
source: expect.any(String),
}]
)
})
it('should add step from custom command', () => {
const sessionId = '1234'
const customCommandBeforeArgs = {
sessionId,
command: 'customCommand',
body: ['arg1', 1, true, { foo: 'bar' }],
} satisfies BeforeCommandArgs
const customCommandAfterArgs = {
sessionId,
command: 'customCommand',
result: { value: {
foo: 'bar',
bar: 1,
baz: true
} }
} satisfies AfterCommandArgs
const allureOptions = {
stdout: true,
outputDir,
}
const reporter = new AllureReporter(allureOptions)
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onBeforeCommand(customCommandBeforeArgs)
reporter.onAfterCommand(customCommandAfterArgs)
reporter.onTestSkip(testPending())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].steps).toHaveLength(1)
expect(results[0].steps[0].name).toEqual('customCommand')
expect(results[0].steps[0].status).toEqual(Status.PASSED)
expect(results[0].steps[0].attachments).toEqual(
[{
name: 'Request',
type: 'application/json',
source: expect.any(String),
},
{
name: 'Response',
type: 'application/json',
source: expect.any(String),
}]
)
})
it('should add step from unknown command', () => {
const sessionId = '1234'
const customCommandBeforeArgs = {
sessionId,
body: undefined,
} satisfies BeforeCommandArgs
const customCommandAfterArgs = {
sessionId,
result: undefined
} satisfies AfterCommandArgs
const allureOptions = {
stdout: true,
outputDir,
}
const reporter = new AllureReporter(allureOptions)
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onBeforeCommand(customCommandBeforeArgs)
reporter.onAfterCommand(customCommandAfterArgs)
reporter.onTestSkip(testPending())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].steps).toHaveLength(1)
expect(results[0].steps[0].name).toEqual('unknown command')
expect(results[0].steps[0].status).toEqual(Status.PASSED)
expect(results[0].steps[0].attachments).toEqual([])
})
it('should add step from failed command', () => {
const error = new Error('Command failed')
const command = {
sessionId: '4d1707ae-820f-1645-8485-5a820b2a40da',
method: 'GET',
endpoint: '/session/:sessionId/element',
cid: '0-0'
}
const beforeCommand = {
...command,
body: { using: 'css selector', value: 'img' },
} satisfies BeforeCommandArgs
const afterCommandFailure = {
...command,
result: { error }
} satisfies AfterCommandArgs
const allureOptions = { stdout: true, outputDir }
const reporter = new AllureReporter(allureOptions)
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onBeforeCommand(beforeCommand)
reporter.onAfterCommand(afterCommandFailure)
reporter.onTestSkip(testPending())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].steps).toHaveLength(1)
expect(results[0].steps[0].name).toEqual(assertionResults['webdriver'].commandTitle)
expect(results[0].steps[0].status).toEqual(Status.PASSED)
expect(results[0].steps[0].attachments).toEqual(
[{
name: 'Request',
type: 'application/json',
source: expect.any(String),
},
{
name: 'Response',
type: 'text/plain',
source: expect.any(String),
}]
)
})
it('should not empty attach for step from command', () => {
const allureOptions = {
stdout: true,
outputDir,
}
const reporter = new AllureReporter(allureOptions)
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
const command = commandStart(false)
delete command.body
reporter.onBeforeCommand(command)
reporter.onAfterCommand(commandEnd(false))
reporter.onTestSkip(testPending())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].steps).toHaveLength(1)
const requestAttachments = results[0].steps[0].attachments.filter(
(attachment: Attachment) => attachment.name === 'Request'
)
expect(results[0].steps[0].name).toEqual(assertionResults['webdriver'].commandTitle)
expect(results[0].steps[0].status).toEqual(Status.PASSED)
expect(requestAttachments).toHaveLength(0)
})
it('should add step with screenshot command', () => {
const allureOptions = {
stdout: true,
outputDir,
}
const reporter = new AllureReporter(allureOptions)
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onBeforeCommand(commandStartScreenShot(false))
reporter.onAfterCommand(commandEndScreenShot(false))
reporter.onTestSkip(testPending())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].steps).toHaveLength(1)
const screenshotAttachments = results[0].steps[0].attachments.filter(
(attachment: Attachment) => attachment.name === 'Screenshot'
)
expect(results[0].steps[0].name).toEqual(assertionResults['webdriver'].screenshotTitle)
expect(results[0].steps[0].status).toEqual(Status.PASSED)
expect(screenshotAttachments).toHaveLength(1)
})
it('should add step with screenshot command when disableWebdriverStepsReporting=true', () => {
const allureOptions = {
stdout: true,
outputDir,
disableWebdriverStepsReporting: true
}
const reporter = new AllureReporter(allureOptions)
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onBeforeCommand(commandStartScreenShot(false))
reporter.onAfterCommand(commandEndScreenShot(false))
reporter.onTestSkip(testPending())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
const screenshotAttachments = results[0].attachments.filter(
(attachment: Attachment) => attachment.name === 'Screenshot'
)
expect(screenshotAttachments).toHaveLength(1)
})
it('should not add step with screenshot command when disableWebdriverScreenshotsReporting=true', () => {
const allureOptions = {
stdout: true,
outputDir,
disableWebdriverScreenshotsReporting: true
}
const reporter = new AllureReporter(allureOptions)
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onBeforeCommand(commandStartScreenShot(false))
reporter.onAfterCommand(commandEndScreenShot(false))
reporter.onTestSkip(testPending())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].steps).toHaveLength(1)
const screenshotAttachments = results[0].steps[0].attachments.filter(
(attachment: Attachment) => attachment.name === 'Screenshot'
)
expect(results[0].steps[0].name).toEqual(assertionResults['webdriver'].screenshotTitle)
expect(results[0].steps[0].status).toEqual(Status.PASSED)
expect(screenshotAttachments).toHaveLength(0)
})
it('should attach screenshot on hook failure', () => {
const allureOptions = {
stdout: true,
outputDir,
disableMochaHooks: true,
disableWebdriverStepsReporting: true
}
const reporter = new AllureReporter(allureOptions)
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onHookStart(hookStart())
reporter.onTestStart(testStart())
reporter.onBeforeCommand(commandStartScreenShot(false))
reporter.onAfterCommand(commandEndScreenShot(false))
reporter.onHookEnd(hookFailed())
reporter.onTestPass()
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results, containers } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(containers[0].befores[0].steps).toHaveLength(1)
const result = results.find((res: any) => res.attachments.length === 1)
expect(result).toBeDefined()
const screenshotAttachments = result.attachments.filter(
(attachment: Attachment) => attachment.name === 'Screenshot'
)
expect(screenshotAttachments).toHaveLength(1)
})
it('should attach console log for passing test', () => {
const allureOptions = {
stdout: true,
outputDir,
disableMochaHooks: true,
addConsoleLogs: true
}
const reporter = new AllureReporter(allureOptions)
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
log('Printing to console 1')
reporter.onTestStart(testStart())
log('Printing to console 2')
log('Printing webdriver to console 2')
reporter.onTestPass()
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
const consoleAttachments = results[0].attachments.filter(
(attachment: Attachment) => attachment.name === 'Console Logs'
)
expect(consoleAttachments).toHaveLength(1)
})
it('should attach console log for failing test', () => {
const allureOptions = {
stdout: true,
outputDir,
disableMochaHooks: true,
addConsoleLogs: true
}
const reporter = new AllureReporter(allureOptions)
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
log('Printing to console 1')
reporter.onTestStart(testStart())
log('Printing to console 2')
log('Printing webdriver to console 2')
reporter.onTestFail(testFailed())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
const consoleAttachments = results[0].attachments.filter(
(attachment: Attachment) => attachment.name === 'Console Logs'
)
expect(consoleAttachments).toHaveLength(1)
})
it('should attach console log for skipping test', () => {
const allureOptions = {
stdout: true,
outputDir,
disableMochaHooks: true,
addConsoleLogs: true
}
const reporter = new AllureReporter(allureOptions)
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
log('Printing to console 1')
reporter.onTestStart(testStart())
log('Printing to console 2')
log('Printing webdriver to console 2')
reporter.onTestSkip(testFailed())
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
const consoleAttachments = results[0].attachments.filter(
(attachment: Attachment) => attachment.name === 'Console Logs'
)
expect(results).toHaveLength(1)
expect(consoleAttachments).toHaveLength(1)
})
it('should not attach webdriver logs', () => {
const allureOptions = {
stdout: true,
outputDir,
disableMochaHooks: true,
addConsoleLogs: true
}
const reporter = new AllureReporter(allureOptions)
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
log('Printing to console 1')
reporter.onTestStart(testStart())
log('Printing mwebdriver to console 2')
reporter.onTestPass()
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
const consoleAttachments = results[0].attachments.filter(
(attachment: Attachment) => attachment.name === 'Console Logs'
)
expect(results).toHaveLength(1)
expect(consoleAttachments).toHaveLength(0)
})
})