Skip to content
Permalink
Browse files
fix(serenity-bdd): serenityBDD reporter ignores any events that happe…
…n outside of the test

If @serenity-js/protractor~Photographer was configured to take screenshots of Activities performed
in Mocha's `after` hook, SerenityBDDReporter would attempt to record those events even though the scenario
has already finished. This failed attempt would then result in `TypeError: Cannot read property
'screenshots' of undefined`.
  • Loading branch information
jan-molak committed Jul 3, 2020
1 parent fb3e549 commit bb3b027b9b1aa3f4024dcadeb8df1483d5e18906
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 2 deletions.
@@ -35,7 +35,7 @@ describe('SerenityBDDReporter', () => {
reporter = env.reporter;
});

describe('reports the activities that took place during scenario execution:', () => {
describe('when reporting activities that took place during scenario execution', () => {

/**
* @test {SerenityBDDReporter}
@@ -64,6 +64,23 @@ describe('SerenityBDDReporter', () => {
expect(report.testSteps[0].result).to.equal('SUCCESS');
});

it('ignores any activities that occurred after the scene has finished', () => {
const pickACard = new ActivityDetails(new Name('Pick the default credit card'));

given(reporter).isNotifiedOfFollowingEvents(
new SceneStarts(defaultCardScenario),
new SceneFinished(defaultCardScenario, new ExecutionSuccessful()),
// activities that occur outside of the scenario, i.e. in Mocha's `after` hook, should be ignored by this reporter
new TaskStarts(pickACard),
new TaskFinished(pickACard, new ExecutionSuccessful()),
new TestRunFinishes(),
);

const report: SerenityBDDReport = stageManager.notifyOf.firstCall.lastArg.artifact.map(_ => _);

expect(report.testSteps).to.have.lengthOf(0);
});

/**
* @test {SerenityBDDReporter}
* @test {SceneStarts}
@@ -39,7 +39,7 @@ export class SerenityBDDReporter implements StageCrewMember {
this.reports.map(report => this.broadcast(report.toJSON()));
})
.else(e => {
if (this.currentStrategy.isSet()) {
if (this.currentStrategy.isSet() && ! this.currentStrategy.value.recordingFinished()) {
this.reports.save(this.currentStrategy.value.handle(e, this.reports.for(this.currentScenario.value)));
}
})
@@ -29,6 +29,8 @@ export abstract class SceneReportingStrategy {

abstract worksFor(anotherScenario: ScenarioDetails): boolean;

abstract recordingFinished(): boolean;

handle(event: DomainEvent, report: SceneReport): SceneReport {
return match<DomainEvent, SceneReport>(event)
.when(FeatureNarrativeDetected, (e: FeatureNarrativeDetected) => report.withFeatureNarrativeOf(e.description))
@@ -17,6 +17,10 @@ export class SceneSequenceReportingStrategy extends SceneReportingStrategy {
&& this.scenario.location.path.equals(anotherScenario.location.path);
}

recordingFinished(): boolean {
return false;
}

handle(event: DomainEvent, report: SceneReport): SceneReport {
return match<DomainEvent, SceneReport>(event)
.when(SceneStarts, (e: SceneStarts) => {
@@ -9,16 +9,24 @@ import { SceneReportingStrategy } from './SceneReportingStrategy';
* @package
*/
export class SingleSceneReportingStrategy extends SceneReportingStrategy {
private finished = false;

worksFor(anotherScenario: ScenarioDetails): boolean {
return this.scenario.equals(anotherScenario);
}

recordingFinished(): boolean {
return this.finished;
}

handle(event: DomainEvent, report: SceneReport): SceneReport {
return match<DomainEvent, SceneReport>(event)
.when(SceneStarts, (e: SceneStarts) => report.executionStartedAt(e.timestamp))
.when(ActivityStarts, (e: ActivityStarts) => report.activityStarted(e.value, e.timestamp))
.when(ActivityFinished, (e: ActivityFinished) => report.activityFinished(e.value, e.outcome, e.timestamp))
.when(SceneFinished, (e: SceneFinished) => {
this.finished = true;

return report
.executionFinishedAt(e.timestamp)
.executionFinishedWith(e.value, e.outcome)

0 comments on commit bb3b027

Please sign in to comment.