Skip to content
Permalink
Browse files
feat(cucumber): cucumber adapter reports ambiguous step defs
affects: @serenity-js/cucumber, @integration/cucumber
  • Loading branch information
jan-molak committed Jul 29, 2018
1 parent 3a43c48 commit cf1ca5020973547984b458600aae82624e428865
@@ -0,0 +1,9 @@
export = function() {
this.Given(/^.*step (?:.*) passes$/, function() {
return void 0;
});

this.Given(/^.*step (?:.*) passes$/, function() {
return void 0;
});
};
@@ -0,0 +1,58 @@
import { expect, ifExitCodeIsOtherThan, logOutput } from '@integration/testing-tools';
import {
ActivityFinished,
ActivityStarts,
SceneFinished,
SceneStarts,
SceneTagged,
TestRunnerDetected,
} from '@serenity-js/core/lib/events';
import { ExecutionFailedWithError, FeatureTag, Name } from '@serenity-js/core/lib/model';

import 'mocha';

import { cucumber, Pick } from '../src';

describe('@serenity-js/cucumber', function() {

this.timeout(5000);

it('recognises scenarios with ambiguous steps', () =>
cucumber(
'--require', 'features/support/configure_serenity.ts',
'--require', `features/step_definitions/ambiguous.steps.ts`,
'--require', 'node_modules/@serenity-js/cucumber/register.js',
'features/passing_scenario.feature',
).
then(ifExitCodeIsOtherThan(1, logOutput)).
then(res => {
expect(res.exitCode).to.equal(1);

expect(res.events).to.have.lengthOf(6);

Pick.from(res.events)
.next(SceneStarts, event => expect(event.value.name).to.equal(new Name('A passing scenario')))
.next(TestRunnerDetected, event => expect(event.value).to.equal(new Name('Cucumber')))
.next(SceneTagged, event => expect(event.tag).to.equal(new FeatureTag('Serenity/JS recognises a passing scenario')))
.next(ActivityStarts, event => expect(event.value.name).to.equal(new Name('Given a step that passes')))
.next(ActivityFinished, event => {
expect(event.outcome).to.be.instanceOf(ExecutionFailedWithError);

const err = (event.outcome as ExecutionFailedWithError).error;

const lines = err.message.split('\n');

expect(lines[0]).to.equal('Each step should have one matching step definition, yet there are several:');
expect(lines[1]).to.contain('ambiguous.steps.ts:2');
expect(lines[2]).to.contain('ambiguous.steps.ts:6');
})
.next(SceneFinished, event => {
expect(event.outcome).to.be.instanceOf(ExecutionFailedWithError);

const err = (event.outcome as ExecutionFailedWithError).error;

expect(err.message).to.equal('Ambiguous step definition detected');
})
;
}));
});
@@ -102,11 +102,19 @@ export class Notifier {
}

private stepOutcomeFrom(result: cucumber.events.StepResultPayload): Outcome {
// todo: catchProblemsWithAmbiguousStepDefinitions
const ambiguousStepDefinitions = result.getAmbiguousStepDefinitions() || [];
const ambiguousStepsDetected = ambiguousStepDefinitions.length > 0
? ambiguousStepDefinitions
.map(step => `${step.getPattern().toString()} - ${step.getUri()}:${step.getLine()}`)
.reduce((err: Error, issue) => {
err.message += `\n${issue}`;
return err;
}, new Error('Each step should have one matching step definition, yet there are several:'))
: void 0;

const
status: string = result.getStatus(),
error: Error = result.getFailureException();
error: Error = result.getFailureException() || ambiguousStepsDetected;

return this.outcomeFrom(status, error);
}
@@ -121,7 +129,12 @@ export class Notifier {
return new ImplementationPending();

case status === 'ambiguous':
return new ExecutionFailedWithError(error); // todo: does this throw an error?
if (! error) {
// Only the step result contains the "ambiguous step def error", the scenario itself doesn't
return new ExecutionFailedWithError(new Error('Ambiguous step definition detected'));
}

return new ExecutionFailedWithError(error);

case status === 'failed':
return new ExecutionFailedWithError(error);

0 comments on commit cf1ca50

Please sign in to comment.