@serenity-js/assertions
Version:
Serenity/JS universal assertion library supporting all types of functional tests, including both web and REST API scenarios
68 lines (60 loc) • 2.24 kB
text/typescript
import type { Answerable, AnswersQuestions, ExpectationOutcome} from '@serenity-js/core';
import { Expectation, ExpectationMet, ExpectationNotMet, LogicError } from '@serenity-js/core';
/**
* Creates an [expectation](https://serenity-js.org/api/core/class/Expectation/) that is met when at least one of the `expectations` is met for the given actual value.
*
* Use `or` to combine several expectations using logical "or",
*
* ## Combining several expectations
*
* ```ts
* import { actorCalled } from '@serenity-js/core'
* import { Ensure, or, startsWith } from '@serenity-js/assertions'
*
* await actorCalled('Ester').attemptsTo(
* Ensure.that('Hello World!', or(startsWith('Hello'), startsWith('Hi'))),
* )
* ```
*
* @param expectations
*
* @group Expectations
*/
export function or<Actual_Type>(...expectations: Array<Expectation<Actual_Type>>): Expectation<Actual_Type> {
return new Or(expectations);
}
/**
* @package
*/
class Or<Actual> extends Expectation<Actual> {
private static readonly Separator = ' or ';
private static subjectFor<A>(expectations: Array<Expectation<A>>): string {
return expectations
.map(expectation => expectation.toString())
.join(Or.Separator);
}
constructor(private readonly expectations: Array<Expectation<Actual>>) {
super(
'or',
Or.subjectFor(expectations),
async (actor: AnswersQuestions, actual: Answerable<Actual>) => {
if (! expectations || expectations.length === 0) {
throw new LogicError(`No expectations provided to or()`);
}
let outcome: ExpectationOutcome;
for (const expectation of expectations) {
outcome = await actor.answer(expectation.isMetFor(actual));
if (outcome instanceof ExpectationMet) {
return outcome;
}
}
return new ExpectationNotMet(
Or.subjectFor(expectations),
outcome.expectation,
outcome.expected,
outcome.actual,
);
}
);
}
}