interface BehaviorDrivenDevelopment {
    given: Given<void>;
}
type GivenPermutation<TPrecondition, TNextPrecondition> = readonly [
    string,
    (precondition: TPrecondition) => Promise<TNextPrecondition> | TNextPrecondition,
    ((precondition: TNextPrecondition) => Promise<void> | void) | undefined
] | readonly [string, (precondition: TPrecondition) => Promise<TNextPrecondition> | TNextPrecondition];
interface Given<TPrecondition> {
    <TNextPrecondition>(message: string, setup: (precondition: TPrecondition) => Promise<TNextPrecondition> | TNextPrecondition, teardown?: ((precondition: TNextPrecondition) => Promise<void> | void) | undefined): {
        and: Given<TNextPrecondition>;
        when: When<TNextPrecondition, void>;
    };
    oneOf<TNextPrecondition>(permutations: readonly GivenPermutation<TPrecondition, TNextPrecondition>[]): {
        and: Given<TNextPrecondition>;
        when: When<TNextPrecondition, void>;
    };
}
type WhenPermutation<TPrecondition, TOutcome, TNextOutcome> = readonly [
    string,
    (precondition: TPrecondition, outcome: TOutcome) => Promise<TNextOutcome> | TNextOutcome,
    ((precondition: TPrecondition, outcome: TNextOutcome) => Promise<void> | void) | undefined
] | readonly [string, (precondition: TPrecondition, outcome: TOutcome) => Promise<TNextOutcome> | TNextOutcome];
interface When<TPrecondition, TOutcome> {
    <TNextOutcome>(message: string, setup: (precondition: TPrecondition, outcome: TOutcome) => Promise<TNextOutcome> | TNextOutcome, teardown?: ((precondition: TPrecondition, outcome: TNextOutcome) => Promise<void> | void) | undefined): {
        then: Then<TPrecondition, TNextOutcome>;
    };
    oneOf<TNextOutcome>(permutations: readonly WhenPermutation<TPrecondition, TOutcome, TNextOutcome>[]): {
        then: Then<TPrecondition, TNextOutcome>;
    };
}
interface Then<TPrecondition, TOutcome> {
    (message: string, fn: (precondition: TPrecondition, outcome: TOutcome) => void): {
        and: Then<TPrecondition, TOutcome>;
        when: When<TPrecondition, TOutcome>;
    };
}
interface TestFacility {
    afterEach: (fn: () => Promise<void> | void) => void;
    beforeEach: (fn: () => Promise<void> | void) => void;
    describe: (message: string, fn: () => void) => void;
    it: (message: string, fn: (() => PromiseLike<void>) | (() => void)) => void;
}
declare function scenario(message: string, fn: (bdd: BehaviorDrivenDevelopment) => void, options?: Partial<TestFacility>): void;

declare function mergeInto<T, TMerge>(objectToMerge: TMerge): (scope: T) => T & TMerge;

export { mergeInto, scenario };
