Navigation Menu

Skip to content

Commit

Permalink
feat(screenplay): See - a screenplay-style way of executing assertions
Browse files Browse the repository at this point in the history
See allows the Actor to perform an intra-flow verification and stop the scenario should the

verification fail. Usage: `actor.attemptsTo(See.that(<Question>, (result) =>

expect(result).to.eventually.equal('foo')))`
  • Loading branch information
jan-molak committed Jan 19, 2017
1 parent f3b3066 commit ade82e5
Show file tree
Hide file tree
Showing 11 changed files with 75 additions and 2 deletions.
37 changes: 37 additions & 0 deletions spec/api/screenplay/tasks/see.spec.ts
@@ -0,0 +1,37 @@
import sinon = require('sinon');
import expect = require('../../../expect');
import { AssertionError } from 'chai';

import { Actor, Question, See, UsesAbilities } from '../../../../src/serenity/screenplay';

describe('Tasks', () => {

describe('See', () => {

class SomeResult implements Question<string> {
answeredBy(actor: UsesAbilities): PromiseLike<string>|string {
return Promise.resolve('some value');
}
}

it ('allows actor to verify a condition', () => {
let actor = Actor.named('James');

let promise = See.
that(new SomeResult(), r => expect(r).to.eventually.equal('some value')).
performAs(actor);

return expect(promise).to.be.eventually.fulfilled;
});

it ('rejects the promise if the condition is not met', () => {
let actor = Actor.named('James');

let promise = See.
that(new SomeResult(), r => expect(r).to.eventually.equal('other value')).
performAs(actor);

return expect(promise).to.be.eventually.rejectedWith(AssertionError, 'expected \'some value\' to equal \'other value\'');
});
});
});
2 changes: 2 additions & 0 deletions src/serenity-protractor/screenplay/questions/attribute.ts
Expand Up @@ -24,4 +24,6 @@ class AttributeValue implements Question<string> {

constructor(private target: Target, private attribute: string) {
}

toString = () => `the value of the '${ this.attribute }' attribute of ${ this.target}`;
}
Expand Up @@ -13,6 +13,8 @@ export class SelectedValue implements Question<string> {

constructor(private target: Target) {
}

toString = () => `the selected value of ${ this.target }`;
}

export class SelectedValues implements Question<string> {
Expand All @@ -26,4 +28,6 @@ export class SelectedValues implements Question<string> {

constructor(private target: Target) {
}

toString = () => `the selected values of ${ this.target }`;
}
4 changes: 4 additions & 0 deletions src/serenity-protractor/screenplay/questions/text.ts
Expand Up @@ -20,6 +20,8 @@ class TextOf implements Question<string> {

constructor(private target: Target) {
}

toString = () => `the text of ${ this.target}`;
}

class TextOfAll implements Question<string[]> {
Expand All @@ -32,4 +34,6 @@ class TextOfAll implements Question<string[]> {

constructor(private target: Target) {
}

toString = () => `the text of all ${ this.target}`;
}
2 changes: 2 additions & 0 deletions src/serenity-protractor/screenplay/questions/value.ts
Expand Up @@ -14,4 +14,6 @@ export class Value implements Question<string> {

constructor(private target: Target) {
}

toString = () => `the value of ${ this.target}`;
}
2 changes: 2 additions & 0 deletions src/serenity-protractor/screenplay/questions/web_element.ts
Expand Up @@ -16,4 +16,6 @@ export class WebElement implements Question<ElementFinder> {

constructor(private target: Target) {
}

toString = () => `the element representing ${ this.target }`;
}
2 changes: 2 additions & 0 deletions src/serenity-protractor/screenplay/questions/website.ts
Expand Up @@ -12,4 +12,6 @@ class WebsiteTitle implements Question<string> {
answeredBy(actor: UsesAbilities): PromiseLike<string> {
return BrowseTheWeb.as(actor).getTitle();
}

toString = () => `the title of the current page`;
}
1 change: 1 addition & 0 deletions src/serenity/screenplay/index.ts
@@ -1,3 +1,4 @@
export * from './actor';
export * from './performables';
export * from './question';
export * from './tasks';
4 changes: 2 additions & 2 deletions src/serenity/screenplay/performables.ts
@@ -1,4 +1,4 @@
import { PerformsTasks, UsesAbilities } from './actor';
import { AnswersQuestions, PerformsTasks, UsesAbilities } from './actor';

export interface Task extends Performable {
performAs(actor: PerformsTasks): PromiseLike<void>;
Expand All @@ -9,5 +9,5 @@ export interface Interaction extends Performable {
}

export interface Performable {
performAs(actor: PerformsTasks | UsesAbilities): PromiseLike<void>;
performAs(actor: PerformsTasks | UsesAbilities | AnswersQuestions): PromiseLike<void>;
}
1 change: 1 addition & 0 deletions src/serenity/screenplay/tasks/index.ts
@@ -0,0 +1 @@
export * from './see';
18 changes: 18 additions & 0 deletions src/serenity/screenplay/tasks/see.ts
@@ -0,0 +1,18 @@
import { AnswersQuestions, Performable, Question } from '..';
import { step } from '../../recording/step_annotation';

export type AssertionFn<S> = (subject: S) => PromiseLike<void>;

export class See<S> implements Performable {
static that<S>(subject: Question<S>, verifier: AssertionFn<S>) {
return new See(subject, verifier);
}

@step('{0} looks at #question')
performAs(actor: AnswersQuestions): PromiseLike<void> {
return this.assert(actor.toSee(this.question));
}

constructor(private question: Question<S>, private assert: AssertionFn<S>) {
}
}

0 comments on commit ade82e5

Please sign in to comment.