import path from 'node:path'
import { describe, it, expect, beforeEach, vi, beforeAll, afterAll } from 'vitest'
import type { HookStats } from '@wdio/types'
import type { Parameter, Label, Link } from 'allure-js-commons'
import { Stage, Status, LabelName, LinkType, ContentType } from 'allure-js-commons'
import AllureReporter from '../src/reporter.js'
import { linkPlaceholder } from '../src/constants.js'
import { TYPE } from '../src/types.js'
import { getResults, clean } from './helpers/wdio-allure-helper.js'
vi.mock('@wdio/reporter', () => import(path.join(process.cwd(), '__mocks__', '@wdio/reporter')))
import { temporaryDirectory } from 'tempy'
import { runnerEnd, runnerStart } from './__fixtures__/runner.js'
import { testStart } from './__fixtures__/testState.js'
import { suiteStart, suiteEnd } from './__fixtures__/suite.js'
let processOn: any
beforeAll(() => {
processOn = process.on.bind(process)
process.on = vi.fn()
})
afterAll(() => {
process.on = processOn
})
beforeEach(() => {
vi.clearAllMocks()
})
describe('reporter runtime implementation', () => {
const outputDir = temporaryDirectory()
beforeEach(() => {
clean(outputDir)
})
it('should correct add custom label', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addLabel({ name: 'customLabel', value: 'Label' })
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].labels.find((label: Label) => label.name === 'customLabel').value).toEqual('Label')
})
it('should correct add story label', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addStory({ storyName: 'foo' })
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].labels.find((label: Label) => label.name === LabelName.STORY).value).toEqual('foo')
})
it('should correct add feature label', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addFeature({ featureName: 'foo' })
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].labels.find((label: Label) => label.name === LabelName.FEATURE).value).toEqual('foo')
})
it('should correct add severity label', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addSeverity({ severity: 'foo' })
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].labels.find((label: Label) => label.name === LabelName.SEVERITY).value).toEqual('foo')
})
it('should correct add suite label', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addSuite({ suiteName: 'foo' })
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].labels.find((label: Label) => label.name === LabelName.SUITE).value).toEqual('foo')
})
it('should correct add subSuite label', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addSubSuite({ suiteName: 'foo' })
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].labels.find((label: Label) => label.name === LabelName.SUB_SUITE).value).toEqual('foo')
})
it('should correct add parentSuite label', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addParentSuite({ suiteName: 'foo' })
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].labels.find((label: Label) => label.name === LabelName.PARENT_SUITE).value).toEqual('foo')
})
it('should correct add tag label', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addTag({ tag: 'foo' })
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].labels.find((label: Label) => label.name === LabelName.TAG).value).toEqual('foo')
})
it('should correct add epic label', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addEpic({ epicName: 'foo' })
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].labels.find((label: Label) => label.name === LabelName.EPIC).value).toEqual('foo')
})
it('should correct add allure id label', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addAllureId({ id: 'foo' })
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].labels.find((label: Label) => label.name === LabelName.AS_ID).value).toEqual('foo')
})
it('should correctly add issue label with link', () => {
const reporter = new AllureReporter({ outputDir, issueLinkTemplate: `http://example.com/${linkPlaceholder}` })
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addIssue({ issue: '1' })
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].links.find((link: Link) => link.type === LinkType.ISSUE).url).toEqual('http://example.com/1')
})
it('should correctly add test id label with link', () => {
const reporter = new AllureReporter({ outputDir, tmsLinkTemplate: `https://webdriver.io/${linkPlaceholder}` })
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addTestId({ testId: '2' })
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].links.find((link: Link) => link.type === LinkType.TMS).url).toEqual('https://webdriver.io/2')
})
it('should correct add description', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addDescription({
description: 'foo',
descriptionType: TYPE.MARKDOWN
})
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].description).toEqual('foo')
})
it('should correct add html description', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addDescription({
description: 'foo',
descriptionType: TYPE.HTML
})
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].descriptionHtml).toEqual('foo')
})
it('should correct add attachment', () => {
const reporter = new AllureReporter({ outputDir })
const attachFileSpy = vi.spyOn(reporter, 'attachFile')
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addAttachment({ name: 'foo', content: 'bar', type: ContentType.TEXT })
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].attachments).toHaveLength(1)
expect(results[0].attachments[0]).toEqual({
name: 'foo',
type: ContentType.TEXT,
source: expect.any(String),
})
expect(attachFileSpy).toHaveBeenCalledWith('foo', Buffer.from('bar'), ContentType.TEXT)
})
it('should correct add "application/json" attachment', () => {
const reporter = new AllureReporter({ outputDir })
const attachJSONSpy = vi.spyOn(reporter, 'attachJSON')
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addAttachment({ name: 'foo', content: { bar: 'bar' }, type: ContentType.JSON })
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].attachments).toHaveLength(1)
expect(results[0].attachments[0]).toEqual({
name: 'foo',
type: ContentType.JSON,
source: expect.any(String),
})
expect(attachJSONSpy).toHaveBeenCalledWith('foo', { bar: 'bar' })
})
it('should allow to start end step', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.startStep('bar')
reporter.endStep(Status.FAILED)
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].steps).toHaveLength(1)
expect(results[0].steps[0].status).toEqual(Status.FAILED)
expect(results[0].steps[0].stage).toEqual(Stage.FINISHED)
})
it('should correct add step with attachment', () => {
const step = {
attachment: { content: 'baz', name: 'attachment' },
status: Status.PASSED,
title: 'foo'
}
const reporter = new AllureReporter({ outputDir })
const attachFileSpy = vi.spyOn(reporter, 'attachFile')
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addStep({ step })
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].steps).toHaveLength(1)
expect(results[0].steps[0].name).toEqual(step.title)
expect(results[0].steps[0].status).toEqual(step.status)
expect(results[0].steps[0].stage).toEqual(Stage.FINISHED)
expect(results[0].steps[0].attachments).toHaveLength(1)
expect(results[0].steps[0].attachments[0]).toEqual({
name: step.attachment.name,
type: ContentType.TEXT,
source: expect.any(String),
})
expect(attachFileSpy).toHaveBeenCalledWith(step.attachment.name, step.attachment.content, ContentType.TEXT)
})
it('should correct add step without attachment', () => {
const step = {
status: Status.PASSED,
title: 'foo'
}
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addStep({ step })
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].steps).toHaveLength(1)
expect(results[0].steps[0].name).toEqual(step.title)
expect(results[0].steps[0].status).toEqual(step.status)
expect(results[0].steps[0].stage).toEqual(Stage.FINISHED)
})
it('should correctly add parameter', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.addArgument({ name: 'os', value: 'osx' })
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
const osParameter = results[0].parameters.find((parameter: Parameter) => parameter.name === 'os')
expect(results).toHaveLength(1)
expect(results[0].historyId).toEqual('3cffc3d1d78d183463efee4c042f156c')
expect(osParameter.value).toEqual('osx')
})
it('should do nothing if no tests run', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart(runnerStart())
reporter.addLabel({ name: 'foo', value: 'bar' })
reporter.addStory({ storyName: 'foobar' })
reporter.addFeature({ featureName: 'foobar' })
reporter.addSeverity({ severity: 'foobar' })
reporter.addIssue({ issue: 'foobar' })
reporter.addTestId({ testId: '123' })
reporter.addDescription({ description: 'foobar' })
reporter.addAttachment({ name: '', content: '', type: '' })
reporter.startStep('test')
reporter.endStep(Status.PASSED)
reporter.addStep({})
reporter.addArgument({})
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(0)
})
describe('add argument', () => {
it('should correctly add argument for selenium', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart({
...runnerStart(),
capabilities: { browserName: 'firefox', version: '1.2.3' },
})
reporter.onTestStart(testStart())
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].parameters).toHaveLength(1)
expect(results[0].parameters[0]).toEqual({ name: 'browser', value: 'firefox-1.2.3' })
})
it('should correctly set proper browser version for chrome headless in devtools', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart({
...runnerStart(),
capabilities: { browserName: 'Chrome Headless', browserVersion: '85.0.4183.84' },
})
reporter.onTestStart(testStart())
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].parameters).toHaveLength(1)
expect(results[0].parameters[0]).toEqual({ name: 'browser', value: 'Chrome Headless-85.0.4183.84' })
})
it('should correctly add argument for appium', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart({
...runnerStart(),
capabilities: {
deviceName: 'Android Emulator',
'appium:platformVersion': '8.0'
},
})
reporter.onTestStart(testStart())
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].parameters).toHaveLength(1)
expect(results[0].parameters[0]).toEqual({ name: 'device', value: 'Android Emulator-8.0' })
})
it('should correctly add device name when run on BrowserStack', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart({
...runnerStart(),
capabilities: { device: 'Google Pixel 3', 'appium:platformVersion': '9.0' },
})
reporter.onTestStart(testStart())
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].parameters).toHaveLength(1)
expect(results[0].parameters[0]).toEqual({ name: 'device', value: 'Google Pixel 3-9.0' })
})
it('should correctly add argument for multiremote', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart({
...runnerStart(),
isMultiremote: true,
capabilities: { myBrowser: { browserName: 'chrome' } },
})
reporter.onTestStart(testStart())
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].parameters).toHaveLength(1)
expect(results[0].parameters[0]).toEqual({ name: 'isMultiremote', value: 'true' })
})
})
describe('add allure step', () => {
it('should add labels from custom steps', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart({
...runnerStart(),
isMultiremote: true,
capabilities: { myBrowser: { browserName: 'chrome' } },
})
reporter.onTestStart(testStart())
reporter.addAllureStep({
labels: [{ name: 'foo', value: 'bar' }],
})
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
const childStepLabel = results[0].labels.find((label: Label) => label.name === 'foo')
expect(results).toHaveLength(1)
expect(childStepLabel.value).toEqual('bar')
})
it('should add parameters from custom steps', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart({
...runnerStart(),
isMultiremote: true,
capabilities: { myBrowser: { browserName: 'chrome' } },
})
reporter.onTestStart(testStart())
reporter.addAllureStep({
parameter: [{ name: 'foo', value: 'bar' }],
})
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
const childStepParameter = results[0].parameters.find((param: Parameter) => param.name === 'foo')
expect(results).toHaveLength(1)
expect(childStepParameter.value).toEqual('bar')
})
it('should add links from custom steps', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart({
...runnerStart(),
isMultiremote: true,
capabilities: { myBrowser: { browserName: 'chrome' } },
})
reporter.onTestStart(testStart())
reporter.addAllureStep({
links: [{ name: 'foo', url: 'http://example.org', type: 'type' }],
})
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
const childStepLink = results[0].links.find((link: Link) => link.name === 'foo')
expect(results).toHaveLength(1)
expect(childStepLink.url).toEqual('http://example.org')
expect(childStepLink.type).toEqual('type')
})
it('should add description from custom steps', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart({
...runnerStart(),
isMultiremote: true,
capabilities: { myBrowser: { browserName: 'chrome' } },
})
reporter.onTestStart(testStart())
reporter.addAllureStep({
description: 'foo'
})
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].description).toEqual('foo')
})
it('should add html description from custom steps', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart({
...runnerStart(),
isMultiremote: true,
capabilities: { myBrowser: { browserName: 'chrome' } },
})
reporter.onTestStart(testStart())
reporter.addAllureStep({
descriptionHtml: 'foo'
})
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].descriptionHtml).toEqual('foo')
})
it('should add custom steps as children to current test', () => {
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart({
...runnerStart(),
isMultiremote: true,
capabilities: { myBrowser: { browserName: 'chrome' } },
})
reporter.onTestStart(testStart())
reporter.addAllureStep({
steps: [
{
name: 'custom step',
attachments: [],
parameters: [],
steps: [],
status: Status.PASSED,
statusDetails: {
message: undefined,
trace: undefined,
},
stage: Stage.FINISHED,
}
]
})
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].steps).toHaveLength(1)
})
})
})
describe('auxiliary methods', () => {
const outputDir = temporaryDirectory()
beforeEach(() => {
clean(outputDir)
})
it('should populate the correct deviceName', () => {
const capabilities = {
deviceName: 'emulator',
desired: {
platformName: 'Android',
'appium:automationName': 'UiAutomator2',
'appium:deviceName': 'Android GoogleAPI Emulator',
'appium:platformVersion': '6.0',
'appium:noReset': true,
}
}
const reporter = new AllureReporter({ outputDir })
reporter.onRunnerStart({
...runnerStart(),
capabilities,
})
reporter.onTestStart(testStart())
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].parameters).toHaveLength(1)
expect(results[0].parameters[0]).toEqual({ name: 'device', value: 'Android GoogleAPI Emulator 6.0' })
})
})
describe('hooks handling disabled Mocha Hooks', () => {
let reporter: any
const outputDir = temporaryDirectory()
beforeEach(() => {
clean(outputDir)
reporter = new AllureReporter({ outputDir, disableMochaHooks: true })
})
it('should not add test on custom hook', () => {
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onHookStart({ cid: '0-0', title: 'foo', parent: 'bar' } as HookStats)
reporter.onHookEnd({ cid: '0-0', title: 'foo', parent: 'bar' } as HookStats)
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(0)
})
it('should not add test if no suite', () => {
reporter.onRunnerStart(runnerStart())
reporter.onHookStart({ cid: '0-0', title: 'foo', parent: 'bar' } as HookStats)
reporter.onHookEnd({ cid: '0-0', title: 'foo', parent: 'bar' } as HookStats)
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(0)
})
it('should ignore global mocha hooks', () => {
reporter.onRunnerStart(runnerStart())
reporter.onHookStart({ title: '"after all" hook', parent: '' } as HookStats)
reporter.onHookEnd({ title: '"after all" hook', parent: '' } as HookStats)
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(0)
})
it('should not capture mocha/jasmine each hooks', () => {
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onTestStart(testStart())
reporter.onHookStart({ cid: '0-0', title: '"before each" hook', parent: 'foo' } as HookStats)
reporter.onHookEnd({ cid: '0-0', title: '"before each" hook', parent: 'foo' } as HookStats)
reporter.onTestPass()
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results, containers } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].status).toEqual(Status.PASSED)
expect(results[0].stage).toEqual(Stage.FINISHED)
expect(containers[0].befores).toHaveLength(0)
})
it('should ignore passed mocha/jasmine each hooks if no test', () => {
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(suiteStart())
reporter.onHookStart({ cid: '0-0', title: '"after each" hook', parent: 'foo' } as HookStats)
reporter.onHookEnd({ cid: '0-0', title: '"after each" hook', parent: 'foo' } as HookStats)
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results, containers } = getResults(outputDir)
expect(containers[0].afters).toHaveLength(0)
expect(containers[0].children).toHaveLength(0)
expect(containers[0].befores).toHaveLength(0)
expect(results).toHaveLength(0)
})
it('should not start test onHookStart if no suite', () => {
reporter.onRunnerStart(runnerStart())
reporter.onTestStart(testStart())
reporter.onHookStart({ cid: '0-0', title: 'foo', parent: 'foo' } as HookStats)
reporter.onHookEnd({ cid: '0-0', title: 'foo', parent: 'foo' } as HookStats)
reporter.onTestPass()
reporter.onRunnerEnd(runnerEnd())
const { results, containers } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(results[0].name).toEqual('should can do something')
expect(containers).toHaveLength(0)
})
it('should ignore custom onHookEnd if no test', () => {
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(testStart())
reporter.onHookEnd({ cid: '0-0', title: 'foo', parent: 'foo' } as HookStats)
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results, containers } = getResults(outputDir)
expect(results).toHaveLength(0)
expect(containers[0].befores).toHaveLength(0)
expect(containers[0].afters).toHaveLength(0)
})
it('should ignore global mocha/jasmine end hooks', () => {
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(testStart())
reporter.onHookEnd({ cid: '0-0', title: 'foo' } as HookStats)
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results, containers } = getResults(outputDir)
expect(results).toHaveLength(0)
expect(containers[0].befores).toHaveLength(0)
})
it('should not pop test case if no steps and before hook', () => {
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(testStart())
reporter.onTestStart(testStart())
reporter.onHookEnd({ cid: '0-0', title: '"before all" hook', parent: 'foo' } as HookStats)
reporter.onTestPass()
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].steps).toHaveLength(0)
})
it('should pop test case if no steps and custom hook', () => {
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(testStart())
reporter.onTestStart(testStart())
reporter.onHookEnd({ cid: '0-0', title: 'bar', parent: 'foo' } as HookStats)
reporter.onTestPass()
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].children).toHaveLength(1)
expect(containers[0].befores).toHaveLength(0)
expect(containers[0].afters).toHaveLength(0)
expect(results[0].steps).toHaveLength(0)
})
it('should keep passed custom hooks if there are some steps', () => {
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(testStart())
reporter.onTestStart(testStart())
reporter.onBeforeCommand({ command: 'SomeCommandStep' })
reporter.onHookStart({ cid: '0-0', title: 'foo', parent: 'bar' } as HookStats)
reporter.onHookEnd({ cid: '0-0', title: 'foo', parent: 'bar' } as HookStats)
reporter.onAfterCommand({ command: 'SomeCommandStep' })
reporter.onTestPass()
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
const testResult = results.find(
(result) => result.name === 'should can do something',
)
const hookResult = results.find((result) =>
result.name.endsWith('foo'),
)
expect(results).toHaveLength(1)
expect(testResult).not.toBeUndefined()
expect(testResult.steps).toHaveLength(1)
expect(testResult.steps[0].name).toEqual('SomeCommandStep')
expect(hookResult).toBeUndefined()
})
it('should keep failed hooks if there no some steps', () => {
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(testStart())
reporter.onTestStart(testStart())
reporter.onHookStart({ cid: '0-0', title: '"after all" hook', parent: 'bar' } as HookStats)
reporter.onHookEnd({ cid: '0-0', title: '"after all" hook', parent: 'bar', error: { message: '', stack: '' } } as HookStats)
reporter.onTestPass()
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results, containers } = getResults(outputDir)
const testResult = results.find(
(result) => result.name === 'should can do something',
)
expect(results).toHaveLength(1)
expect(testResult).not.toBeUndefined()
expect(containers).toHaveLength(1)
expect(containers[0].afters).toHaveLength(1)
expect(containers[0].afters[0].status).toEqual(Status.BROKEN)
})
it('should keep failed hooks if there are some steps', () => {
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(testStart())
reporter.onTestStart(testStart())
reporter.onBeforeCommand({ command: 'SomeCommandStep' })
reporter.onHookStart({ cid: '0-0', title: '"after all" hook', parent: 'bar' } as HookStats)
reporter.onHookEnd({ cid: '0-0', title: '"after all" hook', parent: 'bar', error: { message: '', stack: '' } } as HookStats)
reporter.onAfterCommand({ command: 'SomeCommandStep' })
reporter.onTestPass()
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results, containers } = getResults(outputDir)
const testResult = results.find(
(result) => result.name === 'should can do something',
)
expect(results).toHaveLength(1)
expect(testResult).not.toBeUndefined()
expect(testResult.steps).toHaveLength(1)
expect(testResult.steps[0].name).toEqual('SomeCommandStep')
expect(containers[0].afters).toHaveLength(1)
expect(containers[0].afters[0].status).toEqual(Status.BROKEN)
})
it('should not capture mocha/jasmine each hooks end - passed', () => {
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(testStart())
reporter.onTestStart(testStart())
reporter.onHookStart({ title: '"after each" hook', parent: 'foo' })
reporter.onHookEnd({ title: '"after each" hook', parent: 'foo' })
reporter.onTestPass()
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results, containers } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(containers[0].afters).toHaveLength(0)
})
it('should create a test and add mocha all hooks as fixtures if hook throws', () => {
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart({ cid: '0-0', title: 'SomeSuite' })
reporter.onHookStart({ title: '"before all" hook', parent: 'foo' })
reporter.onHookEnd({ title: '"before all" hook', parent: 'foo', error: { message: '', stack: '' } })
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results, containers } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(containers[0].befores[0].status).toEqual(Status.BROKEN)
expect(containers[0].befores[0].stage).toEqual(Stage.FINISHED)
})
})
describe('hooks handling default', () => {
const outputDir = temporaryDirectory()
let reporter: any
beforeEach(() => {
clean(outputDir)
reporter = new AllureReporter({ outputDir, disableMochaHooks: false })
})
it('should capture mocha/jasmine each hooks ', () => {
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart({ cid: '0-0', title: 'SomeSuite' })
reporter.onHookStart({ title: '"before each" hook', parent: 'foo' })
reporter.onHookEnd({ title: '"before each" hook', parent: 'foo' })
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results, containers } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(containers[0].befores).toHaveLength(1)
expect(containers[0].befores[0].steps[0].name).toEqual(
'"before each" hook',
)
})
it('should not ignore mocha/jasmine each hooks if no test', () => {
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart({ cid: '0-0', title: 'SomeSuite' })
reporter.onHookStart({ title: '"after each" hook', parent: 'foo' })
reporter.onHookEnd({ title: '"after each" hook', parent: 'foo' })
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results, containers } = getResults(outputDir)
expect(results).toHaveLength(1)
expect(containers[0].afters[0].steps[0].name).toEqual(
'"after each" hook',
)
})
it('should keep passed hooks if there are no steps (before/after)', () => {
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart({ cid: '0-0', title: 'SomeSuite' })
reporter.onHookStart({ title: '"before all" hook', parent: 'foo' })
reporter.onHookEnd({ title: '"before all" hook', parent: 'foo' })
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',
)
})
it('should keep passed hooks if there are some steps', () => {
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart({ cid: '0-0', title: 'SomeSuite' })
reporter.onTestStart({ cid: '0-0', title: 'SomeTest' })
reporter.onBeforeCommand({ command: 'SomeCommandStep' })
reporter.onHookStart({ title: 'foo', parent: 'bar' })
reporter.onHookEnd({ title: 'foo', parent: 'bar' })
reporter.onAfterCommand({ command: 'SomeCommandStep' })
reporter.onTestPass()
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
expect(results).toHaveLength(2)
expect(
results.find((result) => result.name === 'hook:foo'),
).not.toBeUndefined()
})
})
describe('nested suite naming', () => {
const outputDir = temporaryDirectory()
let reporter: any
beforeEach(() => {
clean(outputDir)
reporter = new AllureReporter({ outputDir, disableMochaHooks: false })
})
it('should not end test if no hook ignored', () => {
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart({ cid: '0-0', title: 'foo' })
reporter.onSuiteStart({ cid: '0-0', title: 'bar' })
reporter.onSuiteEnd({ cid: '0-0', title: 'foo' })
reporter.onSuiteEnd({ cid: '0-0', title: 'foo' })
reporter.onRunnerEnd(runnerEnd())
const { containers } = getResults(outputDir)
const parentSuite = containers.find((suite) => suite.name === 'foo')
const childSuite = containers.find(
(suite) => suite.name === 'foo: bar',
)
expect(parentSuite).not.toBeUndefined()
expect(childSuite).not.toBeUndefined()
})
})
describe('test step naming', () => {
const outputDir = temporaryDirectory()
let reporter: any
beforeEach(() => {
clean(outputDir)
reporter = new AllureReporter({ outputDir, disableMochaHooks: false })
})
it('should display command name when both command name and enpoint are available ', () => {
const command = {
command: 'SomeCommandStep',
method: 'POST',
endpoint: '/session/:sessionId/element',
}
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(testStart())
reporter.onTestStart(testStart())
reporter.onBeforeCommand(command)
reporter.onAfterCommand(command)
reporter.onTestPass()
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
const testResult = results.find(
(result) => result.name === 'should can do something'
)
expect(results).toHaveLength(1)
expect(testResult).not.toBeUndefined()
expect(testResult.steps).toHaveLength(1)
expect(testResult.steps[0].name).toEqual(
'SomeCommandStep'
)
})
it('should display the endpoint and method in the absence of command name', () => {
const command = {
method: 'POST',
endpoint: '/session/:sessionId/element',
}
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(testStart())
reporter.onTestStart(testStart())
reporter.onBeforeCommand(command)
reporter.onAfterCommand(command)
reporter.onTestPass()
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
const { results } = getResults(outputDir)
const testResult = results.find(
(result) => result.name === 'should can do something'
)
expect(results).toHaveLength(1)
expect(testResult).not.toBeUndefined()
expect(testResult.steps).toHaveLength(1)
expect(testResult.steps[0].name).toEqual(
'POST /session/:sessionId/element'
)
})
})
describe('request fails', () => {
const outputDir = temporaryDirectory()
let reporter: any
beforeEach(() => {
clean(outputDir)
reporter = new AllureReporter({ outputDir, disableMochaHooks: false })
})
it('should attachJSON with error name in onAfterCommand when the command fails', () => {
const command = {
method: 'POST',
endpoint: '/session/:sessionId/element',
result : {
error: {
name: 'SomeError',
}
}
}
const attachJSONSpy = vi.spyOn(reporter, 'attachJSON')
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(testStart())
reporter.onTestStart(testStart())
reporter.onBeforeCommand(command)
reporter.onAfterCommand(command)
reporter.onTestPass()
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
expect(attachJSONSpy).toHaveBeenCalledWith('Response', 'SomeError')
})
it('should not attachJSON in onAfterCommand when the command result has nothing', () => {
const command = {
method: 'POST',
endpoint: '/session/:sessionId/element',
result : {}
}
const attachJSONSpy = vi.spyOn(reporter, 'attachJSON')
reporter.onRunnerStart(runnerStart())
reporter.onSuiteStart(testStart())
reporter.onTestStart(testStart())
reporter.onBeforeCommand(command)
reporter.onAfterCommand(command)
reporter.onTestPass()
reporter.onSuiteEnd(suiteEnd())
reporter.onRunnerEnd(runnerEnd())
expect(attachJSONSpy).not.toHaveBeenCalled()
})
})