@assertive-ts/core
Version:
A type-safe fluent assertion library
338 lines • 11.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ArrayAssertion = void 0;
const tslib_1 = require("tslib");
const es6_1 = tslib_1.__importDefault(require("fast-deep-equal/es6"));
const Assertion_1 = require("./Assertion");
const UnsupportedOperationError_1 = require("./errors/UnsupportedOperationError");
const messages_1 = require("./helpers/messages");
const assert_1 = require("assert");
/**
* Encapsulates assertion methods applicable to arrays.
*
* @param T the type of the array
*/
class ArrayAssertion extends Assertion_1.Assertion {
constructor(actual) {
super(actual);
}
/**
* Check if all the array values match the predicate
*
* @example
* ```
* expect([1, 2, 3]).toMatchAll(x => x < 5);
* expect([apple, orange, pear]).toMatchAll(isFruit);
* ```
*
* @param matcher a generic matcher predicate
* @returns the assertion instance
*/
toMatchAll(matcher) {
const error = new assert_1.AssertionError({
actual: this.actual,
message: "Expected all values of the array to return true on the matcher predicate",
});
const invertedError = new assert_1.AssertionError({
actual: this.actual,
message: "Expected not every value of the array to return true on the matcher predicate",
});
return this.execute({
assertWhen: this.actual.every(matcher),
error,
invertedError,
});
}
/**
* Check if any of the array values match the predicate
*
* @example
* ```
* expect([dog, apple, cat]).toMatchAny(isFruit);
* ```
*
* @param matcher a matcher predicate
* @returns the assertion instance
*/
toMatchAny(matcher) {
const error = new assert_1.AssertionError({
actual: this.actual,
message: "Expected any value of the array to return true on the matcher predicate",
});
const invertedError = new assert_1.AssertionError({
actual: this.actual,
message: "Expected no value of the array to return true on the matcher predicate",
});
return this.execute({
assertWhen: this.actual.some(matcher),
error,
invertedError,
});
}
/**
* Check if all the values of the array satisfies a given assertion.
*
* @example
* ```
* const checkIsFruit = (x: Fruit) => expect(x).toBeInstanceOf(Fruit);
* expect([apple, pear, banana]).toSatisfyAll(checkIsFruit);
* ```
*
* @param consumer a consumer of the array to assert over each value of its
* values
* @returns the assertion instance
*/
toSatisfyAll(consumer) {
const tryAllValues = () => {
try {
this.actual.forEach(consumer);
return undefined;
}
catch (error) {
if (error instanceof assert_1.AssertionError) {
return error;
}
throw error;
}
};
const firstError = tryAllValues();
return this.execute({
assertWhen: firstError === undefined,
error: firstError !== null && firstError !== void 0 ? firstError : new assert_1.AssertionError({}),
invertedError: new assert_1.AssertionError({
actual: this.actual,
message: "Expected not all values of the array to satisfy the given assertion",
}),
});
}
/**
* Check if any value of the array satisfies the give assertion.
*
* @example
* ```
* const checkIsFruit = (x: Fruit) => expect(x).toBeInstanceOf(Fruit);
* expect([dog, apple, cat]).toSatisfyAny(checkIsFruit);
* ```
*
* @param consumer a consumer of the array to assert over each value of its
* values
* @returns the assertion instance
*/
toSatisfyAny(consumer) {
const error = new assert_1.AssertionError({
actual: this.actual,
message: "Expected any value of the array to satisfy the given assertion",
});
const invertedError = new assert_1.AssertionError({
actual: this.actual,
message: "Expected no value of the array to satisfy the given assertion",
});
return this.execute({
assertWhen: this.actual.some(value => {
try {
consumer(value);
return true;
}
catch (err) {
return false;
}
}),
error,
invertedError,
});
}
/**
* Check if the array is empty. That is, when its `length` property is zero.
*
* @example
* ```
* expect([]).toBeEmpty();
* ```
*
* @returns the assertion instance
*/
toBeEmpty() {
const error = new assert_1.AssertionError({
actual: this.actual,
message: "Expected array to be empty",
});
const invertedError = new assert_1.AssertionError({
actual: this.actual,
message: "Expected array NOT to be empty",
});
return this.execute({
assertWhen: this.actual.length === 0,
error,
invertedError,
});
}
/**
* Check if the array has some specific number of elements.
*
* @example
* ```
* expect([0, 1, 2]).toHaveSize(3);
* ```
*
* @param size the expected number of elements in the array
* @returns the assertion instance
*/
toHaveSize(size) {
const error = new assert_1.AssertionError({
actual: this.actual.length,
expected: size,
message: `Expected array to contain ${size} elements, but it has ${this.actual.length}`,
});
const invertedError = new assert_1.AssertionError({
actual: this.actual.length,
message: `Expected array NOT to contain ${size} elements, but it does`,
});
return this.execute({
assertWhen: this.actual.length === size,
error,
invertedError,
});
}
/**
* Check if the array contains the same elements as another. This doesn't
* check the order of the elements.
*
* @example
* ```
* expect([1, 2, 3]).toHaveSameMembers([3, 2, 1]);
* ```
*
* @param expected the other array to compare its elements to
* @returns the assertion instance
*/
toHaveSameMembers(expected) {
const error = new assert_1.AssertionError({
actual: this.actual,
expected,
message: `Expected array to have the same members as <${(0, messages_1.prettify)(expected)}>`,
});
const invertedError = new assert_1.AssertionError({
actual: this.actual,
message: `Expected array NOT to have the same members as <${(0, messages_1.prettify)(expected)}>`,
});
return this.execute({
assertWhen: this.actual.length === expected.length
&& this.actual.every(value => expected.includes(value)),
error,
invertedError,
});
}
/**
* Check if the array contains all the passed values.
*
* @example
* ```
* expect([1, 2, 3]).toContainAll(1, 3);
* ```
*
* @param values the values the array should contain
* @returns the assertion instance
*/
toContainAll(...values) {
const allValues = values.map(messages_1.prettify).join(", ");
const error = new assert_1.AssertionError({
actual: this.actual,
message: `Expected array to contain all the values <${allValues}>`,
});
const invertedError = new assert_1.AssertionError({
actual: this.actual,
message: `Expected array NOT to contain all the values <${allValues}>`,
});
return this.execute({
assertWhen: values.every(value => this.actual.includes(value)),
error,
invertedError,
});
}
/**
* Check if the array contains any of the passed values.
*
* @example
* ```
* expect([1, 2, 3]).toContainAny(1, 50, 36);
* ```
*
* @param values the value the array should include (at least one)
* @returns the assertion instance
*/
toContainAny(...values) {
const allValues = values.map(messages_1.prettify).join(", ");
const error = new assert_1.AssertionError({
actual: this.actual,
message: `Expected array to contain any of the values <${allValues}>`,
});
const invertedError = new assert_1.AssertionError({
actual: this.actual,
message: `Expected array NOT to contain any of the values <${allValues}>`,
});
return this.execute({
assertWhen: values.some(value => this.actual.includes(value)),
error,
invertedError,
});
}
/**
* Check if the array contains an specific value at an exact index.
*
* @param index the index of the array to find the value
* @param value the expected value of the index in the array
* @returns the assertion instance
*/
toContainAt(index, value) {
const error = new assert_1.AssertionError({
actual: this.actual[index],
expected: value,
message: `Expected value at index <${index}> to be <${(0, messages_1.prettify)(value)}>`,
});
const invertedError = new assert_1.AssertionError({
actual: this.actual[index],
message: `Expected value at index <${index}> NOT to be <${(0, messages_1.prettify)(value)}>`,
});
return this.execute({
assertWhen: (0, es6_1.default)(this.actual[index], value),
error,
invertedError,
});
}
/**
* Extract the value on a specific index of the array and create an assertion
* instance of that specific type. This method uses {@link Assertion.asType}
* internally to create the new assertion instance.
*
* @example
* ```
* expect(["foo", 2, true])
* .extracting(1, TypeFactories.Number)
* .toBePositive();
* ```
*
* @typeParam S the type of the factory's value
* @typeParam A the type of the assertion factory
* @param index the index of the array to extract the value
* @param typeFactory a factory to assert the extracted value type and create
* an assertion for it
* @returns a more specific assertion based on the factory type for the value
*/
extracting(index, typeFactory) {
if (this.inverted) {
throw new UnsupportedOperationError_1.UnsupportedOperationError("The `.not` modifier is not allowed on `.extracting(..)` method");
}
if (index >= this.actual.length) {
throw new assert_1.AssertionError({
actual: this.actual,
message: `Out of bounds! Cannot extract index ${index} from an array of ${this.actual.length} elements`,
});
}
// We use `require(..)` to avoid import cycles with the `./expect` module
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { expect } = require("./expect");
return expect(this.actual[index]).asType(typeFactory);
}
}
exports.ArrayAssertion = ArrayAssertion;
//# sourceMappingURL=ArrayAssertion.js.map