@serenity-js/serenity-bdd
Advanced tools
Comparing version 3.14.2 to 3.15.0
@@ -6,2 +6,22 @@ # Change Log | ||
# [3.15.0](https://github.com/serenity-js/serenity-js/compare/v3.14.2...v3.15.0) (2024-01-12) | ||
### Bug Fixes | ||
* **serenity-bdd:** upgraded Serenity BDD CLI to 4.0.43 ([e1d22e9](https://github.com/serenity-js/serenity-js/commit/e1d22e92e120c7b6205ffe63dc22ebba5844e7ba)), closes [#1147](https://github.com/serenity-js/serenity-js/issues/1147) | ||
### Features | ||
* **serenity-bdd:** auto-detect requirements hierarchy root directory ([e2011b0](https://github.com/serenity-js/serenity-js/commit/e2011b0b95565d67e8ee785f3e197f827703a934)), closes [#1147](https://github.com/serenity-js/serenity-js/issues/1147) | ||
* **serenity-bdd:** support for Serenity BDD 4 ([c15c366](https://github.com/serenity-js/serenity-js/commit/c15c3660f957c21c367f8f27218a05d3fbca78de)), closes [#1147](https://github.com/serenity-js/serenity-js/issues/1147) | ||
* **serenity-bdd:** support for Serenity BDD 4 ([0760417](https://github.com/serenity-js/serenity-js/commit/0760417e2fa3e9fbfc78cd9965052531625bf45e)) | ||
* **serenity-bdd:** support for Serenity BDD CLI v4.0.40 ([271068e](https://github.com/serenity-js/serenity-js/commit/271068e7ff64659138c5662cd3b8ae93bc7a7438)), closes [#1147](https://github.com/serenity-js/serenity-js/issues/1147) | ||
* **serenity-bdd:** support for Serenity BDD v4 CLI ([6988248](https://github.com/serenity-js/serenity-js/commit/69882485ce28bb18e502b3f49740a4f82aedaa1d)), closes [#1147](https://github.com/serenity-js/serenity-js/issues/1147) [#2042](https://github.com/serenity-js/serenity-js/issues/2042) | ||
## [3.14.2](https://github.com/serenity-js/serenity-js/compare/v3.14.1...v3.14.2) (2023-12-12) | ||
@@ -8,0 +28,0 @@ |
@@ -0,1 +1,2 @@ | ||
import { Path } from '@serenity-js/core/lib/io'; | ||
import type { Argv } from '../Argv'; | ||
@@ -15,3 +16,3 @@ declare const _default: { | ||
features: { | ||
default: string; | ||
default: Path; | ||
describe: string; | ||
@@ -18,0 +19,0 @@ }; |
@@ -28,2 +28,3 @@ "use strict"; | ||
const path = __importStar(require("path")); // eslint-disable-line unicorn/import-style | ||
const SpecDirectory_1 = require("../../stage/crew/serenity-bdd-reporter/SpecDirectory"); | ||
const defaults_1 = require("../defaults"); | ||
@@ -36,2 +37,3 @@ const io_2 = require("../io"); | ||
const yargs = require('yargs'); // eslint-disable-line @typescript-eslint/no-var-requires | ||
const cwd = new io_1.Path(process.cwd()); | ||
module.exports = { | ||
@@ -50,4 +52,4 @@ command: 'run', | ||
features: { | ||
default: defaults_1.defaults.featuresDir, | ||
describe: 'A relative path to the directory containing the Cucumber.js feature files', | ||
default: cwd.relative(new SpecDirectory_1.SpecDirectory(new io_1.FileSystem(cwd)).guessLocation()), | ||
describe: 'A relative path to the requirements hierarchy root directory, such as "./features" or "./spec"', | ||
}, | ||
@@ -72,3 +74,3 @@ artifact: { | ||
project: { | ||
default: path.basename(process.cwd()), | ||
default: cwd.basename(), | ||
describe: `Project name to appear in the Serenity reports`, | ||
@@ -90,3 +92,3 @@ }, | ||
(0, core_1.configure)({ | ||
actors: new stage_1.RunCommandActors(new io_1.Path(process.cwd())), | ||
actors: new stage_1.RunCommandActors(cwd), | ||
crew: [ | ||
@@ -93,0 +95,0 @@ new stage_1.NotificationReporter(printer), |
/** | ||
* @desc | ||
* Default configuration to be used when invoking the serenity-bdd command line interface. | ||
* See the source code to find out more about the values being used. | ||
* Default configuration to be used when invoking the serenity-bdd command line interface. | ||
* See the source code to find out more about the values being used. | ||
* | ||
@@ -23,5 +22,4 @@ * @typedef {Object} defaults | ||
reportDir: string; | ||
featuresDir: string; | ||
log: string; | ||
}; | ||
//# sourceMappingURL=defaults.d.ts.map |
@@ -5,5 +5,4 @@ "use strict"; | ||
/** | ||
* @desc | ||
* Default configuration to be used when invoking the serenity-bdd command line interface. | ||
* See the source code to find out more about the values being used. | ||
* Default configuration to be used when invoking the serenity-bdd command line interface. | ||
* See the source code to find out more about the values being used. | ||
* | ||
@@ -22,3 +21,3 @@ * @typedef {Object} defaults | ||
exports.defaults = { | ||
artifact: 'net.serenity-bdd:serenity-cli:jar:3.1.0', | ||
artifact: 'net.serenity-bdd:serenity-cli:jar:4.0.43', | ||
repository: 'https://repo1.maven.org/maven2/', | ||
@@ -28,5 +27,4 @@ cacheDir: 'node_modules/@serenity-js/serenity-bdd/cache', | ||
reportDir: 'target/site/serenity', | ||
featuresDir: 'features', | ||
log: 'warn', | ||
}; | ||
//# sourceMappingURL=defaults.js.map |
@@ -1,4 +0,6 @@ | ||
import type { StageCrewMember } from '@serenity-js/core'; | ||
import type { StageCrewMemberBuilder } from '@serenity-js/core'; | ||
import type { SerenityBDDReporterConfig } from './stage'; | ||
import { SerenityBDDReporter } from './stage'; | ||
export * from './stage'; | ||
export default function create(): StageCrewMember; | ||
export default function create(config?: SerenityBDDReporterConfig): StageCrewMemberBuilder<SerenityBDDReporter>; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -19,6 +19,6 @@ "use strict"; | ||
__exportStar(require("./stage"), exports); | ||
function create() { | ||
return new stage_1.SerenityBDDReporter(); | ||
function create(config = {}) { | ||
return stage_1.SerenityBDDReporter.fromJSON(config); | ||
} | ||
exports.default = create; | ||
//# sourceMappingURL=index.js.map |
export * from './SerenityBDDReporter'; | ||
export * from './SerenityBDDReporterConfig'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -18,2 +18,3 @@ "use strict"; | ||
__exportStar(require("./SerenityBDDReporter"), exports); | ||
__exportStar(require("./SerenityBDDReporterConfig"), exports); | ||
//# sourceMappingURL=index.js.map |
import type { DomainEventQueue } from '@serenity-js/core'; | ||
import type { ActivityRelatedArtifactArchived, ActivityRelatedArtifactGenerated, BusinessRuleDetected, FeatureNarrativeDetected, SceneBackgroundDetected, SceneDescriptionDetected, SceneTagged, TestRunnerDetected } from '@serenity-js/core/lib/events'; | ||
import type { SerenityBDDReport } from '../SerenityBDDJsonSchema'; | ||
import type { Path } from '@serenity-js/core/lib/io'; | ||
import type { SerenityBDD4ReportSchema } from '../serenity-bdd-report-schema'; | ||
import type { SerenityBDDReportContext } from './SerenityBDDReportContext'; | ||
@@ -9,4 +10,6 @@ /** | ||
export declare abstract class EventQueueProcessor { | ||
protected readonly specDirectory: Path; | ||
constructor(specDirectory: Path); | ||
abstract supports(queue: DomainEventQueue): boolean; | ||
abstract process(queue: DomainEventQueue): SerenityBDDReport; | ||
abstract process(queue: DomainEventQueue): SerenityBDD4ReportSchema; | ||
protected onFeatureNarrativeDetected<Context extends SerenityBDDReportContext>(report: Context): (event: FeatureNarrativeDetected) => Context; | ||
@@ -13,0 +16,0 @@ protected onSceneBackgroundDetected<Context extends SerenityBDDReportContext>(report: Context): (event: SceneBackgroundDetected) => Context; |
@@ -9,2 +9,6 @@ "use strict"; | ||
class EventQueueProcessor { | ||
specDirectory; | ||
constructor(specDirectory) { | ||
this.specDirectory = specDirectory; | ||
} | ||
onFeatureNarrativeDetected(report) { | ||
@@ -11,0 +15,0 @@ return (event) => report |
import type { DomainEventQueues } from '@serenity-js/core'; | ||
import type { Path } from '@serenity-js/core/lib/io'; | ||
import type { Artifact, CorrelationId } from '@serenity-js/core/lib/model'; | ||
@@ -10,2 +11,3 @@ import { Name } from '@serenity-js/core/lib/model'; | ||
private readonly sceneSequenceProcessor; | ||
constructor(specDirectory: Path); | ||
process(queues: DomainEventQueues): Array<{ | ||
@@ -12,0 +14,0 @@ artifact: Artifact; |
@@ -12,4 +12,8 @@ "use strict"; | ||
class EventQueueProcessors { | ||
singleSceneProcessor = new single_scene_1.SingleSceneEventQueueProcessor(); | ||
sceneSequenceProcessor = new scene_sequence_1.SceneSequenceEventQueueProcessor(); | ||
singleSceneProcessor; | ||
sceneSequenceProcessor; | ||
constructor(specDirectory) { | ||
this.singleSceneProcessor = new single_scene_1.SingleSceneEventQueueProcessor(specDirectory); | ||
this.sceneSequenceProcessor = new scene_sequence_1.SceneSequenceEventQueueProcessor(specDirectory); | ||
} | ||
// todo: move `name` to Artifact and return Artifact[]... and sceneId? | ||
@@ -16,0 +20,0 @@ process(queues) { |
import type { CorrelationId } from '@serenity-js/core/lib/model'; | ||
import type { TestStep } from '../SerenityBDDJsonSchema'; | ||
import type { TestStepSchema } from '../serenity-bdd-report-schema'; | ||
/** | ||
@@ -7,5 +7,5 @@ * @package | ||
export interface LinkedTestStep { | ||
step: TestStep; | ||
step: TestStepSchema; | ||
parentActivityId: CorrelationId; | ||
} | ||
//# sourceMappingURL=LinkedTestStep.d.ts.map |
@@ -1,4 +0,4 @@ | ||
import type { ErrorDetails } from '../../SerenityBDDJsonSchema'; | ||
import type { ErrorDetailsSchema } from '../../serenity-bdd-report-schema'; | ||
/** @package */ | ||
export declare function errorReportFrom(error?: Error | string | number | boolean | object): ErrorDetails; | ||
export declare function errorReportFrom(error?: Error | string | number | boolean | object): ErrorDetailsSchema; | ||
//# sourceMappingURL=errorReportFrom.d.ts.map |
import type { Outcome } from '@serenity-js/core/lib/model'; | ||
import type { ErrorDetails } from '../../SerenityBDDJsonSchema'; | ||
import type { ErrorDetailsSchema } from '../../serenity-bdd-report-schema'; | ||
/** | ||
@@ -8,4 +8,4 @@ * @package | ||
result: string; | ||
error?: ErrorDetails; | ||
error?: ErrorDetailsSchema; | ||
}; | ||
//# sourceMappingURL=outcomeReportFrom.d.ts.map |
import type { DomainEventQueue } from '@serenity-js/core'; | ||
import type { SerenityBDDReport } from '../../SerenityBDDJsonSchema'; | ||
import type { SerenityBDD4ReportSchema } from '../../serenity-bdd-report-schema'; | ||
import { EventQueueProcessor } from '../EventQueueProcessor'; | ||
@@ -9,3 +9,3 @@ /** | ||
supports(queue: DomainEventQueue): boolean; | ||
process(queue: DomainEventQueue): SerenityBDDReport; | ||
process(queue: DomainEventQueue): SerenityBDD4ReportSchema; | ||
private onSceneSequenceDetected; | ||
@@ -12,0 +12,0 @@ private onSceneStarts; |
@@ -39,3 +39,3 @@ "use strict"; | ||
.when(events_1.SceneFinished, this.onSceneFinished(context)) | ||
.else(() => context), new SceneSequenceReportContext_1.SceneSequenceReportContext() // eslint-disable-line @typescript-eslint/indent | ||
.else(() => context), new SceneSequenceReportContext_1.SceneSequenceReportContext(this.specDirectory) // eslint-disable-line @typescript-eslint/indent | ||
).build(); | ||
@@ -42,0 +42,0 @@ } |
import { ExecutionSuccessful } from '@serenity-js/core/lib/model'; | ||
import type { SerenityBDDReport } from '../../SerenityBDDJsonSchema'; | ||
import type { SerenityBDD4ReportSchema } from '../../serenity-bdd-report-schema'; | ||
import { SerenityBDDReportContext } from '../SerenityBDDReportContext'; | ||
@@ -11,4 +11,4 @@ import type { ScenarioParametersDescriptor } from './ScenarioParametersDescriptor'; | ||
readonly worstOutcomeSoFar: ExecutionSuccessful; | ||
build(): SerenityBDDReport; | ||
build(): SerenityBDD4ReportSchema; | ||
} | ||
//# sourceMappingURL=SceneSequenceReportContext.d.ts.map |
import type { CorrelationId } from '@serenity-js/core/lib/model'; | ||
import type { SerenityBDDReport } from '../SerenityBDDJsonSchema'; | ||
import type { Path } from '@serenity-js/core/src/io'; | ||
import type { SerenityBDD4ReportSchema } from '../serenity-bdd-report-schema'; | ||
import type { LinkedTestStep } from './LinkedTestStep'; | ||
@@ -8,8 +9,10 @@ /** | ||
export declare abstract class SerenityBDDReportContext { | ||
readonly report: Partial<SerenityBDDReport>; | ||
readonly specDirectory: Path; | ||
readonly report: Partial<SerenityBDD4ReportSchema>; | ||
readonly steps: Map<string, LinkedTestStep>; | ||
currentActivityId: CorrelationId; | ||
constructor(specDirectory: Path); | ||
with(fn: (report: this) => this): this; | ||
build(): SerenityBDDReport; | ||
build(): SerenityBDD4ReportSchema; | ||
} | ||
//# sourceMappingURL=SerenityBDDReportContext.d.ts.map |
@@ -8,5 +8,9 @@ "use strict"; | ||
class SerenityBDDReportContext { | ||
specDirectory; | ||
report = {}; | ||
steps = new Map(); | ||
currentActivityId = undefined; | ||
constructor(specDirectory) { | ||
this.specDirectory = specDirectory; | ||
} | ||
with(fn) { | ||
@@ -13,0 +17,0 @@ return fn(this); |
import type { DomainEventQueue } from '@serenity-js/core'; | ||
import type { SerenityBDDReport } from '../../SerenityBDDJsonSchema'; | ||
import type { SerenityBDD4ReportSchema } from '../../serenity-bdd-report-schema'; | ||
import { EventQueueProcessor } from '../EventQueueProcessor'; | ||
@@ -9,3 +9,3 @@ /** | ||
supports(queue: DomainEventQueue): boolean; | ||
process(queue: DomainEventQueue): SerenityBDDReport; | ||
process(queue: DomainEventQueue): SerenityBDD4ReportSchema; | ||
private onSceneStarts; | ||
@@ -12,0 +12,0 @@ private onActivityStarts; |
@@ -31,3 +31,3 @@ "use strict"; | ||
.when(events_1.SceneFinished, this.onSceneFinished(context)) | ||
.else(() => context), new SingleSceneReportContext_1.SingleSceneReportContext() // eslint-disable-line @typescript-eslint/indent | ||
.else(() => context), new SingleSceneReportContext_1.SingleSceneReportContext(this.specDirectory) // eslint-disable-line @typescript-eslint/indent | ||
).build(); | ||
@@ -34,0 +34,0 @@ } |
@@ -15,3 +15,3 @@ "use strict"; | ||
linkedStep.step.exception = outcomeReport.error; | ||
linkedStep.step.duration = core_1.Timestamp.fromTimestampInMilliseconds(linkedStep.step.startTime).diff(finishedAt).inMilliseconds(); | ||
linkedStep.step.duration = core_1.Timestamp.fromJSON(linkedStep.step.startTime).diff(finishedAt).inMilliseconds(); | ||
context.currentActivityId = linkedStep.parentActivityId; | ||
@@ -18,0 +18,0 @@ return context; |
@@ -11,4 +11,10 @@ "use strict"; | ||
number: context.steps.size + 1, | ||
/** | ||
* It doesn't look like the TestStep.level was used anywhere in the Serenity BDD Reporter, | ||
* https://github.com/serenity-bdd/serenity-core/blob/5bebe8e77cf0c4ea99e0d3d1035d54822bcde9af/serenity-model/src/main/java/net/thucydides/model/domain/TestStep.java | ||
*/ | ||
// level: 0, | ||
// precondition: false, | ||
description: name.value, | ||
startTime: startedAt.toMilliseconds(), | ||
startTime: startedAt.toISOString(), | ||
children: [], | ||
@@ -15,0 +21,0 @@ reportData: [], |
@@ -13,2 +13,3 @@ "use strict"; | ||
screenshot: path.basename(), | ||
screenshotName: path.basename(), | ||
timeStamp: timestamp.toMilliseconds(), | ||
@@ -15,0 +16,0 @@ }); |
@@ -10,3 +10,3 @@ "use strict"; | ||
return (context) => { | ||
context.report.duration = core_1.Timestamp.fromTimestampInMilliseconds(context.report.startTime) | ||
context.report.duration = core_1.Timestamp.fromJSON(context.report.startTime) | ||
.diff(timestamp) | ||
@@ -13,0 +13,0 @@ .inMilliseconds(); |
@@ -9,3 +9,3 @@ "use strict"; | ||
return (context) => { | ||
context.report.startTime = context.report.startTime || timestamp.toMilliseconds(); | ||
context.report.startTime = context.report.startTime || timestamp.toISOString(); | ||
return context; | ||
@@ -12,0 +12,0 @@ }; |
@@ -13,2 +13,8 @@ "use strict"; | ||
const category = (0, tiny_types_1.ensure)('scenario category', details.category.value, (0, tiny_types_1.isNotBlank)()); | ||
const storyName = (0, mappers_1.escapeHtml)(category); | ||
const requirementsHierarchy = requirementsHierarchyFromPath(context.specDirectory, details.location.path); | ||
const pathElements = requirementsHierarchy.map(name => ({ | ||
name, | ||
description: humanReadable(name), | ||
})); | ||
context.report.name = (0, mappers_1.escapeHtml)(name); | ||
@@ -20,7 +26,8 @@ context.report.title = (0, mappers_1.escapeHtml)(name); | ||
id: (0, mappers_1.dashify)(category), | ||
storyName: (0, mappers_1.escapeHtml)(category), | ||
path: isFeatureFile(details.location.path) | ||
? details.location.path.value | ||
: '', | ||
storyName: storyName, | ||
displayName: storyName, | ||
path: requirementsHierarchy.join('/'), | ||
type: 'feature', | ||
narrative: '', | ||
pathElements, | ||
}; | ||
@@ -31,9 +38,21 @@ return context; | ||
exports.scenarioDetailsOf = scenarioDetailsOf; | ||
/** | ||
* @package | ||
* @param {Path} path | ||
*/ | ||
function isFeatureFile(path) { | ||
return path && path.value.endsWith('.feature'); | ||
function requirementsHierarchyFromPath(specDirectory, path) { | ||
const relative = specDirectory.relative(path); | ||
return relative.split().map((segment, i, segments) => { | ||
if (i < segments.length - 1) { | ||
return segment; | ||
} | ||
// If there is a dot in the file name, extract the substring before it; otherwise, use the entire string | ||
const firstDotIndex = segment.indexOf('.'); | ||
return firstDotIndex === -1 | ||
? segment | ||
: segment.slice(0, firstDotIndex); | ||
}); | ||
} | ||
function humanReadable(name) { | ||
const result = name | ||
.split('_') | ||
.join(' '); | ||
return result.charAt(0).toUpperCase() + result.slice(1); | ||
} | ||
//# sourceMappingURL=scenarioDetailsOf.js.map |
@@ -9,3 +9,3 @@ "use strict"; | ||
return (context) => { | ||
context.report.testSource = name.value; | ||
context.report.testSource = name.value === 'Cucumber' ? name.value : 'JS'; | ||
return context; | ||
@@ -12,0 +12,0 @@ }; |
@@ -1,3 +0,5 @@ | ||
import type { Stage, StageCrewMember } from '@serenity-js/core'; | ||
import type { Stage, StageCrewMember, StageCrewMemberBuilder } from '@serenity-js/core'; | ||
import type { DomainEvent } from '@serenity-js/core/lib/events'; | ||
import { Path } from '@serenity-js/core/lib/io'; | ||
import type { SerenityBDDReporterConfig } from './SerenityBDDReporterConfig'; | ||
/** | ||
@@ -16,4 +18,8 @@ * A {@apilink StageCrewMember} that produces [Serenity BDD](http://serenity-bdd.info/)-standard JSON reports | ||
* crew: [ | ||
* ArtifactArchiver.storingArtifactsAt('./target/site/serenity'), | ||
* new SerenityBDDReporter() | ||
* ArtifactArchiver.fromJSON({ | ||
* outputDirectory: './target/site/serenity' | ||
* }), | ||
* SerenityBDDReporter.fromJSON({ | ||
* specDirectory: './features' // optional configuration | ||
* }) | ||
* ], | ||
@@ -49,4 +55,2 @@ * }) | ||
* // wdio.conf.ts | ||
* import { ArtifactArchiver } from '@serenity-js/core'; | ||
* import { SerenityBDDReporter } from '@serenity-js/serenity-bdd'; | ||
* import { WebdriverIOConfig } from '@serenity-js/webdriverio'; | ||
@@ -73,6 +77,2 @@ * | ||
* // protractor.conf.js | ||
* const | ||
* { ArtifactArchiver } = require('@serenity-js/core'), | ||
* { SerenityBDDReporter } = require('@serenity-js/serenity-bdd') | ||
* | ||
* exports.config = { | ||
@@ -94,12 +94,36 @@ * framework: 'custom', | ||
* | ||
* ## Configuring Serenity BDD Reporter | ||
* | ||
* To override Serenity BDD Reporter default configuration, provide a {@link SerenityBDDReporterConfig} as the second element of the {@link SerenityConfig.crew} array | ||
* using your test runner-specific configuration mechanism. | ||
* | ||
* For example, to change the default location | ||
* of the [requirements hierarchy root directory](https://serenity-bdd.github.io/docs/reporting/living_documentation#the-requirements-hierarchy), | ||
* specify the `specDirectory` property: | ||
* | ||
* ```js | ||
* crew: [ | ||
* [ '@serenity-js/serenity-bdd', { specDirectory: './features' } ], | ||
* // ... | ||
* ], | ||
* ``` | ||
* | ||
* ### Learn more: | ||
* - [Serenity BDD Reporter integration documentation](/handbook/reporting/serenity-bdd-reporter/) | ||
* - [Serenity/JS examples on GitHub](https://github.com/serenity-js/serenity-js/tree/main/examples) | ||
* | ||
* @group Stage | ||
*/ | ||
export declare class SerenityBDDReporter implements StageCrewMember { | ||
private readonly specDirectory; | ||
private stage?; | ||
private readonly eventQueues; | ||
private readonly processors; | ||
static fromJSON(config: SerenityBDDReporterConfig): StageCrewMemberBuilder<SerenityBDDReporter>; | ||
/** | ||
* @param [stage=undefined] stage | ||
* @param {Path} specDirectory | ||
* @param {Stage} [stage] | ||
* The stage this {@apilink StageCrewMember} should be assigned to | ||
*/ | ||
constructor(stage?: Stage); | ||
constructor(specDirectory: Path, stage?: Stage); | ||
/** | ||
@@ -106,0 +130,0 @@ * @inheritDoc |
@@ -6,4 +6,7 @@ "use strict"; | ||
const events_1 = require("@serenity-js/core/lib/events"); | ||
const io_1 = require("@serenity-js/core/lib/io"); | ||
const model_1 = require("@serenity-js/core/lib/model"); | ||
const tiny_types_1 = require("tiny-types"); | ||
const processors_1 = require("./processors"); | ||
const SpecDirectory_1 = require("./SpecDirectory"); | ||
/** | ||
@@ -22,4 +25,8 @@ * A {@apilink StageCrewMember} that produces [Serenity BDD](http://serenity-bdd.info/)-standard JSON reports | ||
* crew: [ | ||
* ArtifactArchiver.storingArtifactsAt('./target/site/serenity'), | ||
* new SerenityBDDReporter() | ||
* ArtifactArchiver.fromJSON({ | ||
* outputDirectory: './target/site/serenity' | ||
* }), | ||
* SerenityBDDReporter.fromJSON({ | ||
* specDirectory: './features' // optional configuration | ||
* }) | ||
* ], | ||
@@ -55,4 +62,2 @@ * }) | ||
* // wdio.conf.ts | ||
* import { ArtifactArchiver } from '@serenity-js/core'; | ||
* import { SerenityBDDReporter } from '@serenity-js/serenity-bdd'; | ||
* import { WebdriverIOConfig } from '@serenity-js/webdriverio'; | ||
@@ -79,6 +84,2 @@ * | ||
* // protractor.conf.js | ||
* const | ||
* { ArtifactArchiver } = require('@serenity-js/core'), | ||
* { SerenityBDDReporter } = require('@serenity-js/serenity-bdd') | ||
* | ||
* exports.config = { | ||
@@ -100,13 +101,41 @@ * framework: 'custom', | ||
* | ||
* ## Configuring Serenity BDD Reporter | ||
* | ||
* To override Serenity BDD Reporter default configuration, provide a {@link SerenityBDDReporterConfig} as the second element of the {@link SerenityConfig.crew} array | ||
* using your test runner-specific configuration mechanism. | ||
* | ||
* For example, to change the default location | ||
* of the [requirements hierarchy root directory](https://serenity-bdd.github.io/docs/reporting/living_documentation#the-requirements-hierarchy), | ||
* specify the `specDirectory` property: | ||
* | ||
* ```js | ||
* crew: [ | ||
* [ '@serenity-js/serenity-bdd', { specDirectory: './features' } ], | ||
* // ... | ||
* ], | ||
* ``` | ||
* | ||
* ### Learn more: | ||
* - [Serenity BDD Reporter integration documentation](/handbook/reporting/serenity-bdd-reporter/) | ||
* - [Serenity/JS examples on GitHub](https://github.com/serenity-js/serenity-js/tree/main/examples) | ||
* | ||
* @group Stage | ||
*/ | ||
class SerenityBDDReporter { | ||
specDirectory; | ||
stage; | ||
eventQueues = new core_1.DomainEventQueues(); | ||
processors = new processors_1.EventQueueProcessors(); | ||
processors; | ||
static fromJSON(config) { | ||
return new SerenityBDDReporterBuilder(config); | ||
} | ||
/** | ||
* @param [stage=undefined] stage | ||
* @param {Path} specDirectory | ||
* @param {Stage} [stage] | ||
* The stage this {@apilink StageCrewMember} should be assigned to | ||
*/ | ||
constructor(stage) { | ||
constructor(specDirectory, stage) { | ||
this.specDirectory = specDirectory; | ||
this.stage = stage; | ||
this.processors = new processors_1.EventQueueProcessors((0, tiny_types_1.ensure)('specDirectory', specDirectory, (0, tiny_types_1.isDefined)())); | ||
} | ||
@@ -148,2 +177,28 @@ /** | ||
exports.SerenityBDDReporter = SerenityBDDReporter; | ||
class SerenityBDDReporterBuilder { | ||
config; | ||
constructor(config) { | ||
this.config = config; | ||
} | ||
build({ stage, fileSystem }) { | ||
(0, tiny_types_1.ensure)('stage', stage, (0, tiny_types_1.isDefined)()); | ||
(0, tiny_types_1.ensure)('fileSystem', fileSystem, (0, tiny_types_1.isDefined)()); | ||
return new SerenityBDDReporter(this.specDirectoryFrom(fileSystem), stage); | ||
} | ||
specDirectoryFrom(fileSystem) { | ||
return this.config.specDirectory | ||
? this.userDefinedSpecDir(fileSystem, this.config.specDirectory) | ||
: this.guessedSpecDir(fileSystem); | ||
} | ||
userDefinedSpecDir(fileSystem, configuredSpecDirectory) { | ||
const specDirectory = io_1.Path.from(configuredSpecDirectory); | ||
if (!fileSystem.exists(specDirectory)) { | ||
throw new core_1.ConfigurationError(`Configured specDirectory \`${this.config.specDirectory}\` does not exist`); | ||
} | ||
return fileSystem.resolve(specDirectory); | ||
} | ||
guessedSpecDir(fileSystem) { | ||
return new SpecDirectory_1.SpecDirectory(fileSystem).guessLocation(); | ||
} | ||
} | ||
//# sourceMappingURL=SerenityBDDReporter.js.map |
{ | ||
"name": "@serenity-js/serenity-bdd", | ||
"version": "3.14.2", | ||
"version": "3.15.0", | ||
"description": "Serenity BDD reporter for Serenity/JS", | ||
@@ -49,7 +49,7 @@ "author": { | ||
"dependencies": { | ||
"@serenity-js/assertions": "3.14.2", | ||
"@serenity-js/core": "3.14.2", | ||
"@serenity-js/rest": "3.14.2", | ||
"@serenity-js/assertions": "3.15.0", | ||
"@serenity-js/core": "3.15.0", | ||
"@serenity-js/rest": "3.15.0", | ||
"ansi-regex": "5.0.1", | ||
"axios": "1.6.2", | ||
"axios": "1.6.5", | ||
"chalk": "4.1.2", | ||
@@ -68,3 +68,3 @@ "find-java-home": "2.0.0", | ||
"@types/progress": "2.0.7", | ||
"c8": "8.0.1", | ||
"c8": "9.0.0", | ||
"if-env": "1.0.4", | ||
@@ -77,3 +77,3 @@ "memfs": "4.6.0", | ||
}, | ||
"gitHead": "b2b052ea1120bf33c2848956f2f0ea5f0ffdfc24" | ||
"gitHead": "f3580d6b6380e9f175544929b9504a85c1d204ad" | ||
} |
306
README.md
@@ -15,3 +15,3 @@ # Serenity/JS | ||
- [API documentation](https://serenity-js.org/api/core) | ||
- [Serenity/JS Project Templates on GitHub](https://serenity-js.org/handbook/getting-started#serenityjs-project-templates) | ||
- [Serenity/JS Project Templates on GitHub](https://serenity-js.org/handbook/getting-started/project-templates/) | ||
@@ -28,304 +28,6 @@ 👋 Join the Serenity/JS Community! | ||
This integration enables your Serenity/JS tests to produce interim JSON reports, which the Serenity BDD reporting CLI | ||
can then turn into world-class, illustrated test reports and living documentation. Learn more about [Serenity/JS reporting](https://serenity-js.org/handbook/reporting/index.html). | ||
Learn more about [Serenity/JS reporting with Serenity BDD](https://serenity-js.org/handbook/reporting/serenity-bdd-reporter/): | ||
- [Installation, configuration and usage](https://serenity-js.org/handbook/reporting/serenity-bdd-reporter/#installation-and-usage) | ||
- [Best practices](https://serenity-js.org/handbook/reporting/serenity-bdd-reporter/#serenity-bdd-best-practices) | ||
### Installation | ||
To install this module, run the following command in your computer terminal: | ||
```sh | ||
npm install --save-dev @serenity-js/core @serenity-js/serenity-bdd | ||
``` | ||
To learn more about Serenity/JS and how to use it on your project, follow the [Serenity/JS Getting Started guide](https://serenity-js.org/handbook/getting-started/). | ||
### SerenityBDDReporter | ||
To allow Serenity/JS to produce Serenity BDD-standard JSON reports, assign the `SerenityBDDReporter` to the `Stage` | ||
and configure the `ArtifactArchiver` to store the reports at the location where Serenity BDD expects to find them. | ||
This can be done: | ||
- via `playwright.config.ts`, if you're using Serenity/JS with [Playwright Test](https://serenity-js.org/api/playwright-test) | ||
- via `wdio.conf.ts`, if you're using Serenity/JS with [WebdriverIO](https://serenity-js.org/api/playwright-test) | ||
- via `protractor.conf.js`, if you're using Serenity/JS with [Protractor](https://serenity-js.org/api/protractor) | ||
- or programmatically. | ||
#### Usage with Playwright Test | ||
Learn more about using [Serenity/JS with Playwright Test](https://serenity-js.org/api/playwright-test). | ||
```typescript | ||
// playwright.config.ts | ||
import type { PlaywrightTestConfig } from '@serenity-js/playwright-test' | ||
const config: PlaywrightTestConfig = { | ||
reporter: [ | ||
[ '@serenity-js/playwright-test', { | ||
crew: [ | ||
'@serenity-js/serenity-bdd', | ||
[ '@serenity-js/core:ArtifactArchiver', { outputDirectory: 'target/site/serenity' } ], | ||
] | ||
}] | ||
], | ||
// Other configuration omitted for brevity | ||
// For details, see https://playwright.dev/docs/test-configuration | ||
} | ||
export default config | ||
``` | ||
#### Usage with WebdriverIO | ||
Learn more about using [Serenity/JS with WebdriverIO](https://serenity-js.org/api/webdriverio). | ||
```typescript | ||
// wdio.conf.ts | ||
import { WebdriverIOConfig } from '@serenity-js/webdriverio' | ||
export const config: WebdriverIOConfig = { | ||
framework: '@serenity-js/webdriverio', | ||
serenity: { | ||
crew: [ | ||
'@serenity-js/serenity-bdd', | ||
[ '@serenity-js/core:ArtifactArchiver', { outputDirectory: 'target/site/serenity' } ], | ||
] | ||
}, | ||
// Other configuration omitted for brevity | ||
// For details, see https://webdriver.io/docs/options | ||
} | ||
``` | ||
#### Usage with Protractor | ||
Learn more about using [Serenity/JS with Protractor](https://serenity-js.org/api/protractor). | ||
```javascript | ||
// protractor.conf.js | ||
exports.config = { | ||
framework: 'custom', | ||
frameworkPath: require.resolve('@serenity-js/protractor/adapter'), | ||
serenity: { | ||
crew: [ | ||
'@serenity-js/serenity-bdd', | ||
[ '@serenity-js/core:ArtifactArchiver', { outputDirectory: 'target/site/serenity' } ], | ||
] | ||
}, | ||
// ... | ||
} | ||
``` | ||
#### Programmatic configuration | ||
Learn more about [configuring Serenity/JS programmatically](https://serenity-js.org/api/core/class/SerenityConfig). | ||
```typescript | ||
import { ArtifactArchiver, configure } from '@serenity-js/core' | ||
import { SerenityBDDReporter } from '@serenity-js/serenity-bdd' | ||
configure({ | ||
crew: [ | ||
ArtifactArchiver.storingArtifactsAt('./target/site/serenity'), | ||
new SerenityBDDReporter() | ||
], | ||
}) | ||
``` | ||
### Serenity BDD Living Documentation | ||
To turn the Serenity BDD-standard JSON reports produced by the `SerenityBDDReporter` into Serenity BDD test reports, | ||
you need the [Serenity BDD reporting CLI](https://github.com/serenity-bdd/serenity-cli). | ||
The Serenity BDD reporting CLI is a Java program, distributed as an executable `.jar` file and [available on Bintray](https://bintray.com/serenity/maven/serenity-cli). | ||
This module ships with a `serenity-bdd` CLI wrapper that makes downloading and running the Serenity BDD reporting CLI easy. | ||
To learn more about the usage of the `serenity-bdd` wrapper, run: | ||
```console | ||
npx serenity-bdd --help | ||
``` | ||
#### Configuring Serenity BDD reporting CLI | ||
To configure the [Serenity BDD reporting CLI](https://github.com/serenity-bdd/serenity-cli), place a file called `serenity.properties` | ||
in your project root directory. | ||
For example: | ||
``` | ||
# serenity.properties | ||
serenity.project.name=My awesome project | ||
``` | ||
Please note that the reporting CLI considers only those properties that are related to producing test reports. | ||
Learn more about configuring [`serenity.properties`](https://serenity-bdd.github.io/docs/reference/serenity-properties). | ||
#### Downloading the Serenity BDD reporting CLI | ||
To download the Serenity BDD reporting CLI or to update it, use the update command: | ||
```console | ||
npx serenity-bdd update | ||
``` | ||
You can also tell it to download the Serenity BDD reporting CLI jar from your company's artifact repository if you can't use the official Bintray one: | ||
``` | ||
npx serenity-bdd update --repository https://artifactory.example.org/ | ||
``` | ||
To learn more about the `update` command, run: | ||
``` | ||
npx serenity-bdd --help update | ||
``` | ||
Please note that the `update` command will try to download the `.jar` only if you don't have it cached already, or when the one you have is not up to date. Otherwise, no outbound network calls are made. | ||
##### Downloading through a proxy | ||
The `update` command will pick up your proxy configuration automatically from your [NPM config](https://docs.npmjs.com/cli/v6/commands/npm-config), [`.npmrc` file](https://docs.npmjs.com/cli/v6/configuring-npm/npmrc), or environment variables. | ||
Please note that you only need to use one of those configuration mechanisms. | ||
###### Use NPM config (Linux, macOS, Windows) | ||
To use NPM-level configuration, run the following commands in your terminal: | ||
```console | ||
npm config set proxy http://[user:pwd]@domain.tld:port | ||
npm config set https-proxy http://[user:pwd]@domain.tld:port | ||
``` | ||
If your proxy requires a certificate file, you can provide a path to it as follows: | ||
```console | ||
npm config set cafile /path/to/root-ca.pem | ||
``` | ||
The above can also be accomplished by placing an [`.npmrc` file](https://docs.npmjs.com/cli/v6/configuring-npm/npmrc) with following contents in your home directory or your project root: | ||
```bash | ||
# ~/.npmrc | ||
proxy = http://[user:pwd]@domain.tld:port | ||
https-proxy = http://[user:pwd]@domain.tld:port | ||
cafile = /path/to/root-ca.pem # optional | ||
noproxy = localhost,mycompany.com # optional | ||
``` | ||
###### Environment variables on Linux or macOS | ||
To set your proxy on Linux or macOS, run the following commands in your terminal: | ||
```console | ||
export HTTP_PROXY=http://[user:pwd]@domain.tld:port | ||
export HTTPS_PROXY=http://[user:pwd]@domain.tld:port | ||
``` | ||
If needed, you can also set a `NO_PROXY` variable to a comma-separated list of domains that don't require a proxy, for example: | ||
```console | ||
export NO_PROXY=localhost,mycompany.com | ||
``` | ||
Please note that you can add the above commands to your shell's `~/.profile`, so that they're executed whenever you open a new terminal. | ||
###### Environment variables on Windows | ||
To configure a proxy on Windows, run the following commands in Command Prompt: | ||
```console | ||
set HTTP_PROXY=http://[user:pwd]@domain.tld:port | ||
set HTTPS_PROXY=http://[user:pwd]@domain.tld:port | ||
``` | ||
If you're using Powershell, run the following commands instead: | ||
```console | ||
$env:HTTP_PROXY = http://[user:pwd]@domain.tld:port | ||
$env:HTTPS_PROXY = http://[user:pwd]@domain.tld:port | ||
``` | ||
##### Use a specific User-Agent | ||
If your artifact registry requires you to use a specific user agent, you can configure it using NPM config: | ||
```console | ||
npm config set user-agent "Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0" | ||
``` | ||
##### Ignore SSL checks | ||
You can instruct the `update` command to ignore any SSL certificate errors by providing an `--ignoreSSL` flag when running the command: | ||
```console | ||
npx serenity-bdd update --ignoreSSL | ||
``` | ||
You can also disable certificate checks at the NPM config level by running: | ||
```console | ||
npm config set strict-ssl false | ||
``` | ||
Alternative, you can accomplish the same with an `.npmrc` file: | ||
```bash | ||
# ~/.npmrc | ||
npm_config_strict-ssl = false | ||
``` | ||
#### Producing the Serenity BDD test report | ||
To produce the Serenity BDD test report and living documentation using default settings, run: | ||
``` | ||
npx serenity-bdd run | ||
``` | ||
To learn more about the `run` command and how to change the default settings, run: | ||
``` | ||
npx serenity-bdd --help run | ||
``` | ||
### Using NPM scripts | ||
[Serenity BDD reports](https://serenity-js.org/handbook/reporting/serenity-bdd-reporter) are generated by [Serenity BDD CLI](https://github.com/serenity-bdd/serenity-core/tree/main/serenity-cli), | ||
a Java program downloaded and managed by the [`@serenity-js/serenity-bdd`](https://serenity-js.org/api/serenity-bdd) module. | ||
In general, to produce Serenity BDD reports, your test suite must: | ||
- download the Serenity BDD CLI, by calling `serenity-bdd update` | ||
- produce intermediate Serenity BDD `.json` reports, by registering [`SerenityBDDReporter`](https://serenity-js.org/api/serenity-bdd/class/SerenityBDDReporter) | ||
- invoke the Serenity BDD CLI when you want to produce the report, by calling `serenity-bdd run` | ||
The pattern used by all the [Serenity/JS Project Templates](https://serenity-js.org/handbook/getting-started#serenityjs-project-templates) relies | ||
on using: | ||
- an NPM [`postinstall`](https://docs.npmjs.com/cli/v9/using-npm/scripts#life-cycle-operation-order) script to download the Serenity BDD CLI | ||
- [`npm-failsafe`](https://www.npmjs.com/package/npm-failsafe) to run the reporting process even if the test suite itself has failed (which is precisely when you need test reports the most...). | ||
- [`rimraf`](https://www.npmjs.com/package/rimraf) as a convenience method to remove any test reports left over from the previous run | ||
```json title="package.json" | ||
{ | ||
"scripts": { | ||
"postinstall": "serenity-bdd update", | ||
"clean": "rimraf target", | ||
"test": "failsafe clean test:execute test:report", | ||
"test:execute": "cucumber-js", | ||
"test:report": "serenity-bdd run --features ./features ", | ||
} | ||
} | ||
``` | ||
Note that in the above code sample, you should configure `test:execute` to invoke [your test runner of choice](https://serenity-js.org/handbook/test-runners/). | ||
## 📣 Stay up to date | ||
@@ -332,0 +34,0 @@ |
import { actorCalled, configure } from '@serenity-js/core'; | ||
import { Path } from '@serenity-js/core/lib/io'; | ||
import * as path from 'path'; // eslint-disable-line unicorn/import-style | ||
import { FileSystem, Path } from '@serenity-js/core/lib/io'; | ||
import * as path from 'path'; // eslint-disable-line unicorn/import-style | ||
import { SpecDirectory } from '../../stage/crew/serenity-bdd-reporter/SpecDirectory'; | ||
import type { Argv } from '../Argv'; | ||
@@ -15,2 +16,4 @@ import { defaults } from '../defaults'; | ||
const cwd = new Path(process.cwd()); | ||
export = { | ||
@@ -29,4 +32,4 @@ command: 'run', | ||
features: { | ||
default: defaults.featuresDir, | ||
describe: 'A relative path to the directory containing the Cucumber.js feature files', | ||
default: cwd.relative(new SpecDirectory(new FileSystem(cwd)).guessLocation()), | ||
describe: 'A relative path to the requirements hierarchy root directory, such as "./features" or "./spec"', | ||
}, | ||
@@ -51,3 +54,3 @@ artifact: { | ||
project: { | ||
default: path.basename(process.cwd()), | ||
default: cwd.basename(), | ||
describe: `Project name to appear in the Serenity reports`, | ||
@@ -75,3 +78,3 @@ }, | ||
configure({ | ||
actors: new RunCommandActors(new Path(process.cwd())), | ||
actors: new RunCommandActors(cwd), | ||
crew: [ | ||
@@ -78,0 +81,0 @@ new NotificationReporter(printer), |
/** | ||
* @desc | ||
* Default configuration to be used when invoking the serenity-bdd command line interface. | ||
* See the source code to find out more about the values being used. | ||
* Default configuration to be used when invoking the serenity-bdd command line interface. | ||
* See the source code to find out more about the values being used. | ||
* | ||
@@ -18,3 +17,3 @@ * @typedef {Object} defaults | ||
export const defaults = { | ||
artifact: 'net.serenity-bdd:serenity-cli:jar:3.1.0', | ||
artifact: 'net.serenity-bdd:serenity-cli:jar:4.0.43', | ||
repository: 'https://repo1.maven.org/maven2/', | ||
@@ -24,4 +23,3 @@ cacheDir: 'node_modules/@serenity-js/serenity-bdd/cache', | ||
reportDir: 'target/site/serenity', | ||
featuresDir: 'features', | ||
log: 'warn', | ||
}; |
@@ -1,3 +0,4 @@ | ||
import type { StageCrewMember } from '@serenity-js/core'; | ||
import type { StageCrewMemberBuilder } from '@serenity-js/core'; | ||
import type { SerenityBDDReporterConfig } from './stage'; | ||
import { SerenityBDDReporter } from './stage'; | ||
@@ -7,4 +8,4 @@ | ||
export default function create(): StageCrewMember { | ||
return new SerenityBDDReporter(); | ||
export default function create(config: SerenityBDDReporterConfig = {}): StageCrewMemberBuilder<SerenityBDDReporter> { | ||
return SerenityBDDReporter.fromJSON(config); | ||
} |
export * from './SerenityBDDReporter'; | ||
export * from './SerenityBDDReporterConfig'; |
@@ -12,4 +12,5 @@ import type { DomainEventQueue } from '@serenity-js/core'; | ||
} from '@serenity-js/core/lib/events'; | ||
import type { Path } from '@serenity-js/core/lib/io'; | ||
import type { SerenityBDDReport } from '../SerenityBDDJsonSchema'; | ||
import type { SerenityBDD4ReportSchema } from '../serenity-bdd-report-schema'; | ||
import type { SerenityBDDReportContext } from './SerenityBDDReportContext'; | ||
@@ -22,4 +23,7 @@ import { activityRelatedArtifact, archivedActivityRelatedArtifact, backgroundOf, businessRuleOf, descriptionOf, featureNarrativeOf, tagOf, testRunnerCalled } from './transformations'; | ||
export abstract class EventQueueProcessor { | ||
constructor(protected readonly specDirectory: Path) { | ||
} | ||
abstract supports(queue: DomainEventQueue): boolean; | ||
abstract process(queue: DomainEventQueue): SerenityBDDReport; // todo: return Artifact with a name instead | ||
abstract process(queue: DomainEventQueue): SerenityBDD4ReportSchema; // todo: return Artifact with a name instead | ||
@@ -26,0 +30,0 @@ protected onFeatureNarrativeDetected<Context extends SerenityBDDReportContext>(report: Context) { |
import type { DomainEventQueues } from '@serenity-js/core'; | ||
import { SceneStarts } from '@serenity-js/core/lib/events'; | ||
import type { Artifact, CorrelationId} from '@serenity-js/core/lib/model'; | ||
import type { Path } from '@serenity-js/core/lib/io'; | ||
import type { Artifact, CorrelationId } from '@serenity-js/core/lib/model'; | ||
import { Name, TestReport } from '@serenity-js/core/lib/model'; | ||
import type { JSONObject } from 'tiny-types'; | ||
import type { SerenityBDDReport } from '../SerenityBDDJsonSchema'; | ||
import type { SerenityBDD4ReportSchema } from '../serenity-bdd-report-schema'; | ||
import type { EventQueueProcessor } from './EventQueueProcessor'; | ||
import { SceneSequenceEventQueueProcessor } from './scene-sequence'; | ||
@@ -15,5 +18,10 @@ import { SingleSceneEventQueueProcessor } from './single-scene'; | ||
private readonly singleSceneProcessor = new SingleSceneEventQueueProcessor(); | ||
private readonly sceneSequenceProcessor = new SceneSequenceEventQueueProcessor(); | ||
private readonly singleSceneProcessor: EventQueueProcessor; | ||
private readonly sceneSequenceProcessor: EventQueueProcessor; | ||
constructor(specDirectory: Path) { | ||
this.singleSceneProcessor = new SingleSceneEventQueueProcessor(specDirectory); | ||
this.sceneSequenceProcessor = new SceneSequenceEventQueueProcessor(specDirectory); | ||
} | ||
// todo: move `name` to Artifact and return Artifact[]... and sceneId? | ||
@@ -24,3 +32,3 @@ process(queues: DomainEventQueues): Array<{artifact: Artifact, name: Name, sceneId: CorrelationId }> { | ||
queues.forEach(queue => { | ||
const report: SerenityBDDReport = queue.first() instanceof SceneStarts | ||
const report: SerenityBDD4ReportSchema = queue.first() instanceof SceneStarts | ||
? this.singleSceneProcessor.process(queue) | ||
@@ -31,3 +39,3 @@ : this.sceneSequenceProcessor.process(queue) | ||
name: new Name(report.name), | ||
artifact: TestReport.fromJSON(report), | ||
artifact: TestReport.fromJSON(report as unknown as JSONObject), | ||
sceneId: queue.sceneId, | ||
@@ -34,0 +42,0 @@ }); |
import type { CorrelationId } from '@serenity-js/core/lib/model'; | ||
import type { TestStep } from '../SerenityBDDJsonSchema'; | ||
import type { TestStepSchema } from '../serenity-bdd-report-schema'; | ||
@@ -9,4 +9,4 @@ /** | ||
export interface LinkedTestStep { | ||
step: TestStep; | ||
step: TestStepSchema; | ||
parentActivityId: CorrelationId; | ||
} |
@@ -6,6 +6,6 @@ /* eslint-disable @typescript-eslint/ban-types */ | ||
import type { ErrorDetails } from '../../SerenityBDDJsonSchema'; | ||
import type { ErrorDetailsSchema } from '../../serenity-bdd-report-schema'; | ||
/** @package */ | ||
export function errorReportFrom(error?: Error | string | number | boolean | object): ErrorDetails { | ||
export function errorReportFrom(error?: Error | string | number | boolean | object): ErrorDetailsSchema { | ||
return { | ||
@@ -20,3 +20,3 @@ ...errorDetailsOf(error), | ||
/** @package */ | ||
function errorDetailsOf(maybeError: Error | string | number | boolean | object): ErrorDetails { | ||
function errorDetailsOf(maybeError: Error | string | number | boolean | object): ErrorDetailsSchema { | ||
return { | ||
@@ -23,0 +23,0 @@ errorType: errorTypeOf(maybeError), |
@@ -13,3 +13,3 @@ import type { | ||
import type { ErrorDetails } from '../../SerenityBDDJsonSchema'; | ||
import type { ErrorDetailsSchema } from '../../serenity-bdd-report-schema'; | ||
import { errorReportFrom } from './errorReportFrom'; | ||
@@ -20,4 +20,4 @@ | ||
*/ | ||
export function outcomeReportFrom(outcome: Outcome): { result: string, error?: ErrorDetails } { | ||
return match<Outcome, { result: string, error?: ErrorDetails }>(outcome). | ||
export function outcomeReportFrom(outcome: Outcome): { result: string, error?: ErrorDetailsSchema } { | ||
return match<Outcome, { result: string, error?: ErrorDetailsSchema }>(outcome). | ||
when(ExecutionCompromised, ({ error }: ExecutionCompromised) => | ||
@@ -24,0 +24,0 @@ ({ result: 'COMPROMISED', error: errorReportFrom(error) }) |
@@ -23,3 +23,3 @@ import type { DomainEventQueue } from '@serenity-js/core'; | ||
import type { SerenityBDDReport } from '../../SerenityBDDJsonSchema'; | ||
import type { SerenityBDD4ReportSchema } from '../../serenity-bdd-report-schema'; | ||
import { EventQueueProcessor } from '../EventQueueProcessor'; | ||
@@ -43,3 +43,3 @@ import type { SerenityBDDReportContext } from '../SerenityBDDReportContext'; | ||
process(queue: DomainEventQueue): SerenityBDDReport { | ||
process(queue: DomainEventQueue): SerenityBDD4ReportSchema { | ||
return queue.reduce((context, event) => | ||
@@ -64,3 +64,3 @@ // eslint-disable-next-line @typescript-eslint/indent | ||
.else(() => context), | ||
new SceneSequenceReportContext() // eslint-disable-line @typescript-eslint/indent | ||
new SceneSequenceReportContext(this.specDirectory) // eslint-disable-line @typescript-eslint/indent | ||
).build(); | ||
@@ -67,0 +67,0 @@ } |
import { ExecutionSuccessful } from '@serenity-js/core/lib/model'; | ||
import type { SerenityBDDReport } from '../../SerenityBDDJsonSchema'; | ||
import type { SerenityBDD4ReportSchema } from '../../serenity-bdd-report-schema'; | ||
import { SerenityBDDReportContext } from '../SerenityBDDReportContext'; | ||
@@ -14,3 +14,3 @@ import type { ScenarioParametersDescriptor } from './ScenarioParametersDescriptor'; | ||
build(): SerenityBDDReport { | ||
build(): SerenityBDD4ReportSchema { | ||
const report = super.build(); | ||
@@ -17,0 +17,0 @@ |
import type { ScenarioDetails, ScenarioParameters } from '@serenity-js/core/lib/model'; | ||
import type { DataTable, DataTableDataSetDescriptor } from '../../../SerenityBDDJsonSchema'; | ||
import type { DataTableDataSetDescriptorSchema, DataTableSchema } from '../../../serenity-bdd-report-schema'; | ||
import type { SceneSequenceReportContext } from '../SceneSequenceReportContext'; | ||
@@ -8,6 +8,6 @@ | ||
function descriptorFor(dataTable: DataTable) { | ||
function descriptorFor(dataTable: DataTableSchema) { | ||
const parameterSetDescription = parameters.description && parameters.description.value; | ||
const existingDescriptor: DataTableDataSetDescriptor = dataTable.dataSetDescriptors | ||
const existingDescriptor: DataTableDataSetDescriptorSchema = dataTable.dataSetDescriptors | ||
.find(descriptor => descriptor.name === parameters.name.value && descriptor.description === parameterSetDescription); | ||
@@ -35,3 +35,3 @@ | ||
const dataTable: DataTable = context.report.dataTable; | ||
const dataTable: DataTableSchema = context.report.dataTable; | ||
@@ -38,0 +38,0 @@ dataTable.headers = headers; |
import type { CorrelationId } from '@serenity-js/core/lib/model'; | ||
import type { Path } from '@serenity-js/core/src/io'; | ||
import type { SerenityBDDReport } from '../SerenityBDDJsonSchema'; | ||
import type { SerenityBDD4ReportSchema } from '../serenity-bdd-report-schema'; | ||
import type { LinkedTestStep } from './LinkedTestStep'; | ||
@@ -11,6 +12,9 @@ | ||
public readonly report: Partial<SerenityBDDReport> = {}; | ||
public readonly report: Partial<SerenityBDD4ReportSchema> = {}; | ||
public readonly steps: Map<string, LinkedTestStep> = new Map(); | ||
public currentActivityId: CorrelationId = undefined; | ||
constructor(public readonly specDirectory: Path) { | ||
} | ||
with(fn: (report: this) => this): this { | ||
@@ -20,3 +24,3 @@ return fn(this); | ||
build(): SerenityBDDReport { | ||
build(): SerenityBDD4ReportSchema { | ||
@@ -50,4 +54,4 @@ const eraseDuplicateExceptionReportFromParentSteps = (current: LinkedTestStep) => { | ||
testSteps, | ||
} as SerenityBDDReport; | ||
} as SerenityBDD4ReportSchema; | ||
} | ||
} |
@@ -20,3 +20,3 @@ import type { DomainEventQueue } from '@serenity-js/core'; | ||
import type { SerenityBDDReport } from '../../SerenityBDDJsonSchema'; | ||
import type { SerenityBDD4ReportSchema } from '../../serenity-bdd-report-schema'; | ||
import { EventQueueProcessor } from '../EventQueueProcessor'; | ||
@@ -37,3 +37,3 @@ import type { SerenityBDDReportContext } from '../SerenityBDDReportContext'; | ||
process(queue: DomainEventQueue): SerenityBDDReport { | ||
process(queue: DomainEventQueue): SerenityBDD4ReportSchema { | ||
return queue.reduce((context, event) => | ||
@@ -54,3 +54,3 @@ match<DomainEvent, SingleSceneReportContext>(event) | ||
.else(() => context), | ||
new SingleSceneReportContext() // eslint-disable-line @typescript-eslint/indent | ||
new SingleSceneReportContext(this.specDirectory) // eslint-disable-line @typescript-eslint/indent | ||
).build(); | ||
@@ -57,0 +57,0 @@ } |
@@ -18,3 +18,3 @@ import { Timestamp } from '@serenity-js/core'; | ||
linkedStep.step.exception = outcomeReport.error; | ||
linkedStep.step.duration = Timestamp.fromTimestampInMilliseconds(linkedStep.step.startTime).diff(finishedAt).inMilliseconds(); | ||
linkedStep.step.duration = Timestamp.fromJSON(linkedStep.step.startTime).diff(finishedAt).inMilliseconds(); | ||
@@ -21,0 +21,0 @@ context.currentActivityId = linkedStep.parentActivityId; |
import type { Timestamp } from '@serenity-js/core'; | ||
import type { CorrelationId, Name } from '@serenity-js/core/lib/model'; | ||
import type { TestStepSchema } from '../../serenity-bdd-report-schema'; | ||
import type { SerenityBDDReportContext } from '../SerenityBDDReportContext'; | ||
@@ -12,6 +13,12 @@ | ||
const step = { | ||
const step: TestStepSchema = { | ||
number: context.steps.size + 1, | ||
/** | ||
* It doesn't look like the TestStep.level was used anywhere in the Serenity BDD Reporter, | ||
* https://github.com/serenity-bdd/serenity-core/blob/5bebe8e77cf0c4ea99e0d3d1035d54822bcde9af/serenity-model/src/main/java/net/thucydides/model/domain/TestStep.java | ||
*/ | ||
// level: 0, | ||
// precondition: false, | ||
description: name.value, | ||
startTime: startedAt.toMilliseconds(), | ||
startTime: startedAt.toISOString(), | ||
children: [], | ||
@@ -18,0 +25,0 @@ reportData: [], |
@@ -17,2 +17,3 @@ import type { Timestamp } from '@serenity-js/core'; | ||
screenshot: path.basename(), | ||
screenshotName: path.basename(), | ||
timeStamp: timestamp.toMilliseconds(), | ||
@@ -19,0 +20,0 @@ }); |
@@ -10,3 +10,3 @@ import { Timestamp } from '@serenity-js/core'; | ||
return (context: Context): Context => { | ||
context.report.duration = Timestamp.fromTimestampInMilliseconds(context.report.startTime) | ||
context.report.duration = Timestamp.fromJSON(context.report.startTime) | ||
.diff(timestamp) | ||
@@ -13,0 +13,0 @@ .inMilliseconds(); |
@@ -10,3 +10,3 @@ import type { Timestamp } from '@serenity-js/core'; | ||
return (context: Context): Context => { | ||
context.report.startTime = context.report.startTime || timestamp.toMilliseconds(); | ||
context.report.startTime = context.report.startTime || timestamp.toISOString(); | ||
@@ -13,0 +13,0 @@ return context; |
@@ -15,3 +15,10 @@ import type { Path } from '@serenity-js/core/lib/io'; | ||
const category = ensure('scenario category', details.category.value, isNotBlank()); | ||
const storyName = escapeHtml(category); | ||
const requirementsHierarchy = requirementsHierarchyFromPath(context.specDirectory, details.location.path); | ||
const pathElements = requirementsHierarchy.map(name => ({ | ||
name, | ||
description: humanReadable(name), | ||
})); | ||
context.report.name = escapeHtml(name); | ||
@@ -23,7 +30,9 @@ context.report.title = escapeHtml(name); | ||
id: dashify(category), | ||
storyName: escapeHtml(category), | ||
path: isFeatureFile(details.location.path) | ||
? details.location.path.value | ||
: '', | ||
storyName: storyName, | ||
displayName: storyName, | ||
path: requirementsHierarchy.join('/'), | ||
type: 'feature', | ||
narrative: '', | ||
pathElements, | ||
}; | ||
@@ -35,8 +44,23 @@ | ||
/** | ||
* @package | ||
* @param {Path} path | ||
*/ | ||
function isFeatureFile(path: Path): boolean { | ||
return path && path.value.endsWith('.feature'); | ||
function requirementsHierarchyFromPath(specDirectory: Path, path: Path): string[] { | ||
const relative = specDirectory.relative(path); | ||
return relative.split().map((segment, i, segments) => { | ||
if (i < segments.length - 1) { | ||
return segment; | ||
} | ||
// If there is a dot in the file name, extract the substring before it; otherwise, use the entire string | ||
const firstDotIndex = segment.indexOf('.'); | ||
return firstDotIndex === -1 | ||
? segment | ||
: segment.slice(0, firstDotIndex); | ||
}); | ||
} | ||
function humanReadable(name: string): string { | ||
const result = name | ||
.split('_') | ||
.join(' '); | ||
return result.charAt(0).toUpperCase() + result.slice(1); | ||
} |
@@ -6,3 +6,3 @@ import type { Tag} from '@serenity-js/core/lib/model'; | ||
import type * as serenitybdd from '../../SerenityBDDJsonSchema'; | ||
import type * as serenitybdd from '../../serenity-bdd-report-schema'; | ||
import type { SerenityBDDReportContext } from '../SerenityBDDReportContext'; | ||
@@ -164,3 +164,3 @@ import { reportIdIncluding } from './reportIdIncluding'; | ||
function tagReportFor(tag: Tag): serenitybdd.Tag { | ||
function tagReportFor(tag: Tag): serenitybdd.TagSchema { | ||
return { | ||
@@ -180,3 +180,3 @@ ...tag.toJSON(), | ||
function displayNameOfRecorded(typeOfTag: { Type: string }, tags: serenitybdd.Tag[]) { | ||
function displayNameOfRecorded(typeOfTag: { Type: string }, tags: serenitybdd.TagSchema[]) { | ||
const found = (tags || []).find(t => t.type === typeOfTag.Type); | ||
@@ -183,0 +183,0 @@ |
@@ -10,6 +10,6 @@ import type { Name } from '@serenity-js/core/lib/model'; | ||
return (context: Context): Context => { | ||
context.report.testSource = name.value; | ||
context.report.testSource = name.value === 'Cucumber' ? name.value : 'JS'; | ||
return context; | ||
} | ||
} | ||
} |
@@ -1,8 +0,13 @@ | ||
import type { Stage, StageCrewMember } from '@serenity-js/core'; | ||
import { DomainEventQueues } from '@serenity-js/core'; | ||
import type { DomainEvent} from '@serenity-js/core/lib/events'; | ||
import type { Stage, StageCrewMember, StageCrewMemberBuilder, StageCrewMemberBuilderDependencies } from '@serenity-js/core'; | ||
import { ConfigurationError, DomainEventQueues } from '@serenity-js/core'; | ||
import type { DomainEvent } from '@serenity-js/core/lib/events'; | ||
import { ArtifactGenerated, AsyncOperationAttempted, AsyncOperationCompleted, AsyncOperationFailed, TestRunFinishes } from '@serenity-js/core/lib/events'; | ||
import type { FileSystem } from '@serenity-js/core/lib/io'; | ||
import { Path } from '@serenity-js/core/lib/io'; | ||
import { CorrelationId, Description, Name } from '@serenity-js/core/lib/model'; | ||
import { ensure, isDefined } from 'tiny-types'; | ||
import { EventQueueProcessors } from './processors'; | ||
import type { SerenityBDDReporterConfig } from './SerenityBDDReporterConfig'; | ||
import { SpecDirectory } from './SpecDirectory'; | ||
@@ -22,4 +27,8 @@ /** | ||
* crew: [ | ||
* ArtifactArchiver.storingArtifactsAt('./target/site/serenity'), | ||
* new SerenityBDDReporter() | ||
* ArtifactArchiver.fromJSON({ | ||
* outputDirectory: './target/site/serenity' | ||
* }), | ||
* SerenityBDDReporter.fromJSON({ | ||
* specDirectory: './features' // optional configuration | ||
* }) | ||
* ], | ||
@@ -55,4 +64,2 @@ * }) | ||
* // wdio.conf.ts | ||
* import { ArtifactArchiver } from '@serenity-js/core'; | ||
* import { SerenityBDDReporter } from '@serenity-js/serenity-bdd'; | ||
* import { WebdriverIOConfig } from '@serenity-js/webdriverio'; | ||
@@ -79,6 +86,2 @@ * | ||
* // protractor.conf.js | ||
* const | ||
* { ArtifactArchiver } = require('@serenity-js/core'), | ||
* { SerenityBDDReporter } = require('@serenity-js/serenity-bdd') | ||
* | ||
* exports.config = { | ||
@@ -100,2 +103,22 @@ * framework: 'custom', | ||
* | ||
* ## Configuring Serenity BDD Reporter | ||
* | ||
* To override Serenity BDD Reporter default configuration, provide a {@link SerenityBDDReporterConfig} as the second element of the {@link SerenityConfig.crew} array | ||
* using your test runner-specific configuration mechanism. | ||
* | ||
* For example, to change the default location | ||
* of the [requirements hierarchy root directory](https://serenity-bdd.github.io/docs/reporting/living_documentation#the-requirements-hierarchy), | ||
* specify the `specDirectory` property: | ||
* | ||
* ```js | ||
* crew: [ | ||
* [ '@serenity-js/serenity-bdd', { specDirectory: './features' } ], | ||
* // ... | ||
* ], | ||
* ``` | ||
* | ||
* ### Learn more: | ||
* - [Serenity BDD Reporter integration documentation](/handbook/reporting/serenity-bdd-reporter/) | ||
* - [Serenity/JS examples on GitHub](https://github.com/serenity-js/serenity-js/tree/main/examples) | ||
* | ||
* @group Stage | ||
@@ -105,8 +128,18 @@ */ | ||
private readonly eventQueues = new DomainEventQueues(); | ||
private readonly processors = new EventQueueProcessors(); | ||
private readonly processors: EventQueueProcessors; | ||
static fromJSON(config: SerenityBDDReporterConfig): StageCrewMemberBuilder<SerenityBDDReporter> { | ||
return new SerenityBDDReporterBuilder(config); | ||
} | ||
/** | ||
* @param [stage=undefined] stage | ||
* @param {Path} specDirectory | ||
* @param {Stage} [stage] | ||
* The stage this {@apilink StageCrewMember} should be assigned to | ||
*/ | ||
constructor(private stage?: Stage) { | ||
constructor( | ||
private readonly specDirectory: Path, | ||
private stage?: Stage, | ||
) { | ||
this.processors = new EventQueueProcessors(ensure('specDirectory', specDirectory, isDefined())); | ||
} | ||
@@ -172,1 +205,34 @@ | ||
} | ||
class SerenityBDDReporterBuilder implements StageCrewMemberBuilder<SerenityBDDReporter> { | ||
constructor(private readonly config: SerenityBDDReporterConfig) { | ||
} | ||
build({ stage, fileSystem }: StageCrewMemberBuilderDependencies): SerenityBDDReporter { | ||
ensure('stage', stage, isDefined()); | ||
ensure('fileSystem', fileSystem, isDefined()); | ||
return new SerenityBDDReporter(this.specDirectoryFrom(fileSystem), stage); | ||
} | ||
private specDirectoryFrom(fileSystem: FileSystem): Path { | ||
return this.config.specDirectory | ||
? this.userDefinedSpecDir(fileSystem, this.config.specDirectory) | ||
: this.guessedSpecDir(fileSystem); | ||
} | ||
private userDefinedSpecDir(fileSystem: FileSystem, configuredSpecDirectory: string): Path { | ||
const specDirectory = Path.from(configuredSpecDirectory); | ||
if (! fileSystem.exists(specDirectory)) { | ||
throw new ConfigurationError(`Configured specDirectory \`${ this.config.specDirectory }\` does not exist`); | ||
} | ||
return fileSystem.resolve(specDirectory); | ||
} | ||
private guessedSpecDir(fileSystem: FileSystem): Path { | ||
return new SpecDirectory(fileSystem).guessLocation(); | ||
} | ||
} |
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
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
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
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
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
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
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
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
420444
443
6395
48
+ Added@serenity-js/assertions@3.15.0(transitive)
+ Added@serenity-js/core@3.15.0(transitive)
+ Added@serenity-js/rest@3.15.0(transitive)
+ Addedaxios@1.6.5(transitive)
+ Addedmoment@2.30.1(transitive)
- Removed@serenity-js/assertions@3.14.2(transitive)
- Removed@serenity-js/core@3.14.2(transitive)
- Removed@serenity-js/rest@3.14.2(transitive)
- Removedaxios@1.6.2(transitive)
- Removedmoment@2.29.4(transitive)
Updated@serenity-js/core@3.15.0
Updated@serenity-js/rest@3.15.0
Updatedaxios@1.6.5