Permalink
Browse files

feat(protractor): support for multi-capability tests

affects: serenity-js

Each test is now tagged with the name of the browser that's been used to execute it.
This allows
for the test results to be filtered by browser name in the Serenity report.

ISSUES CLOSED: Closes #61
  • Loading branch information...
jan-molak committed Jul 15, 2017
1 parent 166fb06 commit bdeb5fbfc11c9c8445882f482874ea77dd399e87
@@ -40,7 +40,7 @@
"protractor": "5.x"
},
"dependencies": {
"@serenity-js/core": "^1.2.1",
"@serenity-js/core": ">= 1.4.0",
"@types/selenium-webdriver": "2.53.39",
"co": "4.6.0",
"glob": "7.1.1",
@@ -1,6 +1,6 @@
import { Serenity } from '@serenity-js/core';
import { ConsoleReporter, SerenityBDDReporter } from '@serenity-js/core/lib/reporting';
import { Config } from 'protractor';
import { Config, ProtractorBrowser } from 'protractor';
import { Runner } from 'protractor/built/runner';
import { SinonStub } from 'sinon';
@@ -12,6 +12,7 @@ import { Photographer } from '../../../../src/serenity-protractor/stage/photogra
import sinon = require('sinon');
import expect = require('../../../expect');
import { ProtractorBrowserDetector } from '../../../../src/serenity-protractor/reporting/protractor_browser_detector';
describe('serenity-protractor', () => {
@@ -30,7 +31,7 @@ describe('serenity-protractor', () => {
serenity: {
dialect: 'mocha',
},
}));
}), protractorBrowser('chrome'));
expect(framework).to.be.instanceOf(SerenityProtractorFramework);
expect(serenity.configure).to.have.been.calledWith(sinon.match({
@@ -39,6 +40,7 @@ describe('serenity-protractor', () => {
some(Photographer),
// core crew:
some(ProtractorReporter),
some(ProtractorBrowserDetector),
some(StandIns),
some(ProtractorNotifier),
],
@@ -54,14 +56,15 @@ describe('serenity-protractor', () => {
new ConsoleReporter(console.log),
],
},
}));
}), protractorBrowser('chrome'));
expect(framework).to.be.instanceOf(SerenityProtractorFramework);
expect(serenity.configure).to.have.been.calledWith(sinon.match({
crew: [
some(ConsoleReporter),
// core crew:
some(ProtractorReporter),
some(ProtractorBrowserDetector),
some(StandIns),
some(ProtractorNotifier),
],
@@ -70,7 +73,7 @@ describe('serenity-protractor', () => {
it('advises the developer what to do if the dialect could not be detected automatically', () => {
expect(() => {
const framework = new SerenityProtractorFramework(serenity, protractorRunner.withConfiguration({}));
const framework = new SerenityProtractorFramework(serenity, protractorRunner.withConfiguration({}), protractorBrowser('chrome'));
}).to.throw([
'Serenity/JS could not determine the test dialect you wish to use. ',
'Please add `serenity: { dialect: \'...\' }` to your Protractor configuration ',
@@ -89,6 +92,16 @@ describe('serenity-protractor', () => {
},
};
const protractorBrowser = (browserName: string) => {
const browser = {
getCapabilities: () => Promise.resolve({
get: (capability: string) => browserName,
}),
};
return browser as any;
};
const some = sinon.match.instanceOf;
});
});
@@ -22,7 +22,7 @@ describe('When working with Cucumber', function() {
describe('Serenity/JS', () => {
const stepApiTypes = 4;
const messagesPerStep = 4;
const messagesPerStep = 6;
const messagesPerFeature = stepApiTypes * messagesPerStep;
it ('reports passing scenarios', () => {
@@ -1,9 +1,9 @@
import { RecordedScene, SceneFinished, SceneStarts, Tag } from '@serenity-js/core/lib/domain';
import { lastOf } from '../../support/event_picker';
import { spawner } from '../../support/spawner';
import expect = require('../../expect');
import { spawner } from '../../support/spawner';
describe('When working with Cucumber', function() {
this.timeout(30 * 1000); // it might take a while to start up the selenium server
@@ -22,17 +22,16 @@ describe('When working with Cucumber', function() {
);
return expect(spawned.result).to.be.eventually.fulfilled.then(() => {
const sceneStarts = spawned.messages[0];
const sceneStarts = lastOf(SceneStarts, spawned.messages);
expect(sceneStarts).to.be.instanceOf(SceneStarts);
expect(sceneStarts.value).to.be.instanceOf(RecordedScene);
expect(sceneStarts.value.tags).to.deep.equal([
new Tag('cucumber'),
new Tag('regression'),
new Tag('issue', [ 'MY-PROJECT-123' ]),
]);
const sceneFinished = spawned.messages.pop();
const sceneFinished = lastOf(SceneFinished, spawned.messages);
expect(sceneFinished).to.be.instanceOf(SceneFinished);
expect(sceneFinished.value.subject).to.be.instanceOf(RecordedScene);
@@ -51,7 +50,7 @@ describe('When working with Cucumber', function() {
);
return expect(spawned.result).to.be.eventually.fulfilled.then(() => {
const sceneStarts = spawned.messages[0];
const sceneStarts = lastOf(SceneStarts, spawned.messages);
expect(sceneStarts).to.be.instanceOf(SceneStarts);
expect(sceneStarts.value).to.be.instanceOf(RecordedScene);
@@ -61,7 +60,7 @@ describe('When working with Cucumber', function() {
new Tag('issues', [ 'MY-PROJECT-123', 'MY-PROJECT-789' ]),
]);
const sceneFinished = spawned.messages.pop();
const sceneFinished = lastOf(SceneFinished, spawned.messages);
expect(sceneFinished).to.be.instanceOf(SceneFinished);
expect(sceneFinished.value.subject).to.be.instanceOf(RecordedScene);
@@ -1,5 +1,7 @@
import expect = require('../../expect');
import { ActivityFinished, ActivityStarts } from '@serenity-js/core/lib/domain';
import { lastOf } from '../../support/event_picker';
import { spawner } from '../../support/spawner';
describe('When working with Cucumber', function() {
@@ -18,7 +20,7 @@ describe('When working with Cucumber', function() {
describe('Serenity/JS', () => {
const messagesPerStep = 4;
const messagesPerStep = 6;
it ('reports data table arguments', () => {
const spawned = protractor('**/*special_step_arguments.feature', '@datatable');
@@ -27,8 +29,8 @@ describe('When working with Cucumber', function() {
expect(spawned.messages).to.have.lengthOf(messagesPerStep);
const
cucumberStepDescriptionFromActivityStartedMessage = spawned.messages[1].value.name,
cucumberStepDescriptionFromActivityFinishedMessage = spawned.messages[2].value.subject.name;
cucumberStepDescriptionFromActivityStartedMessage = lastOf(ActivityStarts, spawned.messages).value.name,
cucumberStepDescriptionFromActivityFinishedMessage = lastOf(ActivityFinished, spawned.messages).value.subject.name;
expect(cucumberStepDescriptionFromActivityStartedMessage).to.equal([
'Given the following accounts:',
@@ -49,8 +51,8 @@ describe('When working with Cucumber', function() {
expect(spawned.messages).to.have.lengthOf(messagesPerStep);
const
cucumberStepDescriptionFromActivityStartedMessage = spawned.messages[1].value.name,
cucumberStepDescriptionFromActivityFinishedMessage = spawned.messages[2].value.subject.name;
cucumberStepDescriptionFromActivityStartedMessage = lastOf(ActivityStarts, spawned.messages).value.name,
cucumberStepDescriptionFromActivityFinishedMessage = lastOf(ActivityFinished, spawned.messages).value.subject.name;
expect(cucumberStepDescriptionFromActivityStartedMessage).to.equal([
'Given an example.ts file with the following contents:',
@@ -22,7 +22,7 @@ describe('When working with Cucumber', function() {
describe('Serenity/JS', () => {
const stepApiTypes = 3;
const messagesPerStep = 4;
const messagesPerStep = 6;
const messagesPerFeature = stepApiTypes * messagesPerStep;
it ('reports timed-out scenarios', () => {
@@ -1,6 +1,7 @@
import expect = require('../../expect');
import { Result, SceneFinished } from '@serenity-js/core/lib/domain';
import { Result, SceneFinished, SceneStarts } from '@serenity-js/core/lib/domain';
import { lastOf } from '../../support/event_picker';
import { spawner } from '../../support/spawner';
describe('When working with Mocha', function() {
@@ -22,12 +23,11 @@ describe('When working with Mocha', function() {
);
return expect(spawned.result).to.be.eventually.fulfilled.then(() => {
expect(spawned.messages).to.have.lengthOf(2);
expect(spawned.messages).to.have.length.greaterThan(2);
const lastMessage = spawned.messages.pop();
const event = lastOf(SceneFinished, spawned.messages);
expect(lastMessage).to.be.instanceOf(SceneFinished);
expect(Result[lastMessage.value.result]).to.equal(Result[Result.SUCCESS]);
expect(Result[event.value.result]).to.equal(Result[Result.SUCCESS]);
});
});
@@ -37,12 +37,11 @@ describe('When working with Mocha', function() {
);
return expect(spawned.result).to.be.eventually.fulfilled.then(() => {
expect(spawned.messages).to.have.lengthOf(2);
expect(spawned.messages).to.have.length.greaterThan(2);
const lastMessage = spawned.messages.pop();
const event = lastOf(SceneFinished, spawned.messages);
expect(lastMessage).to.be.instanceOf(SceneFinished);
expect(Result[lastMessage.value.result]).to.equal(Result[Result.PENDING]);
expect(Result[event.value.result]).to.equal(Result[Result.PENDING]);
});
});
@@ -52,12 +51,11 @@ describe('When working with Mocha', function() {
);
return expect(spawned.result).to.be.eventually.fulfilled.then(() => {
expect(spawned.messages).to.have.lengthOf(2);
expect(spawned.messages).to.have.length.greaterThan(2);
const lastMessage = spawned.messages.pop();
const event = lastOf(SceneFinished, spawned.messages);
expect(lastMessage).to.be.instanceOf(SceneFinished);
expect(Result[lastMessage.value.result]).to.equal(Result[Result.PENDING]);
expect(Result[event.value.result]).to.equal(Result[Result.PENDING]);
});
});
@@ -68,12 +66,11 @@ describe('When working with Mocha', function() {
);
return expect(spawned.result).to.be.eventually.rejected.then(() => {
expect(spawned.messages).to.have.lengthOf(2);
expect(spawned.messages).to.have.length.greaterThan(2);
const lastMessage = spawned.messages.pop();
const event = lastOf(SceneFinished, spawned.messages);
expect(lastMessage).to.be.instanceOf(SceneFinished);
expect(Result[lastMessage.value.result]).to.equal(Result[Result.FAILURE]);
expect(Result[event.value.result]).to.equal(Result[Result.FAILURE]);
});
});
@@ -84,13 +81,12 @@ describe('When working with Mocha', function() {
);
return expect(spawned.result).to.be.eventually.rejected.then(() => {
expect(spawned.messages).to.have.lengthOf(2);
expect(spawned.messages).to.have.length.greaterThan(2);
const lastMessage = spawned.messages.pop();
const event = lastOf(SceneFinished, spawned.messages);
expect(lastMessage).to.be.instanceOf(SceneFinished);
expect(Result[lastMessage.value.result]).to.equal(Result[Result.FAILURE]);
expect(lastMessage.value.error).to.deep.equal({
expect(Result[event.value.result]).to.equal(Result[Result.FAILURE]);
expect(event.value.error).to.deep.equal({
actual: 'async pass',
expected: 'async fail',
message: 'expected \'async pass\' to equal \'async fail\'',
@@ -107,13 +103,12 @@ describe('When working with Mocha', function() {
);
return expect(spawned.result).to.be.eventually.rejected.then(() => {
expect(spawned.messages).to.have.lengthOf(2);
expect(spawned.messages).to.have.length.greaterThan(2);
const lastMessage = spawned.messages.pop();
const event = lastOf(SceneFinished, spawned.messages);
expect(lastMessage).to.be.instanceOf(SceneFinished);
expect(Result[lastMessage.value.result]).to.equal(Result[Result.ERROR]);
expect(lastMessage.value.error.message).to.match(/Timeout of 5ms exceeded./);
expect(Result[event.value.result]).to.equal(Result[Result.ERROR]);
expect(event.value.error.message).to.match(/Timeout of 5ms exceeded./);
});
});
@@ -124,13 +119,12 @@ describe('When working with Mocha', function() {
);
return expect(spawned.result).to.be.eventually.rejected.then(() => {
expect(spawned.messages).to.have.lengthOf(2);
expect(spawned.messages).to.have.length.greaterThan(2);
const lastMessage = spawned.messages.pop();
const event = lastOf(SceneFinished, spawned.messages);
expect(lastMessage).to.be.instanceOf(SceneFinished);
expect(Result[lastMessage.value.result]).to.equal(Result[Result.ERROR]);
expect(lastMessage.value.error.message).to.match(/Expected problem/);
expect(Result[event.value.result]).to.equal(Result[Result.ERROR]);
expect(event.value.error.message).to.match(/Expected problem/);
});
});
@@ -141,13 +135,12 @@ describe('When working with Mocha', function() {
);
return expect(spawned.result).to.be.eventually.rejected.then(() => {
expect(spawned.messages).to.have.lengthOf(2);
expect(spawned.messages).to.have.length.greaterThan(2);
const lastMessage = spawned.messages.pop();
const event = lastOf(SceneFinished, spawned.messages);
expect(lastMessage).to.be.instanceOf(SceneFinished);
expect(Result[lastMessage.value.result]).to.equal(Result[Result.ERROR]);
expect(lastMessage.value.error.message).to.match(/Expected async problem/);
expect(Result[event.value.result]).to.equal(Result[Result.ERROR]);
expect(event.value.error.message).to.match(/Expected async problem/);
});
});
@@ -157,10 +150,13 @@ describe('When working with Mocha', function() {
);
return expect(spawned.result).to.be.eventually.fulfilled.then(() => {
expect(spawned.messages).to.have.lengthOf(2);
expect(spawned.messages).to.have.length.greaterThan(2);
expect(spawned.messages[0].value.category).to.equal('Integration with Mocha');
expect(spawned.messages[1].value.subject.category).to.equal('Integration with Mocha');
const sceneStarts = lastOf(SceneStarts, spawned.messages);
const sceneFinished = lastOf(SceneFinished, spawned.messages);
expect(sceneStarts.value.category).to.equal('Integration with Mocha');
expect(sceneFinished.value.subject.category).to.equal('Integration with Mocha');
});
});
@@ -170,10 +166,13 @@ describe('When working with Mocha', function() {
);
return expect(spawned.result).to.be.eventually.fulfilled.then(() => {
expect(spawned.messages).to.have.lengthOf(2);
expect(spawned.messages).to.have.length.greaterThan(2);
const sceneStarts = lastOf(SceneStarts, spawned.messages);
const sceneFinished = lastOf(SceneFinished, spawned.messages);
expect(spawned.messages[0].value.name).to.equal('A sample test that passes');
expect(spawned.messages[1].value.subject.name).to.equal('A sample test that passes');
expect(sceneStarts.value.name).to.equal('A sample test that passes');
expect(sceneFinished.value.subject.name).to.equal('A sample test that passes');
});
});
@@ -183,12 +182,14 @@ describe('When working with Mocha', function() {
);
return expect(spawned.result).to.be.eventually.fulfilled.then(() => {
expect(spawned.messages).to.have.lengthOf(2);
expect(spawned.messages).to.have.length.greaterThan(2);
expect(spawned.messages[0].value.name).to.equal('A test with both setup and teardown that passes');
expect(spawned.messages[1].value.subject.name).to.equal('A test with both setup and teardown that passes');
const sceneStarts = lastOf(SceneStarts, spawned.messages);
const sceneFinished = lastOf(SceneFinished, spawned.messages);
expect(sceneStarts.value.name).to.equal('A test with both setup and teardown that passes');
expect(sceneFinished.value.subject.name).to.equal('A test with both setup and teardown that passes');
});
});
});
});
@@ -0,0 +1,3 @@
import { DomainEvent } from '@serenity-js/core/lib/domain';
export const lastOf = (type: typeof DomainEvent, events: Array<DomainEvent<any>>) => events.filter(e => e instanceof type).pop();
Oops, something went wrong.

0 comments on commit bdeb5fb

Please sign in to comment.