Skip to content
Permalink
Browse files
feat(core): Transform allows for transforming an answer to a question
  • Loading branch information
jan-molak committed Apr 11, 2019
1 parent 569d1bc commit 082adeb389369086bb025552d171bbf105e94ce3
@@ -0,0 +1,64 @@
import { given } from 'mocha-testdata';
import * as sinon from 'sinon';

import { Actor, Answerable, Question, Transform } from '../../../src/screenplay';
import { Stage } from '../../../src/stage';
import { expect } from '../../expect';

/** @test {TransformAnswer} */
describe('TransformAnswer', () => {

const stage = sinon.createStubInstance(Stage);

const expectedAnswer = {
headers: { header: 'value' },
body: 'some content',
};

type EA = typeof expectedAnswer;

const actor = new Actor('Bumblebee', stage as unknown as Stage);

given([
expectedAnswer,
p(expectedAnswer),
q(expectedAnswer),
q(p(expectedAnswer)),
]).
it('transforms an answer to Answerable<T> to another type', (answerable: Answerable<EA>) =>
expect(
Transform.the(answerable, complexObject => complexObject.headers.header).answeredBy(actor),
).to.eventually.equal(expectedAnswer.headers.header));

it('transforms answers to Array<Answerable<T>> to another type', () =>
expect(
Transform.the(
[ q(p(expectedAnswer)), q(expectedAnswer), expectedAnswer],
(ea1: EA, ea2: EA, ea3: EA) => ea1.headers.header + ea2.body + Object.keys(ea3).length,
).answeredBy(actor),
).to.eventually.equal(expectedAnswer.headers.header + expectedAnswer.body + Object.keys(expectedAnswer).length));

it('transforms answers to questions of different types to another type', () =>
expect(
Transform.the(
[ q('the answer to life the universe and everything'), q(p(42)) ],
(a1: string, a2: number) => `${ a1 } is ${ a2 }`,
).answeredBy(actor),
).to.eventually.equal(`the answer to life the universe and everything is 42`));

it('provides a sensible default description', () => {
expect(Transform.the(expectedAnswer, _ => _).toString()).to.equal('a transformed answer');
});

it('allows for the default description to be changed', () => {
expect(Transform.the(expectedAnswer, _ => _).as('a better description').toString()).to.equal('a better description');
});

function q<T>(value: T): Question<T> {
return Question.about(`something`, someActor => value);
}

function p<T>(value: T) {
return Promise.resolve(value);
}
});
@@ -5,4 +5,5 @@ export * from './Answerable';
export * from './Interaction';
export * from './interactions';
export * from './Question';
export * from './questions';
export * from './Task';
@@ -0,0 +1,36 @@
import { AnswersQuestions, UsesAbilities } from '../actor';
import { Answerable } from '../Answerable';
import { Question } from '../Question';

export class Transform<Answer_Type extends any, Output_Type> implements Question<Promise<Output_Type>> {
static the<AT extends any, OT>(questions: Answerable<AT> | Array<Answerable<AT>>, transformation: (...answers: AT[]) => OT) {
return new Transform<AT, OT>([].concat(questions), transformation);
}

constructor(
private readonly questions: Array<Answerable<Answer_Type>>,
private readonly transformation: (...answers: Answer_Type[]) => Output_Type,
private readonly description: string = `a transformed answer`,
) {
}

/**
* @desc
* Overrides the default {@link Transform#toString} representation of this object.
*
* @param {string} description
* @returns {Transform}
*/
as(description: string) {
return new Transform(this.questions, this.transformation, description);
}

answeredBy(actor: AnswersQuestions & UsesAbilities): Promise<Output_Type> {
return Promise.all(this.questions.map(question => actor.answer(question)))
.then(answers => this.transformation(...answers));
}

toString() {
return this.description;
}
}
@@ -0,0 +1 @@
export * from './Transform';

0 comments on commit 082adeb

Please sign in to comment.