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