UNPKG

@serenity-js/core

Version:

The core Serenity/JS framework, providing the Screenplay Pattern interfaces, as well as the test reporting and integration infrastructure

186 lines 8.41 kB
import type { Answerable, AnswersQuestions, QuestionAdapter } from '../index'; import { Describable } from '../questions'; import type { ExpectationOutcome } from './expectations'; /** * @group Expectations */ export type Predicate<Actual> = (actor: AnswersQuestions, actual: Answerable<Actual>) => Promise<ExpectationOutcome> | ExpectationOutcome; type AnswerableArguments<Arguments extends Array<unknown>> = { [Index in keyof Arguments]: Answerable<Arguments[Index]>; }; /** * Defines an expectation to be used with [`Wait.until`](https://serenity-js.org/api/core/class/Wait/#until), * [`Check.whether`](https://serenity-js.org/api/core/class/Check/#whether), * [`Ensure.that`](https://serenity-js.org/api/assertions/class/Ensure/#that) * and as part of the Page Element Query Language with [`PageElements.where`](https://serenity-js.org/api/web/class/PageElements/#where) * and [`List.where`](https://serenity-js.org/api/core/class/List/#where). * * @group Expectations */ export declare class Expectation<Actual> extends Describable { private readonly functionName; private readonly predicate; /** * A factory method to that makes defining custom [expectations](https://serenity-js.org/api/core/class/Expectation/) easier * * #### Defining a custom expectation * * ```ts * import { Expectation } from '@serenity-js/core' * import { PageElement } from '@serenity-js/web' * * const isEmpty = Expectation.define( * 'isEmpty', // name of the expectation function to be used when producing an AssertionError * 'become empty', // human-readable description of the relationship between expected and actual values * async (actual: PageElement) => { * const value = await actual.value(); * return value.length === 0; * } * ) * ``` * * #### Using a custom expectation in an assertion * * ```ts * import { Ensure } from '@serenity-js/assertions' * import { actorCalled } from '@serenity-js/core' * import { By, Clear, PageElement } from '@serenity-js/web' * * const nameField = () => * PageElement.located(By.css('[data-test-id="name"]')).describedAs('name field'); * * await actorCalled('Izzy').attemptsTo( * Clear.the(nameField()), * Ensure.that(nameField(), isEmpty()) * ) * ``` * * #### Using a custom expectation in a control flow statement * * ```ts * import { not } from '@serenity-js/assertions' * import { actorCalled, Check, Duration, Wait } from '@serenity-js/core' * import { By, PageElement } from '@serenity-js/web' * * const nameField = () => * PageElement.located(By.css('[data-test-id="name"]')).describedAs('name field'); * * await actorCalled('Izzy').attemptsTo( * Check.whether(nameField(), isEmpty()) * .andIfSo( * Enter.theValue(actorInTheSpotlight().name).into(nameField()), * ), * ) * ``` * * #### Using a custom expectation in a synchronisation statement * * ```ts * import { not } from '@serenity-js/assertions' * import { actorCalled, Duration, Wait } from '@serenity-js/core' * import { By, PageElement } from '@serenity-js/web' * * const nameField = () => * PageElement.located(By.css('[data-test-id="name"]')).describedAs('name field'); * * await actorCalled('Izzy').attemptsTo( * Enter.theValue(actorInTheSpotlight().name).into(nameField()), * * Wait.upTo(Duration.ofSeconds(2)) * .until(nameField(), not(isEmpty())), * ) * ``` * * #### Learn more * - [`Ensure`](https://serenity-js.org/api/assertions/class/Ensure/) * - [`Check`](https://serenity-js.org/api/core/class/Check/) * - [`Wait`](https://serenity-js.org/api/core/class/Wait/) * * @param functionName * Name of the expectation function to be used when producing an [`AssertionError`](https://serenity-js.org/api/core/class/AssertionError/) * * @param relationship * Human-readable description of the relationship between the `expected` and the `actual` values. * Used when reporting [activities](https://serenity-js.org/api/core/class/Activity/) performed by an [actor](https://serenity-js.org/api/core/class/Actor/) * * @param predicate */ static define<Actual_Type, PredicateArguments extends Array<unknown>>(functionName: string, relationship: ((...answerableArguments: AnswerableArguments<PredicateArguments>) => Answerable<string>) | Answerable<string>, predicate: (actual: Actual_Type, ...predicateArguments: PredicateArguments) => Promise<boolean> | boolean): (...answerableArguments: AnswerableArguments<PredicateArguments>) => Expectation<Actual_Type>; /** * Used to define a simple [`Expectation`](https://serenity-js.org/api/core/class/Expectation/) * * #### Simple parameterised expectation * * ```ts * import { actorCalled, Expectation } from '@serenity-js/core' * import { Ensure } from '@serenity-js/assertions' * * function isDivisibleBy(expected: Answerable<number>): Expectation<number> { * return Expectation.thatActualShould<number, number>('have value divisible by', expected) * .soThat((actualValue, expectedValue) => actualValue % expectedValue === 0); * } * * await actorCalled('Erica').attemptsTo( * Ensure.that(4, isDivisibleBy(2)), * ) * ``` * * @param relationshipName * Name of the relationship between the `actual` and the `expected`. Use format `have value <adjective>` * so that the description works in both positive and negative contexts, e.g. `Waited until 5 does have value greater than 2`, * `Expected 5 to not have value greater than 2`. * * @param expectedValue */ static thatActualShould<Expected_Type, Actual_Type>(relationshipName: string, expectedValue?: Answerable<Expected_Type>): { soThat: (simplifiedPredicate: (actualValue: Actual_Type, expectedValue: Expected_Type) => Promise<boolean> | boolean) => Expectation<Actual_Type>; }; /** * Used to compose [expectations](https://serenity-js.org/api/core/class/Expectation/). * * #### Composing [expectations](https://serenity-js.org/api/core/class/Expectation/) * * ```ts * import { actorCalled, Expectation } from '@serenity-js/core' * import { Ensure, and, or, isGreaterThan, isLessThan, equals } from '@serenity-js/assertions' * * function isWithin(lowerBound: number, upperBound: number) { * return Expectation * .to(`have value within ${ lowerBound } and ${ upperBound }`) * .soThatActual( * and( * or(isGreaterThan(lowerBound), equals(lowerBound)), * or(isLessThan(upperBound), equals(upperBound)), * ) * ) * } * * await actorCalled('Erica').attemptsTo( * Ensure.that(5, isWithin(3, 6)), * ) * ``` * * @param relationshipName * Name of the relationship between the `actual` and the `expected`. Use format `have value <adjective>` * so that the description works in both positive and negative contexts, e.g. `Waited until 5 does have value greater than 2`, * `Expected 5 to not have value greater than 2`. */ static to<Actual_Type>(relationshipName: string): { soThatActual: (expectation: Expectation<Actual_Type>) => Expectation<Actual_Type>; }; protected constructor(functionName: string, description: Answerable<string>, predicate: Predicate<Actual>); /** * Returns a [`QuestionAdapter`](https://serenity-js.org/api/core/#QuestionAdapter) that resolves to [`ExpectationOutcome`](https://serenity-js.org/api/core/class/ExpectationOutcome/) * indicating that the [expectation was met](https://serenity-js.org/api/core/class/ExpectationMet/) * or that the [expectation was not met](https://serenity-js.org/api/core/class/ExpectationNotMet/) * * @param actual */ isMetFor(actual: Answerable<Actual>): QuestionAdapter<ExpectationOutcome>; /** * @inheritDoc */ describedAs(description: Answerable<string>): this; } export {}; //# sourceMappingURL=Expectation.d.ts.map