Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
feat(core): Transform allows for transforming an answer to a question
- Loading branch information
Showing
with
102 additions
and 0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@@ -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); | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@@ -5,4 +5,5 @@ export * from './Answerable'; | ||
export * from './Interaction'; | ||
export * from './interactions'; | ||
export * from './Question'; | ||
export * from './questions'; | ||
export * from './Task'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@@ -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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@@ -0,0 +1 @@ | ||
export * from './Transform'; |