Skip to content
Permalink
Browse files
feat(core): new APIs to make configuring and using Serenity/JS easier
New APIs available in @serenity-js/core:
- `configure(config: SerenityConfig)` - allows to configure:
  - `actors: DressingRoom` - an implementation of the `DressingRoom` interface; a factory object preparing the Actors for the performance by giving them Abilities
  - `crew: StageCrewMember[]` - the StageCrewMembers, such as reporters
  - `cueTimeout: Duration` - the amout of time Serenity/JS waits for the async operations to complete when the scenario is finished. Those operations include saving the screenshots, generating JSON reports, waiting for the browser to be restarted, etc.
- `engage(actors: DressingRooom)` - allows to reset the type of `DressingRoom` implementation used; typically used in before each hooks of your test runner
- `actorCalled(name: string)` - creates or retrieves an actor by name. This is an alias for `stage.theActorCalled(name: string)`, which direct usage is no longer encouraged.
- `actorInTheSpotlight()` - retrieves the most recently accessed actor. This is an alias for `stage.theActorInTheSpotlight()`, which direct usage is no longer encouraged.

The `configure(...)` method supersedes the now deprecated `serenity.callToStageFor(actors)` and `serenity.setTheStage()`.
The `actorCalled(...)` and `actorInTheSpotlight()` are designed as replacements for accessing the `Stage` directly.

**While the superseded methods will continue to work for now, they have been marked as `deprecated` and using them will print a warning message to the terminal when the tests are executed.**

Please see the example implementations in the `examples` folder to help with making the necessary updates to your code base.
A step-by-step setup guide will be described in the Serenity/JS Handbook shortly.
  • Loading branch information
jan-molak committed Jan 25, 2020
1 parent 9840023 commit d11a80de66519cb16b6eaa61a39694006a76b5fb
Showing with 962 additions and 943 deletions.
  1. +12 −15 examples/cucumber-domain-level-testing/features/step_definitions/domain-level.steps.ts
  2. +0 −20 examples/cucumber-domain-level-testing/features/support/configure_serenity.ts
  3. +17 −0 examples/cucumber-domain-level-testing/features/support/setup.ts
  4. +1 −1 examples/cucumber-domain-level-testing/package.json
  5. +13 −18 examples/cucumber-rest-api-level-testing/features/step_definitions/api-level.steps.ts
  6. +0 −19 examples/cucumber-rest-api-level-testing/features/support/configure_serenity.ts
  7. +17 −0 examples/cucumber-rest-api-level-testing/features/support/setup.ts
  8. +1 −1 examples/cucumber-rest-api-level-testing/package.json
  9. +17 −14 examples/protractor-cucumber/features/step_definitions/ui.steps.ts
  10. +1 −8 examples/protractor-cucumber/features/support/setup.ts
  11. +0 −6 examples/protractor-jasmine-todomvc/spec/config/configure_stage.ts
  12. +23 −32 examples/protractor-jasmine-todomvc/spec/manage_a_todo_list.spec.ts
  13. +0 −6 examples/protractor-jasmine/spec/config/configure_stage.ts
  14. +8 −6 examples/protractor-jasmine/spec/interactions.spec.ts
  15. +13 −17 integration/cucumber-1-runner/src/step_definitions/screenplay.steps.ts
  16. +9 −10 integration/cucumber-1-runner/src/support/configure_serenity.ts
  17. +13 −17 integration/cucumber-2-runner/src/step_definitions/screenplay.steps.ts
  18. +10 −11 integration/cucumber-2-runner/src/support/configure_serenity.ts
  19. +13 −17 integration/cucumber-3-runner/src/step_definitions/screenplay.steps.ts
  20. +10 −11 integration/cucumber-3-runner/src/support/configure_serenity.ts
  21. +13 −17 integration/cucumber-4-runner/src/step_definitions/screenplay.steps.ts
  22. +8 −9 integration/cucumber-4-runner/src/support/configure_serenity.ts
  23. +13 −17 integration/cucumber-5-runner/src/step_definitions/screenplay.steps.ts
  24. +8 −9 integration/cucumber-5-runner/src/support/configure_serenity.ts
  25. +13 −17 integration/cucumber-6-runner/src/step_definitions/screenplay.steps.ts
  26. +8 −9 integration/cucumber-6-runner/src/support/configure_serenity.ts
  27. +6 −4 integration/cucumber/features/support/configure_serenity.ts
  28. +2 −4 integration/jasmine/examples/failing/screenplay-assertion-error.spec.js
  29. +6 −4 integration/jasmine/examples/setup.js
  30. +9 −0 integration/protractor-jasmine/examples/Actors.js
  31. +5 −14 integration/protractor-jasmine/examples/multiple_passing_scenarios.spec.js
  32. +3 −1 integration/protractor-jasmine/examples/protractor.conf.js
  33. +5 −10 integration/protractor-jasmine/examples/screenplay.spec.js
  34. +6 −8 packages/assertions/spec/Check.spec.ts
  35. +62 −60 packages/assertions/spec/Ensure.spec.ts
  36. +7 −8 packages/assertions/spec/Expectation.spec.ts
  37. +5 −7 packages/assertions/spec/expectations/and.spec.ts
  38. +4 −7 packages/assertions/spec/expectations/contain.spec.ts
  39. +5 −7 packages/assertions/spec/expectations/containAtLeastOneItemThat.spec.ts
  40. +5 −7 packages/assertions/spec/expectations/containItemsWhereEachItem.spec.ts
  41. +4 −6 packages/assertions/spec/expectations/endsWith.spec.ts
  42. +5 −7 packages/assertions/spec/expectations/equals.spec.ts
  43. +4 −6 packages/assertions/spec/expectations/includes.spec.ts
  44. +4 −6 packages/assertions/spec/expectations/isAfter.spec.ts
  45. +4 −6 packages/assertions/spec/expectations/isBefore.spec.ts
  46. +4 −6 packages/assertions/spec/expectations/isGreaterThan.spec.ts
  47. +4 −6 packages/assertions/spec/expectations/isLessThan.spec.ts
  48. +4 −6 packages/assertions/spec/expectations/matches.spec.ts
  49. +16 −17 packages/assertions/spec/expectations/not.spec.ts
  50. +5 −7 packages/assertions/spec/expectations/or.spec.ts
  51. +4 −6 packages/assertions/spec/expectations/property.spec.ts
  52. +4 −6 packages/assertions/spec/expectations/startsWith.spec.ts
  53. +5 −0 packages/assertions/spec/setup.spec.ts
  54. +3 −3 packages/console-reporter/src/stage/crew/console-reporter/ConsoleReporter.ts
  55. +10 −8 packages/core/spec/Serenity.spec.ts
  56. +115 −12 packages/core/src/Serenity.ts
  57. +11 −0 packages/core/src/SerenityConfig.ts
  58. +1 −0 packages/core/src/index.ts
  59. +19 −1 packages/core/src/instance.ts
  60. +12 −8 packages/core/src/screenplay/actor/Actor.ts
  61. +17 −4 packages/core/src/stage/Stage.ts
  62. +2 −0 packages/core/src/stage/WithStage.ts
  63. +6 −6 packages/core/src/stage/crew/stream-reporter/StreamReporter.ts
  64. +4 −3 packages/cucumber/spec/listeners/CucumberEventProtocolAdapter.spec.ts
  65. +1 −1 packages/jasmine/spec/SerenityReporterForJasmine.spec.ts
  66. +14 −12 packages/local-server/spec/reporting.spec.ts
  67. +23 −15 packages/local-server/spec/servers.spec.ts
  68. +5 −0 packages/local-server/spec/setup.spec.ts
  69. +1 −1 packages/protractor/spec/adapter/reporter/ProtractorReporter.spec.ts
  70. +6 −9 packages/protractor/spec/expectations/isClickable.spec.ts
  71. +5 −8 packages/protractor/spec/expectations/isEnabled.spec.ts
  72. +5 −8 packages/protractor/spec/expectations/isPresent.spec.ts
  73. +6 −9 packages/protractor/spec/expectations/isSelected.spec.ts
  74. +5 −8 packages/protractor/spec/expectations/isVisible.spec.ts
  75. +7 −10 packages/protractor/spec/screenplay/interactions/Clear.spec.ts
  76. +3 −5 packages/protractor/spec/screenplay/interactions/Click.spec.ts
  77. +3 −5 packages/protractor/spec/screenplay/interactions/DoubleClick.spec.ts
  78. +6 −8 packages/protractor/spec/screenplay/interactions/Enter.spec.ts
  79. +3 −5 packages/protractor/spec/screenplay/interactions/Hover.spec.ts
  80. +6 −8 packages/protractor/spec/screenplay/interactions/Navigate.spec.ts
  81. +4 −6 packages/protractor/spec/screenplay/interactions/Press.spec.ts
  82. +4 −9 packages/protractor/spec/screenplay/interactions/ResizeBrowserWindow.spec.ts
  83. +3 −5 packages/protractor/spec/screenplay/interactions/Scroll.spec.ts
  84. +8 −10 packages/protractor/spec/screenplay/interactions/TakeScreenshot.spec.ts
  85. +4 −7 packages/protractor/spec/screenplay/interactions/UseAngular.spec.ts
  86. +5 −9 packages/protractor/spec/screenplay/interactions/Wait.spec.ts
  87. +23 −25 packages/protractor/spec/screenplay/interactions/execute-script/ExecuteAsynchronousScript.spec.ts
  88. +6 −9 packages/protractor/spec/screenplay/interactions/execute-script/ExecuteScriptFromUrl.spec.ts
  89. +23 −25 packages/protractor/spec/screenplay/interactions/execute-script/ExecuteSynchronousScript.spec.ts
  90. +2 −5 packages/protractor/spec/screenplay/questions/Attribute.spec.ts
  91. +4 −8 packages/protractor/spec/screenplay/questions/Browser.spec.ts
  92. +3 −6 packages/protractor/spec/screenplay/questions/CSSClasses.spec.ts
  93. +3 −3 packages/protractor/spec/screenplay/questions/Cookie.spec.ts
  94. +12 −15 packages/protractor/spec/screenplay/questions/LastScriptExecution.spec.ts
  95. +19 −22 packages/protractor/spec/screenplay/questions/Pick.spec.ts
  96. +13 −15 packages/protractor/spec/screenplay/questions/Target.spec.ts
  97. +5 −7 packages/protractor/spec/screenplay/questions/Text.spec.ts
  98. +4 −7 packages/protractor/spec/screenplay/questions/Value.spec.ts
  99. +3 −6 packages/protractor/spec/screenplay/questions/Website.spec.ts
  100. +8 −0 packages/protractor/spec/setup.spec.ts
  101. +2 −5 packages/protractor/src/adapter/Config.ts
  102. +6 −2 packages/protractor/src/adapter/ProtractorFrameworkAdapter.ts
  103. +7 −4 packages/rest/spec/actors.ts
  104. +23 −18 packages/rest/spec/screenplay/interactions/Send.spec.ts
  105. +5 −0 packages/rest/spec/setup.spec.ts
  106. +2 −5 packages/serenity-bdd/src/cli/bootstrap.ts
  107. +12 −10 packages/serenity-bdd/src/cli/commands/run.ts
  108. +12 −10 packages/serenity-bdd/src/cli/commands/update.ts
@@ -1,34 +1,31 @@
import { Operand, Operator } from '@serenity-js-examples/calculator-app';
import { Ensure, equals } from '@serenity-js/assertions';
import { WithStage } from '@serenity-js/core';
import { actorCalled, actorInTheSpotlight } from '@serenity-js/core';
import { Given, Then, When } from 'cucumber';
import { EnterOperand, RequestANewCalculation, ResultOfCalculation, UseOperator } from '../support/screenplay';

Given(/^(.*) has requested a new calculation/, function (this: WithStage, actorName: string) {
return this.stage.theActorCalled(actorName).attemptsTo(
Given(/^(.*) has requested a new calculation/, (actorName: string) =>
actorCalled(actorName).attemptsTo(
RequestANewCalculation(),
);
});
));

When(/^(.*) enters (\d+)$/, function (this: WithStage, actorName: string, operandValue: string) {
const actor = ! isPronoun(actorName) ? this.stage.actor(actorName) : this.stage.theActorInTheSpotlight();
When(/^(.*) enters (\d+)$/, (actorName: string, operandValue: string) => {
const actor = ! isPronoun(actorName) ? actorCalled(actorName) : actorInTheSpotlight();

return actor.attemptsTo(
EnterOperand(new Operand(parseFloat(operandValue))),
);
});

When(/(?:he|she|they) uses? the (.) operator/, function (this: WithStage, operatorSymbol: string) {
return this.stage.theActorInTheSpotlight().attemptsTo(
When(/(?:he|she|they) uses? the (.) operator/, (operatorSymbol: string) =>
actorInTheSpotlight().attemptsTo(
UseOperator(Operator.fromString(operatorSymbol)),
);
});
));

Then(/(?:he|she|they) should get a result of (\d+)/, function (this: WithStage, expectedResult: string) {
return this.stage.theActorInTheSpotlight().attemptsTo(
Then(/(?:he|she|they) should get a result of (\d+)/, (expectedResult: string) =>
actorInTheSpotlight().attemptsTo(
Ensure.that(ResultOfCalculation(), equals(parseFloat(expectedResult))),
);
});
));

function isPronoun(actorName: string) {
return !!~ ['he', 'she', 'they'].indexOf(actorName);

This file was deleted.

@@ -0,0 +1,17 @@
import { ConsoleReporter } from '@serenity-js/console-reporter';
import { ArtifactArchiver, configure } from '@serenity-js/core';
import { SerenityBDDReporter } from '@serenity-js/serenity-bdd';

import { setDefaultTimeout } from 'cucumber';
import { Actors } from './screenplay';

configure({
actors: new Actors(),
crew: [
ArtifactArchiver.storingArtifactsAt('./target/site/serenity'),
new SerenityBDDReporter(),
ConsoleReporter.forDarkTerminals(),
],
});

setDefaultTimeout(1000);
@@ -19,7 +19,7 @@
"clean": "rimraf target",
"lint": "tslint --project tsconfig-lint.json --config ../../tslint.json --format stylish",
"test:update-serenity": "serenity-bdd update --ignoreSSL",
"test:acceptance": "cucumber-js --require-module ts-node/register --format node_modules/@serenity-js/cucumber --require ./features/step_definitions/domain-level.steps.ts --require ./features/support/configure_serenity.ts",
"test:acceptance": "cucumber-js --require-module ts-node/register --format node_modules/@serenity-js/cucumber --require ./features/step_definitions/domain-level.steps.ts --require ./features/support/setup.ts",
"test:report": "serenity-bdd run",
"test": "failsafe clean test:update-serenity test:acceptance test:report",
"verify": "npm test"
@@ -1,32 +1,27 @@
import { equals } from '@serenity-js/assertions';
import { WithStage } from '@serenity-js/core';
import { actorCalled, actorInTheSpotlight } from '@serenity-js/core';
import { LocalServer, StartLocalServer, StopLocalServer } from '@serenity-js/local-server';
import { ChangeApiUrl, LastResponse } from '@serenity-js/rest';
import { After, Before, Then, When } from 'cucumber';
import { RequestCalculationOf, VerifyResultAt } from '../support/screenplay';

Before(function () {
return this.stage.theActorCalled('Apisitt').attemptsTo( // todo: change to Maggie
Before(() =>
actorCalled('Apisitt').attemptsTo(
StartLocalServer.onRandomPort(),
ChangeApiUrl.to(LocalServer.url()),
// TakeNote.of(LocalServer.url()) // Question or Question<Promise>; Pass between actors
);
});
));

When(/^(.*) asks for the following calculation: (.*)$/, function (this: WithStage, actorName: string, expression: string) {
return this.stage.actor(actorName).attemptsTo(
When(/^(.*) asks for the following calculation: (.*)$/, (actorName: string, expression: string) =>
actorCalled(actorName).attemptsTo(
RequestCalculationOf(expression),
);
});
));

Then(/(?:he|she|they) should get a result of ([\d-.]+)/, function (this: WithStage, expectedResult: string) {
return this.stage.theActorInTheSpotlight().attemptsTo(
Then(/(?:he|she|they) should get a result of ([\d-.]+)/, (expectedResult: string) =>
actorInTheSpotlight().attemptsTo(
VerifyResultAt(LastResponse.header('location'), equals({ result: Number(expectedResult) })),
);
});
));

After(function () {
return this.stage.theActorCalled('Apisitt').attemptsTo(
After(() =>
actorCalled('Apisitt').attemptsTo(
StopLocalServer.ifRunning(),
);
});
));

This file was deleted.

@@ -0,0 +1,17 @@
import { ConsoleReporter } from '@serenity-js/console-reporter';
import { ArtifactArchiver, configure } from '@serenity-js/core';
import { SerenityBDDReporter } from '@serenity-js/serenity-bdd';

import { setDefaultTimeout } from 'cucumber';
import { Actors } from './screenplay';

configure({
actors: new Actors(),
crew: [
ArtifactArchiver.storingArtifactsAt('./target/site/serenity'),
new SerenityBDDReporter(),
ConsoleReporter.forDarkTerminals(),
],
});

setDefaultTimeout(1000);
@@ -19,7 +19,7 @@
"clean": "rimraf target",
"lint": "tslint --project tsconfig-lint.json --config ../../tslint.json --format stylish",
"test:update-serenity": "serenity-bdd update --ignoreSSL",
"test:acceptance": "cucumber-js --require-module ts-node/register --format node_modules/@serenity-js/cucumber --require ./features/step_definitions/api-level.steps.ts --require ./features/support/configure_serenity.ts",
"test:acceptance": "cucumber-js --require-module ts-node/register --format node_modules/@serenity-js/cucumber --require ./features/step_definitions/api-level.steps.ts --require ./features/support/setup.ts",
"test:report": "serenity-bdd run",
"test": "failsafe clean test:update-serenity test:acceptance test:report",
"verify": "npm test"
@@ -1,25 +1,28 @@
import { Ensure, equals } from '@serenity-js/assertions';
import { WithStage } from '@serenity-js/core';
import { actorCalled, actorInTheSpotlight, engage } from '@serenity-js/core';
import { LocalServer, StartLocalServer, StopLocalServer } from '@serenity-js/local-server';
import { Navigate, UseAngular, Website } from '@serenity-js/protractor';
import { After, Then, When } from 'cucumber';
import { After, Before, Then, When } from 'cucumber';
import { Actors } from '../support/screenplay';

When(/^(.*) navigates to the test website$/, function(this: WithStage, actorName: string) {
return this.stage.actor(actorName).attemptsTo(
Before(() => {
console.log('Cucumber :: sneario-level before')
engage(new Actors())
});

When(/^(.*) navigates to the test website$/, (actorName: string) =>
actorCalled(actorName).attemptsTo(
StartLocalServer.onRandomPort(),
UseAngular.disableSynchronisation(),
Navigate.to(LocalServer.url()),
);
});
));

Then(/(?:he|she|they) should see the title of "(.*)"/, function(this: WithStage, expectedTitle: string) {
return this.stage.theActorInTheSpotlight().attemptsTo(
Then(/(?:he|she|they) should see the title of "(.*)"/, (expectedTitle: string) =>
actorInTheSpotlight().attemptsTo(
Ensure.that(Website.title(), equals(expectedTitle)),
);
});
));

After(function () {
return this.stage.theActorCalled('Umbra').attemptsTo(
After(() =>
actorCalled('Umbra').attemptsTo(
StopLocalServer.ifRunning(),
);
});
));
@@ -1,10 +1,3 @@
import { serenity, WithStage } from '@serenity-js/core';

import { setDefaultTimeout, setWorldConstructor } from 'cucumber';
import { Actors } from './screenplay';
import { setDefaultTimeout } from 'cucumber';

setDefaultTimeout(1000);

setWorldConstructor(function (this: WithStage, { parameters }) {
this.stage = serenity.callToStageFor(new Actors());
});

This file was deleted.

@@ -1,34 +1,31 @@
import { contain, Ensure, equals, property } from '@serenity-js/assertions';
import { Interaction, WithStage } from '@serenity-js/core';
import { actorCalled, actorInTheSpotlight, engage } from '@serenity-js/core';
import { Actors } from './support';
import { ClearLocalStorage, RecordedItems, RecordItem, RemoveItem, RenameItem, Start } from './support/screenplay';

describe('Managing a Todo List', () => {

afterEach(function (this: WithStage) {
return this.stage.theActorInTheSpotlight().attemptsTo(
ClearLocalStorage(),
);
});
beforeEach(() => engage(new Actors()));

afterEach(() => actorInTheSpotlight().attemptsTo(
ClearLocalStorage(),
));

describe('TodoMVC', () => {

describe('actor', () => {

it('records new items', function (this: WithStage) {
return this.stage.theActorCalled('Jasmine').attemptsTo(
Start.withAnEmptyList(),
RecordItem.called('Walk a dog'),
Ensure.that(RecordedItems(), contain('Walk a dog')),
);
});

it('removes the recorded items', function (this: WithStage) {
return this.stage.theActorCalled('Jasmine').attemptsTo(
Start.withAListContaining('Walk a dog'),
RemoveItem.called('Walk a dog'),
Ensure.that(RecordedItems(), property('length', equals(0))),
);
});
it('records new items', () => actorCalled('Jasmine').attemptsTo(
Start.withAnEmptyList(),
RecordItem.called('Walk a dog'),
Ensure.that(RecordedItems(), contain('Walk a dog')),
));

it('removes the recorded items', () => actorCalled('Jasmine').attemptsTo(
Start.withAListContaining('Walk a dog'),
RemoveItem.called('Walk a dog'),
Ensure.that(RecordedItems(), property('length', equals(0))),
));

// it('marks an item as completed', function (this: WithStage) {
// return this.stage.theActorCalled('Jasmine').attemptsTo(
@@ -37,17 +34,11 @@ describe('Managing a Todo List', () => {
// );
// });

it('edits an item', function (this: WithStage) {
return this.stage.theActorCalled('Jasmine').attemptsTo(
Start.withAListContaining('Buy a cake'),
RenameItem.called('Buy a cake').to('Buy an apple'),
Ensure.that(RecordedItems(), contain('Buy an apple')),
);
});
it('edits an item', () => actorCalled('Jasmine').attemptsTo(
Start.withAListContaining('Buy a cake'),
RenameItem.called('Buy a cake').to('Buy an apple'),
Ensure.that(RecordedItems(), contain('Buy an apple')),
));
});
});
});

const Debug = () => Interaction.where(`#actor pauses execution using a debugger`, actor => {
debugger; // tslint:disable-line:no-debugger
});

This file was deleted.

@@ -1,21 +1,23 @@
import { Ensure, equals } from '@serenity-js/assertions';
import { actorCalled, actorInTheSpotlight, engage } from '@serenity-js/core';
import { LocalServer, StartLocalServer, StopLocalServer } from '@serenity-js/local-server';
import { Navigate, UseAngular, Website } from '@serenity-js/protractor';
import { Actors } from './support/Actors';

describe('Interaction flow', () => {

beforeEach(() => engage(new Actors()));

it('enables the actor to interact with the website', function () {
return this.stage.theActorCalled('Jasmine').attemptsTo(
return actorCalled('Jasmine').attemptsTo(
StartLocalServer.onRandomPort(),
UseAngular.disableSynchronisation(),
Navigate.to(LocalServer.url()),
Ensure.that(Website.title(), equals('Test Website')),
);
});

afterEach(function () {
return this.stage.theActorInTheSpotlight().attemptsTo(
StopLocalServer.ifRunning(),
);
});
afterEach(() => actorInTheSpotlight().attemptsTo(
StopLocalServer.ifRunning(),
));
});

0 comments on commit d11a80d

Please sign in to comment.