@wdio/allure-reporter
Advanced tools
Comparing version 8.36.1 to 8.37.0
@@ -24,5 +24,5 @@ export declare const events: { | ||
}; | ||
export declare const mochaEachHooks: readonly ["\"before each\" hook", "\"after each\" hook"]; | ||
export declare const mochaAllHooks: readonly ["\"before all\" hook", "\"after all\" hook"]; | ||
export declare const eachHooks: readonly ["\"before each\" hook", "\"after each\" hook"]; | ||
export declare const allHooks: readonly ["\"before all\" hook", "\"after all\" hook"]; | ||
export declare const linkPlaceholder = "{}"; | ||
//# sourceMappingURL=constants.d.ts.map |
@@ -24,4 +24,4 @@ export const events = { | ||
}; | ||
export const mochaEachHooks = ['"before each" hook', '"after each" hook']; | ||
export const mochaAllHooks = ['"before all" hook', '"after all" hook']; | ||
export const eachHooks = ['"before each" hook', '"after each" hook']; | ||
export const allHooks = ['"before all" hook', '"after all" hook']; | ||
export const linkPlaceholder = '{}'; |
/// <reference types="node" resolution-mode="require"/> | ||
import type { SuiteStats, HookStats, RunnerStats, TestStats, BeforeCommandArgs, AfterCommandArgs } from '@wdio/reporter'; | ||
import WDIOReporter from '@wdio/reporter'; | ||
import type { MetadataMessage, AllureStep } from 'allure-js-commons'; | ||
import { AllureGroup, AllureTest, Status as AllureStatus, Stage, ContentType } from 'allure-js-commons'; | ||
import type { MetadataMessage } from 'allure-js-commons'; | ||
import { AllureGroup, AllureTest, Status as AllureStatus, Stage, ContentType, AllureStep } from 'allure-js-commons'; | ||
import { addFeature, addLink, addOwner, addEpic, addSuite, addSubSuite, addParentSuite, addTag, addLabel, addSeverity, addIssue, addTestId, addStory, addAllureId, addDescription, addAttachment, startStep, endStep, addStep, addArgument, step } from './common/api.js'; | ||
@@ -7,0 +7,0 @@ import { AllureReporterState } from './state.js'; |
import { stringify } from 'csv-stringify/sync'; | ||
import WDIOReporter from '@wdio/reporter'; | ||
import { AllureRuntime, AllureGroup, AllureTest, Status as AllureStatus, Stage, LabelName, LinkType, ContentType, AllureCommandStepExecutable, } from 'allure-js-commons'; | ||
import { AllureRuntime, AllureGroup, AllureTest, Status as AllureStatus, Stage, LabelName, LinkType, ContentType, AllureCommandStepExecutable, ExecutableItemWrapper, AllureStep, Status } from 'allure-js-commons'; | ||
import { addFeature, addLink, addOwner, addEpic, addSuite, addSubSuite, addParentSuite, addTag, addLabel, addSeverity, addIssue, addTestId, addStory, addAllureId, addDescription, addAttachment, startStep, endStep, addStep, addArgument, step, } from './common/api.js'; | ||
import { AllureReporterState } from './state.js'; | ||
import { getTestStatus, isEmpty, isMochaEachHooks, getErrorFromFailedTest, isMochaAllHooks, getLinkByTemplate, isScreenshotCommand, getSuiteLabels, setAllureIds, isMochaBeforeEachHook, } from './utils.js'; | ||
import { getTestStatus, isEmpty, isEachTypeHooks, getErrorFromFailedTest, isAllTypeHooks, getLinkByTemplate, isScreenshotCommand, getSuiteLabels, setAllureIds, isBeforeTypeHook, cleanCucumberHooks, getHookStatus } from './utils.js'; | ||
import { events } from './constants.js'; | ||
@@ -47,3 +47,3 @@ import { TYPE as DescriptionType } from './types.js'; | ||
attachLogs() { | ||
if (!this._consoleOutput || !this._state.currentAllureTestOrStep) { | ||
if (!this._consoleOutput || !this._state.currentAllureStepableEntity) { | ||
return; | ||
@@ -53,3 +53,3 @@ } | ||
const attachmentFilename = this._allure.writeAttachment(logsContent, ContentType.TEXT); | ||
this._state.currentAllureTestOrStep.addAttachment('Console Logs', { | ||
this._state.currentAllureStepableEntity.addAttachment('Console Logs', { | ||
contentType: ContentType.TEXT, | ||
@@ -59,7 +59,7 @@ }, attachmentFilename); | ||
attachFile(name, content, contentType) { | ||
if (!this._state.currentAllureTestOrStep) { | ||
if (!this._state.currentAllureStepableEntity) { | ||
throw new Error("There isn't any active test!"); | ||
} | ||
const attachmentFilename = this._allure.writeAttachment(content, contentType); | ||
this._state.currentAllureTestOrStep.addAttachment(name, { | ||
this._state.currentAllureStepableEntity.addAttachment(name, { | ||
contentType, | ||
@@ -85,21 +85,29 @@ }, attachmentFilename); | ||
} | ||
while (this._state.currentAllureTestOrStep) { | ||
const currentTest = this._state.pop(); | ||
const isAnyStepFailed = currentTest.wrappedItem.steps.some((step) => step.status === AllureStatus.FAILED); | ||
const isAnyStepBroken = currentTest.wrappedItem.steps.some((step) => step.status === AllureStatus.BROKEN); | ||
currentTest.stage = Stage.FINISHED; | ||
currentTest.status = isAnyStepFailed | ||
? AllureStatus.FAILED | ||
: isAnyStepBroken | ||
? AllureStatus.BROKEN | ||
: AllureStatus.PASSED; | ||
if (currentTest instanceof AllureTest) { | ||
setAllureIds(currentTest, this._state.currentSuite); | ||
currentTest.endTest(); | ||
while (this._state.currentAllureStepableEntity) { | ||
const currentElement = this._state.pop(); | ||
if (!(currentElement instanceof AllureGroup)) { | ||
const isAnyStepFailed = currentElement.wrappedItem.steps.some((step) => step.status === AllureStatus.FAILED); | ||
const isAnyStepBroken = currentElement.wrappedItem.steps.some((step) => step.status === AllureStatus.BROKEN); | ||
currentElement.stage = Stage.FINISHED; | ||
currentElement.status = isAnyStepFailed | ||
? AllureStatus.FAILED | ||
: isAnyStepBroken | ||
? AllureStatus.BROKEN | ||
: AllureStatus.PASSED; | ||
} | ||
else { | ||
currentTest.endStep(); | ||
if (currentElement instanceof AllureTest) { | ||
setAllureIds(currentElement, this._state.currentSuite); | ||
currentElement.endTest(); | ||
} | ||
else if (currentElement instanceof AllureStep) { | ||
currentElement.endStep(); | ||
} | ||
} | ||
const currentSuite = this._state.pop(); | ||
// if a hook were execute without a test the report will need a test to display the hook | ||
if (this._state.stats.hooks > 0 && this._state.stats.test === 0) { | ||
const test = currentSuite.startTest(currentSuite.name); | ||
test.status = Status.BROKEN; | ||
test.endTest(); | ||
} | ||
currentSuite.endGroup(); | ||
@@ -114,3 +122,3 @@ } | ||
_skipTest() { | ||
if (!this._state.currentAllureTestOrStep) { | ||
if (!this._state.currentAllureStepableEntity) { | ||
return; | ||
@@ -130,3 +138,3 @@ } | ||
_endTest(status, error, stage) { | ||
if (!this._state.currentAllureTestOrStep) { | ||
if (!this._state.currentAllureStepableEntity) { | ||
return; | ||
@@ -140,2 +148,6 @@ } | ||
currentSpec.detailsTrace = error.stack; | ||
// if some step or sub step fails the current test will fails. | ||
if (this._state.currentTest) { | ||
this._state.currentTest.statusDetails = { message: error.message, trace: error.stack }; | ||
} | ||
} | ||
@@ -146,3 +158,3 @@ if (currentSpec instanceof AllureTest) { | ||
} | ||
else { | ||
else if (currentSpec instanceof AllureStep) { | ||
currentSpec.endStep(); | ||
@@ -152,6 +164,6 @@ } | ||
_startStep(testTitle) { | ||
if (!this._state.currentAllureTestOrStep) { | ||
throw new Error("There isn't any active test!"); | ||
if (!this._state.currentAllureStepableEntity) { | ||
throw new Error('There are no active steppable entities!'); | ||
} | ||
const newStep = this._state.currentAllureTestOrStep.startStep(testTitle); | ||
const newStep = this._state.currentAllureStepableEntity.startStep(testTitle); | ||
this._state.push(newStep); | ||
@@ -238,3 +250,3 @@ } | ||
this._state.currentFile = suite.file; | ||
// handle cucumber scenario as allure "case" instead of "suite" | ||
// handle a cucumber scenario as allure "case" instead of "suite" | ||
if (useCucumberStepReporter && isScenario) { | ||
@@ -291,2 +303,9 @@ this._startTest(suite.title, suite.cid); | ||
if (isPassed || isPartiallySkipped) { | ||
// const currentTest = this._state.pop() as AllureTest | ||
// const currentTest = this._state.currentTest as AllureTest | ||
// | ||
// currentTest.status = AllureStatus.PASSED | ||
// currentTest.stage = Stage.FINISHED | ||
// setHistoryId(currentTest, this._state.currentSuite) | ||
// setAllureIds(currentTest, this._state.currentSuite) | ||
this._endTest(AllureStatus.PASSED); | ||
@@ -333,7 +352,7 @@ return; | ||
} | ||
if (!this._state.currentAllureTestOrStep) { | ||
if (!this._state.currentAllureStepableEntity) { | ||
this.onTestStart(test); | ||
} | ||
else { | ||
this._state.currentAllureTestOrStep.name = test.title; | ||
else if (this._state.currentAllureStepableEntity instanceof AllureTest) { | ||
this._state.currentAllureStepableEntity.name = test.title; | ||
} | ||
@@ -345,7 +364,12 @@ this.attachLogs(); | ||
onTestSkip(test) { | ||
const { useCucumberStepReporter } = this._options; | ||
this.attachLogs(); | ||
if (!this._state.currentAllureTestOrStep || this._state.currentAllureTestOrStep.wrappedItem.name !== test.title) { | ||
this._startTest(test.title, test.cid); | ||
this._skipTest(); | ||
return; | ||
if (!this._state.currentAllureStepableEntity || this._state.currentAllureStepableEntity.wrappedItem.name !== | ||
test.title) { | ||
if (useCucumberStepReporter) { | ||
this.onTestStart(test); | ||
} | ||
else { | ||
this._startTest(test.title, test.cid); | ||
} | ||
} | ||
@@ -355,3 +379,3 @@ this._skipTest(); | ||
onBeforeCommand(command) { | ||
if (!this._state.currentAllureTestOrStep) { | ||
if (!this._state.currentAllureStepableEntity) { | ||
return; | ||
@@ -384,24 +408,28 @@ } | ||
onHookStart(hook) { | ||
const { disableMochaHooks } = this._options; | ||
// ignore global hooks | ||
if (!hook.parent || !this._state.currentSuite) { | ||
const { disableMochaHooks, useCucumberStepReporter } = this._options; | ||
// ignore global hooks or hooks when option is set in false | ||
// any hook is skipped if there is not a suite created. | ||
if (!hook.parent || !this._state.currentSuite || disableMochaHooks) { | ||
return; | ||
} | ||
const isMochaAllHook = isMochaAllHooks(hook.title); | ||
const isMochaEachHook = isMochaEachHooks(hook.title); | ||
// don't add hook as test to suite for mocha each hooks if no current test | ||
if (disableMochaHooks && isMochaEachHook && !this._state.currentAllureTestOrStep) { | ||
return; | ||
const isAllHook = isAllTypeHooks(hook.title); // if the hook is beforeAll or afterAll for mocha/jasmine | ||
const isEachHook = isEachTypeHooks(hook.title); // if the hook is beforeEach or afterEach for mocha/jasmine | ||
// if the hook is before/after from mocha/jasmine | ||
if (isAllHook || isEachHook) { | ||
const hookExecutable = isBeforeTypeHook(hook.title) | ||
? this._state.currentSuite.addBefore() | ||
: this._state.currentSuite.addAfter(); | ||
const hookStep = hookExecutable.startStep(hook.title); | ||
this._state.push(hookExecutable); | ||
this._state.push(hookStep); | ||
// if the hook is custom by default, it will be reported as test (not usual) | ||
} | ||
// add beforeEach / afterEach hook as step to test | ||
if (disableMochaHooks && isMochaEachHook && this._state.currentAllureTestOrStep) { | ||
this._startStep(hook.title); | ||
return; | ||
else if (!(isAllHook || isEachHook) && !useCucumberStepReporter) { | ||
const customHookTest = this._state.currentSuite.startTest(`hook:${hook.title}`); | ||
this._state.push(customHookTest); | ||
// hooks in cucumber mode will be treated as Test/Step | ||
} | ||
// don't add hook as test to suite for mocha All hooks | ||
if (disableMochaHooks && isMochaAllHook) { | ||
return; | ||
else if (useCucumberStepReporter) { | ||
this.onTestStart(hook); | ||
} | ||
// add hook as test to suite | ||
this.onTestStart(hook); | ||
} | ||
@@ -411,44 +439,100 @@ onHookEnd(hook) { | ||
// ignore global hooks | ||
// any hook is skipped if there is not a suite created. | ||
if (!hook.parent || !this._state.currentSuite) { | ||
return; | ||
} | ||
const isMochaAllHook = isMochaAllHooks(hook.title); | ||
const isMochaEachHook = isMochaEachHooks(hook.title); | ||
if (disableMochaHooks && !isMochaAllHook && !this._state.currentAllureTestOrStep) { | ||
return; | ||
const isAllHook = isAllTypeHooks(hook.title); // if the hook is beforeAll or afterAll for mocha/jasmine | ||
const isEachHook = isEachTypeHooks(hook.title); // if the hook is beforeEach or afterEach for mocha/jasmine | ||
/**** | ||
* if the hook is before/after from mocha/jasmine and disableMochaHooks=false. | ||
*/ | ||
// if the hook is before/after from mocha/jasmine and disableMochaHooks=false. | ||
if ((isAllHook || isEachHook) && !disableMochaHooks) { | ||
// getting the hook root step, and the hook element from stack. | ||
const currentHookRootStep = this._state.pop(); | ||
const currentHookRoot = this._state.pop(); | ||
// check if the elements exist | ||
if (currentHookRootStep || currentHookRoot) { | ||
// check if the elements related to hook | ||
if (currentHookRootStep instanceof AllureStep && | ||
currentHookRoot instanceof ExecutableItemWrapper) { | ||
getHookStatus(hook, currentHookRoot, currentHookRootStep); | ||
currentHookRootStep.endStep(); | ||
if (isBeforeTypeHook(hook.title) && (hook.error || hook.errors?.length)) { | ||
this._startTest(hook.currentTest || hook.title, hook.cid); | ||
this._endTest(AllureStatus.BROKEN, getErrorFromFailedTest(hook)); | ||
} | ||
return; | ||
} | ||
// put them back to the list | ||
if (currentHookRoot) { | ||
this._state.push(currentHookRoot); | ||
} | ||
if (currentHookRootStep) { | ||
this._state.push(currentHookRootStep); | ||
} | ||
} | ||
} | ||
// set beforeEach / afterEach hook (step) status | ||
if (disableMochaHooks && isMochaEachHook) { | ||
this._endTest(hook.error ? AllureStatus.FAILED : AllureStatus.PASSED, hook.error); | ||
// mocha doesn't fire onTestEnd for failed beforeEach hook | ||
// we have to force mark test as failed test | ||
if (isMochaBeforeEachHook(hook.title) && hook.error) { | ||
const fakeTestStat = Object.assign({}, hook, { title: hook.currentTest }); | ||
this._endTest(fakeTestStat.error ? AllureStatus.FAILED : AllureStatus.PASSED, fakeTestStat.error); | ||
/**** | ||
* if the hook is before/after from mocha/jasmine or cucumber by setting useCucumberStepReporter=true, | ||
* and disableMochaHooks=true with a failed hook. | ||
* | ||
* Only if the hook fails, it will be reported. | ||
*/ | ||
if (disableMochaHooks && hook.error) { | ||
// hook is from cucumber | ||
if (useCucumberStepReporter) { | ||
// report a new allure hook (step) | ||
this.onTestStart(hook); | ||
// set the hook as failed one | ||
this.onTestFail(hook); | ||
// remove cucumber hook (reported as step) from suite if it has no steps or attachments. | ||
const currentItem = this._state.currentAllureStepableEntity?.wrappedItem; | ||
if (currentItem) { | ||
cleanCucumberHooks(currentItem); | ||
} | ||
return; | ||
} | ||
// hook is before/after from mocha/jasmine | ||
const hookExecutable = isBeforeTypeHook(hook.title) | ||
? this._state.currentSuite.addBefore() | ||
: this._state.currentSuite.addAfter(); | ||
const hookStep = hookExecutable.startStep(hook.title); | ||
// register the hook | ||
this._state.stats.hooks++; | ||
// updating the hook information | ||
getHookStatus(hook, hookExecutable, hookStep); | ||
hookStep.endStep(); | ||
return; | ||
} | ||
if (hook.error) { | ||
// add hook as test to suite for mocha all hooks, when it didn't start before | ||
if (disableMochaHooks && isMochaAllHook) { | ||
this.onTestStart(hook); | ||
/**** | ||
* if the hook is not before/after from mocha/jasmine (custom hook) and useCucumberStepReporter=false | ||
* Custom hooks are not affected by "disableMochaHooks" option | ||
*/ | ||
if (!(isAllHook || isEachHook) && !useCucumberStepReporter) { | ||
// getting the latest element | ||
const lastElement = this._state.pop(); | ||
if (lastElement) { | ||
const isCustomHook = lastElement instanceof AllureTest && | ||
lastElement.wrappedItem.name?.startsWith('hook:'); | ||
this._state.push(lastElement); | ||
if (isCustomHook) { | ||
// we end the test case (custom hook) that represents the custom hook call. | ||
this._endTest(getTestStatus(hook), hook.error); | ||
} | ||
} | ||
this.onTestFail(hook); | ||
// mocha doesn't fire onTestEnd for failed beforeEach hook | ||
// we have to force mark test as failed test | ||
if (isMochaBeforeEachHook(hook.title) && !disableMochaHooks) { | ||
this.onTestFail(Object.assign({}, hook, { title: hook.currentTest })); | ||
} | ||
return; | ||
} | ||
this.onTestPass(); | ||
if (useCucumberStepReporter) { | ||
// remove hook from suite if it has no steps or attachments | ||
const currentItem = this._state.currentAllureTestOrStep?.wrappedItem; | ||
/**** | ||
* if the hook comes from Cucumber useCucumberStepReporter=true | ||
*/ | ||
if (useCucumberStepReporter && !disableMochaHooks) { | ||
// closing the cucumber hook (in this case, it's reported as a step) | ||
hook.error ? this.onTestFail(hook) : this.onTestPass(); | ||
// remove cucumber hook (reported as a step) from a suite if it has no steps or attachments. | ||
const currentItem = this._state.currentAllureStepableEntity?.wrappedItem; | ||
if (currentItem) { | ||
const currentStep = currentItem.steps[currentItem.steps.length - 1]; | ||
if (currentStep.steps.length === 0 && currentStep.attachments.length === 0 && currentItem.attachments.length === 0) { | ||
currentItem.steps.pop(); | ||
} | ||
cleanCucumberHooks(currentItem); | ||
} | ||
return; | ||
} | ||
@@ -569,3 +653,3 @@ } | ||
addAttachment({ name, content, type = ContentType.TEXT }) { | ||
if (!this._state.currentTest) { | ||
if (!this._state.currentAllureStepableEntity) { | ||
return; | ||
@@ -580,3 +664,3 @@ } | ||
startStep(title) { | ||
if (!this._state.currentAllureTestOrStep) { | ||
if (!this._state.currentAllureStepableEntity) { | ||
return; | ||
@@ -587,3 +671,3 @@ } | ||
endStep(status) { | ||
if (!this._state.currentAllureTestOrStep) { | ||
if (!this._state.currentAllureStepableEntity) { | ||
return; | ||
@@ -594,3 +678,3 @@ } | ||
addStep({ step }) { | ||
if (!this._state.currentAllureTestOrStep) { | ||
if (!this._state.currentAllureStepableEntity) { | ||
return; | ||
@@ -611,3 +695,3 @@ } | ||
addAllureStep(metadata) { | ||
const { currentAllureTestOrStep: currentAllureSpec } = this._state; | ||
const { currentAllureStepableEntity: currentAllureSpec } = this._state; | ||
if (!currentAllureSpec) { | ||
@@ -614,0 +698,0 @@ throw new Error("Couldn't add step: no test case running!"); |
@@ -1,13 +0,20 @@ | ||
import { AllureGroup, AllureTest, AllureStep } from 'allure-js-commons'; | ||
import { AllureGroup, AllureTest, AllureStep, ExecutableItemWrapper } from 'allure-js-commons'; | ||
import type { AllureStepableUnit } from './types.js'; | ||
export declare class AllureReporterState { | ||
currentFile?: string; | ||
runningUnits: Array<AllureGroup | AllureTest | AllureStep>; | ||
runningUnits: Array<AllureGroup | AllureStepableUnit>; | ||
stats: { | ||
test: number; | ||
hooks: number; | ||
suites: number; | ||
}; | ||
get currentSuite(): AllureGroup | undefined; | ||
get currentTest(): AllureTest | undefined; | ||
get currentStep(): AllureStep | undefined; | ||
get currentAllureTestOrStep(): AllureTest | AllureStep | undefined; | ||
get currentHook(): ExecutableItemWrapper | undefined; | ||
get currentAllureStepableEntity(): AllureStepableUnit | undefined; | ||
get currentPackageLabel(): string | undefined; | ||
push(unit: AllureGroup | AllureTest | AllureStep): void; | ||
pop(): AllureGroup | AllureTest | AllureStep | undefined; | ||
push(unit: AllureGroup | AllureStepableUnit): void; | ||
pop(): AllureGroup | AllureStepableUnit | undefined; | ||
} | ||
//# sourceMappingURL=state.d.ts.map |
import { sep } from 'node:path'; | ||
import { AllureGroup, AllureTest, AllureStep } from 'allure-js-commons'; | ||
import { AllureGroup, AllureTest, AllureStep, ExecutableItemWrapper } from 'allure-js-commons'; | ||
import { findLast } from './utils.js'; | ||
@@ -7,2 +7,3 @@ export class AllureReporterState { | ||
runningUnits = []; | ||
stats = { test: 0, hooks: 0, suites: 0 }; | ||
get currentSuite() { | ||
@@ -17,5 +18,8 @@ return findLast(this.runningUnits, (unit) => unit instanceof AllureGroup); | ||
} | ||
get currentAllureTestOrStep() { | ||
return findLast(this.runningUnits, (unit) => unit instanceof AllureTest || unit instanceof AllureStep); | ||
get currentHook() { | ||
return findLast(this.runningUnits, (unit) => unit instanceof ExecutableItemWrapper); | ||
} | ||
get currentAllureStepableEntity() { | ||
return findLast(this.runningUnits, (unit) => unit instanceof AllureTest || unit instanceof AllureStep || unit instanceof ExecutableItemWrapper); | ||
} | ||
get currentPackageLabel() { | ||
@@ -28,2 +32,11 @@ if (!this.currentFile) { | ||
push(unit) { | ||
if (unit instanceof AllureGroup) { | ||
this.stats.suites++; | ||
} | ||
else if (unit instanceof AllureTest) { | ||
this.stats.test++; | ||
} | ||
else { | ||
this.stats.hooks++; | ||
} | ||
this.runningUnits.push(unit); | ||
@@ -30,0 +43,0 @@ } |
@@ -0,1 +1,2 @@ | ||
import type { AllureStep, AllureTest, ExecutableItemWrapper } from 'allure-js-commons'; | ||
/** | ||
@@ -126,2 +127,3 @@ * When you add a new option, please also update the docs at ./packages/wdio-allure-reporter/README.md | ||
} | ||
export type AllureStepableUnit = AllureTest | AllureStep | ExecutableItemWrapper; | ||
declare global { | ||
@@ -128,0 +130,0 @@ namespace WebdriverIO { |
import type { HookStats, TestStats, SuiteStats, CommandArgs } from '@wdio/reporter'; | ||
import type { Options } from '@wdio/types'; | ||
import type { Label, AllureTest, AllureGroup } from 'allure-js-commons'; | ||
import type { AllureGroup, AllureStep, AllureTest, ExecutableItemWrapper, FixtureResult, Label, TestResult } from 'allure-js-commons'; | ||
import { Status as AllureStatus } from 'allure-js-commons'; | ||
@@ -20,3 +20,3 @@ import CompoundError from './compoundError.js'; | ||
/** | ||
* Is mocha beforeEach hook | ||
* Is mocha/jasmine beforeEach hook | ||
* @param title {String} - hook title | ||
@@ -26,5 +26,5 @@ * @returns {boolean} | ||
*/ | ||
export declare const isMochaBeforeEachHook: (title: string) => boolean; | ||
export declare const isBeforeEachTypeHook: (title: string) => boolean; | ||
/** | ||
* Is mocha beforeEach / afterEach hook | ||
* Is mocha/jasmine beforeAll / beforeEach hook | ||
* @param title {String} - hook title | ||
@@ -34,5 +34,5 @@ * @returns {boolean} | ||
*/ | ||
export declare const isMochaEachHooks: (title: string) => boolean; | ||
export declare const isBeforeTypeHook: (title: string) => boolean; | ||
/** | ||
* Is mocha beforeAll / afterAll hook | ||
* Is mocha/jasmine beforeEach / afterEach hook | ||
* @param title {String} - hook title | ||
@@ -42,4 +42,11 @@ * @returns {boolean} | ||
*/ | ||
export declare const isMochaAllHooks: (title: string) => boolean; | ||
export declare const isEachTypeHooks: (title: string) => boolean; | ||
/** | ||
* Is mocha/jasmine beforeAll / afterAll hook | ||
* @param title {String} - hook title | ||
* @returns {boolean} | ||
* @private | ||
*/ | ||
export declare const isAllTypeHooks: (title: string) => boolean; | ||
/** | ||
* Properly format error from different test runners | ||
@@ -52,2 +59,12 @@ * @param {object} test - TestStat object | ||
/** | ||
* Update the hook information with the new one, it could be use when a hook ends | ||
* @param {HookStats} newHookStats - New information that will be applied to current hook info | ||
* @param {ExecutableItemWrapper} hookElement - hook element registered in the report | ||
* @param {AllureStep} hookRootStep - root hook step | ||
* | ||
* @private | ||
*/ | ||
export declare const getHookStatus: (newHookStats: HookStats, hookElement: ExecutableItemWrapper, hookRootStep: AllureStep) => void; | ||
export declare const cleanCucumberHooks: (hook: FixtureResult | TestResult) => void; | ||
/** | ||
* Substitute task id to link template | ||
@@ -54,0 +71,0 @@ * @param {string} template - link template |
import stripAnsi from 'strip-ansi'; | ||
import { Status as AllureStatus, md5, LabelName } from 'allure-js-commons'; | ||
import { LabelName, md5, Stage, Status, Status as AllureStatus } from 'allure-js-commons'; | ||
import CompoundError from './compoundError.js'; | ||
import { mochaEachHooks, mochaAllHooks, linkPlaceholder } from './constants.js'; | ||
import { allHooks, eachHooks, linkPlaceholder } from './constants.js'; | ||
/** | ||
@@ -31,2 +31,5 @@ * Get allure test status by TestStat object | ||
} | ||
else if (test.errors) { | ||
return AllureStatus.FAILED; | ||
} | ||
return AllureStatus.BROKEN; | ||
@@ -41,3 +44,3 @@ }; | ||
/** | ||
* Is mocha beforeEach hook | ||
* Is mocha/jasmine beforeEach hook | ||
* @param title {String} - hook title | ||
@@ -47,5 +50,5 @@ * @returns {boolean} | ||
*/ | ||
export const isMochaBeforeEachHook = (title) => title.includes(mochaEachHooks[0]); | ||
export const isBeforeEachTypeHook = (title) => title.includes(eachHooks[0]); | ||
/** | ||
* Is mocha beforeEach / afterEach hook | ||
* Is mocha/jasmine beforeAll / beforeEach hook | ||
* @param title {String} - hook title | ||
@@ -55,5 +58,5 @@ * @returns {boolean} | ||
*/ | ||
export const isMochaEachHooks = (title) => mochaEachHooks.some((hook) => title.includes(hook)); | ||
export const isBeforeTypeHook = (title) => title.includes(allHooks[0]) || title.includes(eachHooks[0]); | ||
/** | ||
* Is mocha beforeAll / afterAll hook | ||
* Is mocha/jasmine beforeEach / afterEach hook | ||
* @param title {String} - hook title | ||
@@ -63,4 +66,11 @@ * @returns {boolean} | ||
*/ | ||
export const isMochaAllHooks = (title) => mochaAllHooks.some((hook) => title.includes(hook)); | ||
export const isEachTypeHooks = (title) => eachHooks.some((hook) => title.includes(hook)); | ||
/** | ||
* Is mocha/jasmine beforeAll / afterAll hook | ||
* @param title {String} - hook title | ||
* @returns {boolean} | ||
* @private | ||
*/ | ||
export const isAllTypeHooks = (title) => allHooks.some((hook) => title.includes(hook)); | ||
/** | ||
* Properly format error from different test runners | ||
@@ -72,3 +82,3 @@ * @param {object} test - TestStat object | ||
export const getErrorFromFailedTest = (test) => { | ||
if (test.errors && Array.isArray(test.errors)) { | ||
if (test.errors && Array.isArray(test.errors) && test.errors.length) { | ||
for (let i = 0; i < test.errors.length; i += 1) { | ||
@@ -97,2 +107,51 @@ if (test.errors[i].message) { | ||
/** | ||
* Update the hook information with the new one, it could be use when a hook ends | ||
* @param {HookStats} newHookStats - New information that will be applied to current hook info | ||
* @param {ExecutableItemWrapper} hookElement - hook element registered in the report | ||
* @param {AllureStep} hookRootStep - root hook step | ||
* | ||
* @private | ||
*/ | ||
export const getHookStatus = (newHookStats, hookElement, hookRootStep) => { | ||
// stage to finish for all hook. | ||
hookElement.stage = hookRootStep.stage = | ||
Stage.FINISHED; | ||
// set error detail information | ||
const formattedError = getErrorFromFailedTest(newHookStats); | ||
hookElement.detailsMessage = hookRootStep.detailsMessage = formattedError?.message; | ||
hookElement.detailsTrace = hookRootStep.detailsTrace = formattedError?.stack; | ||
let finalStatus = Status.PASSED; | ||
// set status to hook root step | ||
const hookSteps = hookRootStep.wrappedItem.steps; | ||
if (Array.isArray(hookSteps) && hookSteps.length) { | ||
const statusPriority = { | ||
[Status.FAILED]: 0, | ||
[Status.BROKEN]: 1, | ||
[Status.SKIPPED]: 2, | ||
[Status.PASSED]: 3, | ||
}; | ||
let stepStatus = Status.PASSED; | ||
for (const step of hookSteps) { | ||
if (step.status && statusPriority[step.status] < statusPriority[finalStatus]) { | ||
stepStatus = step.status; | ||
} | ||
} | ||
finalStatus = stepStatus === Status.FAILED ? Status.BROKEN : stepStatus; | ||
} | ||
else if (newHookStats.error || (Array.isArray(newHookStats.errors) && newHookStats.errors.length)) { | ||
finalStatus = Status.BROKEN; | ||
} | ||
hookElement.status = hookRootStep.status = finalStatus; | ||
}; | ||
export const cleanCucumberHooks = (hook) => { | ||
const currentStep = hook.steps[hook.steps.length - 1]; | ||
if (currentStep && | ||
currentStep.steps.length === 0 && | ||
currentStep.attachments.length === 0 && | ||
hook.attachments.length === 0 && | ||
currentStep.status === Status.PASSED) { | ||
hook.steps.pop(); | ||
} | ||
}; | ||
/** | ||
* Substitute task id to link template | ||
@@ -99,0 +158,0 @@ * @param {string} template - link template |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.linkPlaceholder = exports.mochaAllHooks = exports.mochaEachHooks = exports.events = void 0; | ||
exports.linkPlaceholder = exports.allHooks = exports.eachHooks = exports.events = void 0; | ||
exports.events = { | ||
@@ -27,4 +27,4 @@ addLabel: 'allure:addLabel', | ||
}; | ||
exports.mochaEachHooks = ['"before each" hook', '"after each" hook']; | ||
exports.mochaAllHooks = ['"before all" hook', '"after all" hook']; | ||
exports.eachHooks = ['"before each" hook', '"after each" hook']; | ||
exports.allHooks = ['"before all" hook', '"after all" hook']; | ||
exports.linkPlaceholder = '{}'; |
{ | ||
"name": "@wdio/allure-reporter", | ||
"version": "8.36.1", | ||
"version": "8.37.0", | ||
"description": "A WebdriverIO reporter plugin to create Allure Test Reports", | ||
@@ -43,4 +43,4 @@ "author": "Boris Osipov <osipov.boris@gmail.com>", | ||
"@types/node": "^20.1.0", | ||
"@wdio/reporter": "8.36.1", | ||
"@wdio/types": "8.36.1", | ||
"@wdio/reporter": "8.37.0", | ||
"@wdio/types": "8.37.0", | ||
"allure-js-commons": "^2.5.0", | ||
@@ -53,3 +53,3 @@ "csv-stringify": "^6.0.4", | ||
}, | ||
"gitHead": "6c4a9745052c29d13b73ac622dfda387c884ffd8" | ||
"gitHead": "cefb415aa315075fb6b682c6d059d9ff37fbefb8" | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
100719
2113
47
+ Added@wdio/reporter@8.37.0(transitive)
+ Added@wdio/types@8.37.0(transitive)
- Removed@wdio/reporter@8.36.1(transitive)
- Removed@wdio/types@8.36.1(transitive)
Updated@wdio/reporter@8.37.0
Updated@wdio/types@8.37.0