diff --git a/packages/library/src/constants.ts b/packages/library/src/constants.ts index a6d4d29..9d519e8 100644 --- a/packages/library/src/constants.ts +++ b/packages/library/src/constants.ts @@ -1,6 +1,6 @@ export const PREFIX = 'allure2' as const; -export const $POINTER = [PREFIX, '$pointer'] as const; +export const CURRENT_STEP = [PREFIX, 'currentStep'] as const; export const DESCRIPTION = [PREFIX, 'description'] as const; export const DESCRIPTION_HTML = [PREFIX, 'descriptionHtml'] as const; export const LABELS = [PREFIX, 'labels'] as const; diff --git a/packages/library/src/environment/decorator.ts b/packages/library/src/environment/decorator.ts index d765b81..de83e16 100644 --- a/packages/library/src/environment/decorator.ts +++ b/packages/library/src/environment/decorator.ts @@ -10,7 +10,7 @@ import { Stage, Status } from '@noomorph/allure-js-commons'; import type { AllureTestCaseMetadata, AllureTestStepMetadata, -} from '../runtime'; +} from '../metadata'; import { PREFIX } from '../constants'; import { AllureRuntime } from '../runtime'; @@ -67,7 +67,7 @@ export function WithAllure2( }: ForwardedCircusEvent) { const metadata: AllureTestCaseMetadata = { stage: Stage.SCHEDULED, - code: event.fn.toString(), + code: [event.fn.toString()], }; state.currentMetadata.assign(PREFIX, metadata); diff --git a/packages/library/src/metadata/MetadataSquasher.ts b/packages/library/src/metadata/MetadataSquasher.ts new file mode 100644 index 0000000..5ab1e98 --- /dev/null +++ b/packages/library/src/metadata/MetadataSquasher.ts @@ -0,0 +1,102 @@ +import type { + AggregatedResultMetadata, + DescribeBlockMetadata, + RunMetadata, + TestEntryMetadata, + TestFnInvocationMetadata, + TestInvocationMetadata, +} from 'jest-metadata'; + +import { PREFIX } from '../constants'; + +import { chain, extractCode, getStart, getStop } from './utils'; +import type { AllureTestCaseMetadata } from './metadata'; + +export class MetadataSquasher { + protected readonly testInvocationConfig: MetadataSquasherConfig; + + constructor(flat: boolean) { + this.testInvocationConfig = flat + ? MetadataSquasher.flatConfig() + : MetadataSquasher.deepConfig(); + } + + testInvocation(metadata: TestInvocationMetadata): AllureTestCaseMetadata { + const config = this.testInvocationConfig as any; + const keys = Object.keys(config) as (keyof AllureTestCaseMetadata)[]; + const result: Partial = {}; + const context = { + aggregatedResult: metadata.entry.describeBlock.run.aggregatedResult, + run: metadata.entry.describeBlock.run, + describeBlock: [...metadata.entry.ancestors()], + testEntry: metadata.entry, + testInvocation: metadata, + testFnInvocation: metadata.fn, + }; + + for (const key of keys) { + result[key] = config[key](context, key); + } + + return result as AllureTestCaseMetadata; + } + + private static flatConfig(): MetadataSquasherConfig { + return { + code: extractCode, + workerId: ({ run }) => run?.get([PREFIX, 'workerId']) as string, + description: chain(['testEntry', 'testInvocation', 'testFnInvocation']), + descriptionHtml: chain([ + 'testEntry', + 'testInvocation', + 'testFnInvocation', + ]), + attachments: chain(['testEntry', 'testInvocation', 'testFnInvocation']), + parameters: chain(['testEntry', 'testInvocation', 'testFnInvocation']), + labels: chain([ + 'aggregatedResult', + 'run', + 'describeBlock', + 'testEntry', + 'testInvocation', + 'testFnInvocation', + ]), + links: chain([ + 'aggregatedResult', + 'run', + 'describeBlock', + 'testEntry', + 'testInvocation', + 'testFnInvocation', + ]), + start: getStart, + stop: getStop, + }; + } + + private static deepConfig(): MetadataSquasherConfig { + return { + ...this.flatConfig(), + attachments: chain(['testEntry', 'testInvocation']), + parameters: chain(['testEntry', 'testInvocation']), + }; + } +} + +export type MetadataSquasherConfig = { + [K in keyof T]: MetadataSquasherMapping; +}; + +export type MetadataSquasherMapping = ( + context: MetadataSquasherContext, + key: K, +) => T[K]; + +export type MetadataSquasherContext = Partial<{ + aggregatedResult: AggregatedResultMetadata; + run: RunMetadata; + describeBlock: DescribeBlockMetadata[]; + testEntry: TestEntryMetadata; + testInvocation: TestInvocationMetadata; + testFnInvocation: TestFnInvocationMetadata; +}>; diff --git a/packages/library/src/metadata/StepExtractor.ts b/packages/library/src/metadata/StepExtractor.ts new file mode 100644 index 0000000..e296cd0 --- /dev/null +++ b/packages/library/src/metadata/StepExtractor.ts @@ -0,0 +1,44 @@ +import type { + HookInvocationMetadata, + TestFnInvocationMetadata, +} from 'jest-metadata'; + +import { PREFIX } from '../constants'; + +import type { AllureTestStepMetadata } from './metadata'; + +export class StepExtractor { + constructor(protected readonly flat: boolean) {} + + public extractFromHook( + metadata: HookInvocationMetadata, + ): AllureTestStepMetadata { + const data = { + name: metadata.definition.hookType, + ...(metadata.get([PREFIX]) as AllureTestStepMetadata), + }; + + if (this.flat) { + delete data.attachments; + delete data.parameters; + } + + return data; + } + + public extractFromTestFn( + metadata: TestFnInvocationMetadata, + ): AllureTestStepMetadata { + const data = { + name: 'test', + ...(metadata.get([PREFIX]) as AllureTestStepMetadata), + }; + + if (this.flat) { + delete data.attachments; + delete data.parameters; + } + + return data; + } +} diff --git a/packages/library/src/metadata/index.ts b/packages/library/src/metadata/index.ts new file mode 100644 index 0000000..94ed2e9 --- /dev/null +++ b/packages/library/src/metadata/index.ts @@ -0,0 +1,3 @@ +export * from './metadata'; +export * from './MetadataSquasher'; +export * from './StepExtractor'; diff --git a/packages/library/src/runtime/metadata.ts b/packages/library/src/metadata/metadata.ts similarity index 78% rename from packages/library/src/runtime/metadata.ts rename to packages/library/src/metadata/metadata.ts index 5c02884..640cfa0 100644 --- a/packages/library/src/runtime/metadata.ts +++ b/packages/library/src/metadata/metadata.ts @@ -12,7 +12,6 @@ export interface AllureTestStepMetadata { steps?: AllureTestStepMetadata[]; name?: string; - code?: string; status?: Status; statusDetails?: StatusDetails; stage?: Stage; @@ -28,14 +27,17 @@ export interface AllureTestCaseMetadata extends AllureTestStepMetadata { * @example ['steps', '0', 'steps', '0'] * @internal */ - $pointer?: string[]; + currentStep?: string[]; /** * Jest worker ID. * @internal Used to generate unique thread names. - * @see {LabelName.THREAD} + * @see {import('@noomorph/allure-js-commons').LabelName.THREAD} */ - $workerId?: string; - + workerId?: string; + /** + * Source code of the test case, glued from all hooks and test function itself. + */ + code?: string[]; /** * Only steps can have names. */ diff --git a/packages/library/src/metadata/utils/chain.ts b/packages/library/src/metadata/utils/chain.ts new file mode 100644 index 0000000..9f23b49 --- /dev/null +++ b/packages/library/src/metadata/utils/chain.ts @@ -0,0 +1,22 @@ +import type { Metadata } from 'jest-metadata'; + +import { PREFIX } from '../../constants'; +import type { + MetadataSquasherContext, + MetadataSquasherMapping, +} from '../MetadataSquasher'; + +export function chain( + sources: (keyof MetadataSquasherContext)[], +): MetadataSquasherMapping { + return (context: MetadataSquasherContext, key: K) => { + const path = [PREFIX, key as string]; + const metadatas: Metadata[] = sources.flatMap((sourceName) => { + const value: Metadata | Metadata[] | undefined = context[sourceName]; + if (!value) return []; + return Array.isArray(value) ? value : [value]; + }); + + return metadatas.flatMap((metadata) => metadata.get(path, [])) as T[K]; + }; +} diff --git a/packages/library/src/metadata/utils/extractCode.ts b/packages/library/src/metadata/utils/extractCode.ts new file mode 100644 index 0000000..6374526 --- /dev/null +++ b/packages/library/src/metadata/utils/extractCode.ts @@ -0,0 +1,29 @@ +import type { HookInvocationMetadata } from 'jest-metadata'; +import type { Metadata } from 'jest-metadata'; + +import type { MetadataSquasherMapping } from '../MetadataSquasher'; +import type { AllureTestCaseMetadata } from '../metadata'; + +export const extractCode: MetadataSquasherMapping< + AllureTestCaseMetadata, + 'code' +> = ({ testInvocation }) => { + if (!testInvocation) return []; + + const getHookDefinition = (metadata: HookInvocationMetadata) => + metadata.definition; + const getCode = (functionName: string) => (metadata: Metadata) => { + const code = metadata.get(['allure2', 'code']); + return code ? `${functionName}(${code})` : ''; + }; + + return [ + ...testInvocation.beforeAll + .map(getHookDefinition) + .map(getCode('beforeAll')), + ...testInvocation.before.map(getHookDefinition).map(getCode('beforeEach')), + getCode('test')(testInvocation.entry), + ...testInvocation.after.map(getHookDefinition).map(getCode('afterEach')), + ...testInvocation.afterAll.map(getHookDefinition).map(getCode('afterAll')), + ].filter(Boolean); +}; diff --git a/packages/library/src/metadata/utils/getStart.ts b/packages/library/src/metadata/utils/getStart.ts new file mode 100644 index 0000000..9abc355 --- /dev/null +++ b/packages/library/src/metadata/utils/getStart.ts @@ -0,0 +1,16 @@ +import type { MetadataSquasherMapping } from '../MetadataSquasher'; +import type { AllureTestCaseMetadata } from '../metadata'; + +export const getStart: MetadataSquasherMapping< + AllureTestCaseMetadata, + 'start' +> = ({ testEntry, testInvocation }) => { + const first = + (testInvocation && + (testInvocation.beforeAll[0] ?? + testInvocation.before[0] ?? + testInvocation.fn)) ?? + testEntry; + + return (first?.get(['allure2', 'start']) as number) ?? Number.NaN; +}; diff --git a/packages/library/src/metadata/utils/getStop.ts b/packages/library/src/metadata/utils/getStop.ts new file mode 100644 index 0000000..952ba3e --- /dev/null +++ b/packages/library/src/metadata/utils/getStop.ts @@ -0,0 +1,18 @@ +import type { MetadataSquasherMapping } from '../MetadataSquasher'; +import type { AllureTestCaseMetadata } from '../metadata'; +import { PREFIX } from '../../constants'; + +export const getStop: MetadataSquasherMapping< + AllureTestCaseMetadata, + 'stop' +> = ({ testEntry, testInvocation }) => { + const last = + (testInvocation && + (testInvocation.afterAll.at(-1) ?? + testInvocation.after.at(-1) ?? + testInvocation.fn)) ?? + testEntry; + + const stop: number = (last?.get([PREFIX, 'stop']) as number); + return stop; +}; diff --git a/packages/library/src/metadata/utils/index.ts b/packages/library/src/metadata/utils/index.ts new file mode 100644 index 0000000..13ebde6 --- /dev/null +++ b/packages/library/src/metadata/utils/index.ts @@ -0,0 +1,4 @@ +export * from './chain'; +export * from './extractCode'; +export * from './getStart'; +export * from './getStop'; diff --git a/packages/library/src/options/ReporterOptions.ts b/packages/library/src/options/ReporterOptions.ts index 7dddff0..af9b901 100644 --- a/packages/library/src/options/ReporterOptions.ts +++ b/packages/library/src/options/ReporterOptions.ts @@ -15,7 +15,7 @@ import type { Config } from '@jest/reporters'; import type { AllureTestCaseMetadata, AllureTestStepMetadata, -} from '../runtime'; +} from '../metadata'; /** * Configuration options for the `jest-allure2-reporter` package. @@ -61,9 +61,13 @@ export type ReporterOptions = { */ resultsDir?: string; /** - * Configures globally how test cases are reported: names, descriptions, labels, status, etc. + * Customize how test cases are reported: names, descriptions, labels, status, etc. */ testCase?: Partial; + /** + * Customize how individual test steps are reported. + */ + testStep?: Partial; /** * Configures the environment information that will be reported. */ @@ -86,6 +90,7 @@ export type ReporterOptions = { export type ReporterConfig = Required & { testCase: ResolvedTestCaseCustomizer; + testStep: ResolvedTestStepCustomizer; }; /** @@ -119,20 +124,20 @@ export interface TestCaseCustomizer { * @example ({ testCaseMetadata }) => '
' + testCaseMetadata.code + '
' */ descriptionHtml: TestCaseExtractor; + /** + * Extractor for the test case stage. + */ + stage: TestCaseExtractor; /** * Extractor for the test case status. * @see https://wix-incubator.github.io/jest-allure2-reporter/docs/config/statuses/ * @example ({ value }) => value === 'broken' ? 'failed' : value */ - status: TestCaseExtractor; + status: TestCaseExtractor; /** * Extractor for the test case status details. */ statusDetails: TestCaseExtractor; - /** - * Customize step details for the test case. - */ - steps: Partial; /** * Customize Allure labels for the test case. * @@ -167,21 +172,22 @@ export interface TestCaseCustomizer { } export type ResolvedTestCaseCustomizer = Required & { - steps: Required; labels: TestCaseExtractor; links: TestCaseExtractor; }; +export type ResolvedTestStepCustomizer = Required; + export interface TestStepCustomizer { /** * Extractor for the step name. - * @example ({ testStep }) => ['beforeEach', 'afterEach'].includes(testStep.name) ? testStep.name.replace('Each', ' each') : testStep.name + * @example ({ value }) => value.replace(/(before|after)(Each|All)/, (_, p1, p2) => p1 + ' ' + p2.toLowerCase()) */ name: TestStepExtractor; /** * Extractor for the test step stage. * @see https://wix-incubator.github.io/jest-allure2-reporter/docs/config/statuses/ - * @example ({ value }) => value === 'broken' ? 'failed' : value + * TODO: add example */ stage: TestStepExtractor; /** @@ -280,6 +286,6 @@ export interface TestStepExtractorContext // TODO: improve typings (less never patches, please) export type AllureTestStepContext = AllureTestStepMetadata & { - $pointer: readonly string[]; + currentStep: readonly string[]; steps: never; }; diff --git a/packages/library/src/options/composeOptions.ts b/packages/library/src/options/composeOptions.ts index 1a97a31..17cd0f6 100644 --- a/packages/library/src/options/composeOptions.ts +++ b/packages/library/src/options/composeOptions.ts @@ -23,6 +23,10 @@ export function composeOptions( overwrite: custom.overwrite ?? base.overwrite, resultsDir: custom.resultsDir ?? base.resultsDir, testCase: composeTestCaseCustomizers(base.testCase, custom.testCase), + testStep: composeTestStepCustomizers( + base.testStep as TestStepCustomizer, + custom.testStep, + ), environment: composeExtractors(custom.environment, base.environment), executor: composeExtractors(custom.executor, base.executor), categories: composeExtractors(custom.categories, base.categories), @@ -46,14 +50,11 @@ function composeTestCaseCustomizers( custom.descriptionHtml, base.descriptionHtml, ), + stage: composeExtractors(custom.stage, base.stage), status: composeExtractors(custom.status, base.status), statusDetails: composeExtractors(custom.statusDetails, base.statusDetails), attachments: composeExtractors(custom.attachments, base.attachments), parameters: composeExtractors(custom.parameters, base.parameters), - steps: composeTestStepCustomizers( - base.steps as TestStepCustomizer, - custom.steps, - ), labels: composeExtractors( aggregateLabelCustomizers(custom.labels), base.labels, diff --git a/packages/library/src/options/defaultOptions.ts b/packages/library/src/options/defaultOptions.ts index f4148c0..4eb0017 100644 --- a/packages/library/src/options/defaultOptions.ts +++ b/packages/library/src/options/defaultOptions.ts @@ -1,18 +1,19 @@ import path from 'node:path'; import type { TestCaseResult } from '@jest/reporters'; -import type { Status, StatusDetails } from '@noomorph/allure-js-commons'; +import type { StatusDetails } from '@noomorph/allure-js-commons'; +import { Stage, Status } from '@noomorph/allure-js-commons'; import type { ExtractorContext, ReporterConfig, ResolvedTestCaseCustomizer, + ResolvedTestStepCustomizer, } from './ReporterOptions'; import { aggregateLabelCustomizers } from './aggregateLabelCustomizers'; const identity = (context: ExtractorContext) => context.value; -const last = (context: ExtractorContext) => - context.value?.[context.value.length - 1]; +const last = (context: ExtractorContext) => context.value?.at(-1); const all = identity; export function defaultOptions(): ReporterConfig { @@ -24,18 +25,11 @@ export function defaultOptions(): ReporterConfig { return '```javascript\n' + testCaseMetadata.code + '\n```'; }, descriptionHtml: () => void 0, + stage: ({ testCase }) => getTestCaseStage(testCase), status: ({ testCase }) => getTestCaseStatus(testCase), statusDetails: ({ testCase }) => getTestCaseStatusDetails(testCase), attachments: ({ testCaseMetadata }) => testCaseMetadata.attachments, parameters: ({ testCaseMetadata }) => testCaseMetadata.parameters, - steps: { - name: ({ testStep }) => testStep.name, - stage: ({ testStep }) => testStep.stage, - status: ({ testStep }) => testStep.status, - statusDetails: ({ testStep }) => testStep.statusDetails, - attachments: ({ testStep }) => testStep.attachments, - parameters: ({ testStep }) => testStep.parameters, - }, labels: aggregateLabelCustomizers({ package: last, testClass: last, @@ -47,7 +41,7 @@ export function defaultOptions(): ReporterConfig { epic: all, feature: all, story: all, - thread: ({ testCaseMetadata }) => testCaseMetadata.$workerId, + thread: ({ testCaseMetadata }) => testCaseMetadata.workerId, severity: last, tag: all, owner: last, @@ -55,35 +49,68 @@ export function defaultOptions(): ReporterConfig { links: all, }; + const testStep: ResolvedTestStepCustomizer = { + name: ({ testStep }) => testStep.name, + stage: ({ testStep }) => testStep.stage, + status: ({ testStep }) => testStep.status, + statusDetails: ({ testStep }) => testStep.statusDetails, + attachments: ({ testStep }) => testStep.attachments, + parameters: ({ testStep }) => testStep.parameters, + }; + return { overwrite: true, resultsDir: 'allure-results', testCase, + testStep, environment: identity, executor: identity, categories: identity, }; } -function getTestCaseStatus(testCase: TestCaseResult): Status[keyof Status] { +function getTestCaseStatus(testCase: TestCaseResult): Status { const hasErrors = testCase.failureMessages?.length > 0; // TODO: Add support for 'broken' status switch (testCase.status) { - case 'passed': - case 'failed': + case 'passed': { + return Status.PASSED; + } + case 'failed': { + return Status.FAILED; + } case 'skipped': { - return testCase.status; + return Status.SKIPPED; } case 'pending': case 'todo': case 'disabled': { - return 'skipped'; + return Status.SKIPPED; } case 'focused': { - return hasErrors ? 'failed' : 'passed'; + return hasErrors ? Status.FAILED : Status.PASSED; + } + default: { + return 'unknown' as Status; + } + } +} + +function getTestCaseStage(testCase: TestCaseResult): Stage { + switch (testCase.status) { + case 'passed': + case 'focused': + case 'failed': { + return Stage.FINISHED; + } + case 'todo': + case 'disabled': + case 'pending': + case 'skipped': { + return Stage.PENDING; } default: { - return 'unknown'; + return Stage.INTERRUPTED; } } } diff --git a/packages/library/src/options/resolveOptions.ts b/packages/library/src/options/resolveOptions.ts index 25fd428..01f6e06 100644 --- a/packages/library/src/options/resolveOptions.ts +++ b/packages/library/src/options/resolveOptions.ts @@ -1,7 +1,4 @@ -import type { - ReporterOptions, - ReporterConfig, -} from './ReporterOptions'; +import type { ReporterOptions, ReporterConfig } from './ReporterOptions'; import { composeOptions } from './composeOptions'; import { defaultOptions } from './defaultOptions'; diff --git a/packages/library/src/reporter/JestAllure2Reporter.ts b/packages/library/src/reporter/JestAllure2Reporter.ts index 7c6e096..e572307 100644 --- a/packages/library/src/reporter/JestAllure2Reporter.ts +++ b/packages/library/src/reporter/JestAllure2Reporter.ts @@ -6,8 +6,11 @@ import type { } from '@jest/reporters'; import { JestMetadataReporter, query } from 'jest-metadata/reporter'; import rimraf from 'rimraf'; -import type { ExecutableItemWrapper } from '@noomorph/allure-js-commons'; -import { AllureRuntime } from '@noomorph/allure-js-commons'; +import type { + ExecutableItemWrapper, + Status, +} from '@noomorph/allure-js-commons'; +import { AllureRuntime, Stage } from '@noomorph/allure-js-commons'; import type { TestContext } from '@jest/reporters'; import type { @@ -18,17 +21,12 @@ import type { TestStepExtractorContext, } from '../options/ReporterOptions'; import { resolveOptions } from '../options'; -import type { AllureTestCaseMetadata } from '../runtime'; +import type { AllureTestCaseMetadata } from '../metadata'; +import { MetadataSquasher, StepExtractor } from '../metadata'; const ns = (key?: keyof AllureTestCaseMetadata) => key ? ['allure2', key] : ['allure2']; -function flattenTestCaseMetadata( - _testCaseResult: TestCaseResult, -): AllureTestCaseMetadata { - return {} as any; // TODO: implement -} - function doBeforeMagic( _testCaseResult: TestCaseResult, ): TestStepExtractorContext[] { @@ -53,7 +51,7 @@ export class JestAllure2Reporter extends JestMetadataReporter { super.onTestFileStart(test); // TODO: use Thread service fallback - query.test(test).set(ns('$workerId'), '1'); + query.test(test).set(ns('workerId'), '1'); } onTestCaseResult(test: Test, testCaseResult: TestCaseResult) { @@ -107,16 +105,59 @@ export class JestAllure2Reporter extends JestMetadataReporter { allure.writeCategoriesDefinitions(categories); } + const squasher = new MetadataSquasher(true); + const stepper = new StepExtractor(true); + for (const testResult of results.testResults) { for (const testCaseResult of testResult.testResults) { - const testCaseContext: TestCaseExtractorContext = { - ...globalContext, - testFile: testResult, - testCase: testCaseResult, - testCaseMetadata: flattenTestCaseMetadata(testCaseResult), - }; + const allInvocations = query.testCaseResult(testCaseResult).invocations; + for (const invocationMetadata of allInvocations) { + const testCaseContext: TestCaseExtractorContext = { + ...globalContext, + testFile: testResult, + testCase: testCaseResult, + testCaseMetadata: squasher.testInvocation(invocationMetadata), + }; + + const invocationIndex = allInvocations.indexOf(invocationMetadata); + const groupName = `${testCaseResult.fullName} (${invocationIndex})`; + const allureGroup = allure.startGroup(groupName); + const allureTest = allureGroup.startTest( + config.testCase.name(testCaseContext), + testCaseContext.testCaseMetadata.start, + ); + allureTest.description = config.testCase.description(testCaseContext); + allureTest.descriptionHtml = + config.testCase.descriptionHtml(testCaseContext); + + allureTest.status = (config.testCase.status(testCaseContext) ?? + 'unknown') as Status; + allureTest.stage = (config.testCase.stage(testCaseContext) ?? + Stage.FINISHED) as Stage; + + for (const link of config.testCase.links(testCaseContext) ?? []) { + allureTest.addLink(link.url, link.name, link.type); + } + + for (const label of config.testCase.labels(testCaseContext) ?? []) { + allureTest.addLabel(label.name, label.value); + } + + const parameters = config.testCase.parameters(testCaseContext) ?? []; + for (const { name, value, ...options } of parameters) { + allureTest.addParameter(name, value, options); + } + + const attachments = + config.testCase.attachments(testCaseContext) ?? []; + for (const { name, source, type } of attachments) { + allureTest.addAttachment(name, type, source); + } + + allureTest.endTest(testCaseContext.testCaseMetadata.stop); + } - const customize: Required = config.testCase.steps; + const customize: Required = config.testStep; const foo = ( testStepContext: TestStepExtractorContext, allureStep: ExecutableItemWrapper, @@ -131,35 +172,8 @@ export class JestAllure2Reporter extends JestMetadataReporter { allureStep.statusDetails = customize.statusDetails(testStepContext) ?? allureStep.statusDetails; - - const parameters = customize.parameters(testStepContext) ?? []; - for (const { name, value, ...options } of parameters) { - allureStep.addParameter(name, value, options); - } - - const attachments = customize.attachments(testStepContext) ?? []; - for (const { name, source, type } of attachments) { - allureStep.addAttachment(name, type, source); - } }; - const allureGroup = allure.startGroup(testCaseResult.fullName); - const allureTest = allureGroup.startTest( - config.testCase.name(testCaseContext), - testCaseContext.testCaseMetadata.start, - ); - allureTest.description = config.testCase.description(testCaseContext); - allureTest.descriptionHtml = - config.testCase.descriptionHtml(testCaseContext); - - for (const link of config.testCase.links(testCaseContext) ?? []) { - allureTest.addLink(link.url, link.name, link.type); - } - - for (const label of config.testCase.labels(testCaseContext) ?? []) { - allureTest.addLabel(label.name, label.value); - } - for (const testStepContext of doBeforeMagic(testCaseResult)) { foo(testStepContext, allureGroup.addBefore()); } @@ -169,8 +183,6 @@ export class JestAllure2Reporter extends JestMetadataReporter { for (const testStepContext of doAfterMagic(testCaseResult)) { foo(testStepContext, allureGroup.addAfter()); } - - allureTest.endTest(testCaseContext.testCaseMetadata.stop); } } } diff --git a/packages/library/src/reporter/draft.txt b/packages/library/src/reporter/draft.txt index 8ca100b..4980483 100644 --- a/packages/library/src/reporter/draft.txt +++ b/packages/library/src/reporter/draft.txt @@ -103,7 +103,7 @@ aTest.addLabel(LabelName.SUB_SUITE, 'Sub-suite'); aTest.addLabel( LabelName.THREAD, - testEntry.describeBlock.run.get(ns('$workerId')) as string, + testEntry.describeBlock.run.get(ns('workerId')) as string, ); aTest.addLabel( LabelName.TEST_METHOD, diff --git a/packages/library/src/runtime/AllureRuntime.test.ts b/packages/library/src/runtime/AllureRuntime.test.ts index d67c1df..8bbf764 100644 --- a/packages/library/src/runtime/AllureRuntime.test.ts +++ b/packages/library/src/runtime/AllureRuntime.test.ts @@ -1,7 +1,7 @@ import { state } from 'jest-metadata'; -import { AllureRuntime } from './AllureRuntime'; import { PREFIX } from '../constants'; +import { AllureRuntime } from './AllureRuntime'; describe('AllureRuntime', () => { it('should add attachments within the steps', async () => { diff --git a/packages/library/src/runtime/AllureRuntime.ts b/packages/library/src/runtime/AllureRuntime.ts index 6d435d6..4fae314 100644 --- a/packages/library/src/runtime/AllureRuntime.ts +++ b/packages/library/src/runtime/AllureRuntime.ts @@ -9,7 +9,7 @@ import type { } from '@noomorph/allure-js-commons'; import { - $POINTER, + CURRENT_STEP, DESCRIPTION, DESCRIPTION_HTML, LABELS, @@ -17,8 +17,7 @@ import { PREFIX, } from '../constants'; import { isPromiseLike } from '../utils/isPromiseLike'; - -import type { AllureTestStepMetadata } from './metadata'; +import type { AllureTestStepMetadata } from '../metadata/metadata'; export type AllureRuntimeConfig = { metadataProvider: () => Metadata; @@ -160,7 +159,7 @@ export class AllureRuntime { }, ]); // eslint-disable-next-line unicorn/no-array-push-push - this.#metadata.push($POINTER, ['steps', `${count}`]); + this.#metadata.push(CURRENT_STEP, ['steps', `${count}`]); }; #stopStep = (status: Status, statusDetails?: StatusDetails) => { @@ -170,8 +169,8 @@ export class AllureRuntime { statusDetails, stop: this.#now(), }); - const $pointer = this.#metadata.get($POINTER, []) as string[]; - this.#metadata.set($POINTER, $pointer.slice(0, -2)); + const currentStep = this.#metadata.get(CURRENT_STEP, []) as string[]; + this.#metadata.set(CURRENT_STEP, currentStep.slice(0, -2)); }; #updateStep = (stage: Stage) => { @@ -179,7 +178,7 @@ export class AllureRuntime { }; #localPath(key?: keyof AllureTestStepMetadata, ...innerKeys: string[]) { - const stepPath = this.#metadata.get($POINTER, []) as string[]; + const stepPath = this.#metadata.get(CURRENT_STEP, []) as string[]; const allKeys = key ? [key, ...innerKeys] : innerKeys; return [PREFIX, ...stepPath, ...allKeys]; } diff --git a/packages/library/src/runtime/__snapshots__/AllureRuntime.test.ts.snap b/packages/library/src/runtime/__snapshots__/AllureRuntime.test.ts.snap index 6e5d115..f394c29 100644 --- a/packages/library/src/runtime/__snapshots__/AllureRuntime.test.ts.snap +++ b/packages/library/src/runtime/__snapshots__/AllureRuntime.test.ts.snap @@ -2,7 +2,7 @@ exports[`AllureRuntime should add attachments within the steps 1`] = ` { - "$pointer": [], + "currentStep": [], "attachments": [ { "content": { diff --git a/packages/library/src/runtime/index.ts b/packages/library/src/runtime/index.ts index c405123..61480b4 100644 --- a/packages/library/src/runtime/index.ts +++ b/packages/library/src/runtime/index.ts @@ -1,2 +1 @@ export * from './AllureRuntime'; -export * from './metadata'; diff --git a/packages/presets/eslint-config/index.js b/packages/presets/eslint-config/index.js index 91739ed..4873bae 100644 --- a/packages/presets/eslint-config/index.js +++ b/packages/presets/eslint-config/index.js @@ -34,6 +34,7 @@ module.exports = { "node/no-extraneous-import": "off", "unicorn/consistent-function-scoping": "off", "unicorn/filename-case": "off", + "unicorn/no-array-callback-reference": "off", "unicorn/no-null": "off", "unicorn/prefer-event-target": "off", "unicorn/prefer-module": "off",