import { AnswersQuestions, UsesAbilities } from './actor'; /** * @desc * Enables the {@link Actor} to query the system under test. * * @example A basic Question * import { Actor, AnswersQuestions, UsesAbilities, Question } from '@serenity-js/core' * import { Ensure, equals } from '@serenity-js/assertions' * * const LastItemOf = (list: T[]): Question => * Question.about('last item from the list', (actor: AnswersQuestions & UsesAbilities) => { * return list[list.length - 1]; * }); * * Actor.named('Quentin').attemptsTo( * Ensure.that(LastItemFrom([1,2,3]), equals(3)), * ); * * @example A question using the Actor's Ability to do something * import { AnswersQuestions, UsesAbilities, Question } from '@serenity-js/core' * import { CallAnApi } from '@serenity-js/rest' * * const TextOfLastResponseStatus = () => * Question.about(`the text of the last response status`, actor => { * return CallAnApi.as(actor).mapLastResponse(response => response.statusText); * }); * * @example Mapping answers to other questions * import { Actor, AnswersQuestions, UsesAbilities, Question } from '@serenity-js/core' * import { CallAnApi, LastResponse } from '@serenity-js/rest' * import { Ensure, equals } from '@serenity-js/assertions'; * * const RequestWasSuccessful = () => * Question.about(`the text of the last response status`, actor => { * return LastResponse.status().answeredBy(actor) === 200; * }); * * const actor = Actor.named('Quentin').whoCan(CallAnApi.at('https://myapp.com/api')); * * actor.attemptsTo( * Send.a(GetRequest.to('/books/0-688-00230-7')), * Ensure.that(RequestWasSuccessful(), equals(true)), * ); */ export abstract class Question { /** * Factory method that simplifies the process of defining custom questions. */ static about(description: string, body: (actor: AnswersQuestions & UsesAbilities) => R): Question { return new AnonymousQuestion(description, body); } /** * Checks if the value is a {@link Question} * @returns {boolean} */ static isAQuestion(maybeQuestion: any): maybeQuestion is Question { return !! (maybeQuestion as any).answeredBy; } /** * @abstract */ abstract answeredBy(actor: AnswersQuestions & UsesAbilities): T; } /** * @package */ class AnonymousQuestion implements Question { constructor(private description: string, private body: (actor: AnswersQuestions & UsesAbilities) => T) { } answeredBy(actor: AnswersQuestions & UsesAbilities) { return this.body(actor); } toString() { return this.description; } }