The Stage

The Stage is the central place where the action of a test scenario takes place, and where the actors perform their activities.

The stage can be instantiated using the serenity.callToStageFor(cast: Cast) method, which requires you to provide an object representing the custom cast of actors, appropriate for your domain:

import { serenity } from 'serenity-js';

let stage = serenity.callToStageFor(/* custom cast */);

Where the custom Cast instantiates the actors based on their name:

Error: marker `cast` not found

Instantiating the actors

In many cases, the system under test exposes only one interface with which the test scenarios will interact - the web interface, for example.

If there's no need for variability amongst the actors, it's often enough to define the custom Cast inline:

import { serenity } from 'serenity-js';
import { protractor } from 'protractor';
import { Actor, BrowseTheWeb } from 'serenity-js/protractor'

let stage = serenity.callToStageFor({
    actor: name => Actor.named(name).whoCan(BrowseTheWeb.using(protractor.browser)),
});

However, many more heterogeneous systems expose additional interfaces - REST APIs, messaging queues, batch processing servers that require a file to be uploaded via FTP and so on.

In those scenarios, it's more convenient to have a designated class responsible for instantiating the actors, such as this one:

import { Actor, BrowseTheWeb, Cast } from 'serenity-js/protractor'

import { protractor } from 'protractor';

// some custom, project-specific abilities
import { Authenticate, InteractWithTheAPI } from './abilities'

export class Bloggers implements Cast {
    actor(name: string): Actor {
        switch(name) {
            case 'Maria':
                return Actor.named(name).whoCan(
                    InteractWithTheAPI.using('some-authentication-token')
                );
            case 'Wendy': 
            case 'William':
            default:
                return Actor.named(name).whoCan(
                    BrowseTheWeb.using(protractor.browser),
                    Authenticate.using(name, 'P@ssw0rd1'),
                );
        }
    }
}

And then:

import { serenity } from 'serenity-js';

// project-specific actors
import { Bloggers } from './bloggers';

let stage = serenity.callToStageFor(new Bloggers());

Working with the actors

Once the Stage is set up, you can retrieve an actor by their name:

let wendy = stage.theActorCalled('Wendy');

In a typical Mocha test, you'd see:

import { serenity } from 'serenity-js';

describe('Wendy can edit an article that', () => {

    const stage = serenity.callToStageFor(new Bloggers());

    it('is pending correction', () => stage.theActorCalled('Wendy').attemptsTo(
        /* tasks related to editing an article */
    ));    
})

Calling an actor to the stage puts them in the spotlight.

When you instantiate an actor using stage.theActorCalled(name) the Stage will remember the last actor you worked with. This way you can work with them again without having to use local variables and state.

This feature is particularly useful when working with Cucumber as it helps to keep the step definition libraries and "The World" clean, as we can instantiate the actor in the first step of the scenario, and then simply reuse it in subsequent steps:

this.Given(/^.*that (.*) started working with the Admin Panel$/, function(name: string) {
    return this.stage.theActorCalled(name).attemptsTo(              // instantiate
    );        
});

this.When(/^s?he picks the first article that's pending correction$/, function() {
    return this.stage.theActorInTheSpotlight().attemptsTo(          // retrieve
    );
});

this.Then(/^s?he should be able to edit it$/, function() {
    return this.stage.theActorInTheSpotlight().attemptsTo(          // retrieve again
    );
});

Your feedback matters!

Suggest features and improvements on github, get in touch on twitter, and if you found Serenity/JS useful - don't forget to give it a star! ★

Star

results matching ""

    No results matching ""