UNPKG

@augment-vir/assert

Version:

A collection of assertions for test and production code alike.

1,423 lines 60.8 kB
import { stringify } from '@augment-vir/core'; import { AssertionError } from '../augments/assertion.error.js'; import { createWaitUntil } from '../guard-types/wait-until-function.js'; const assertions = { /** * Asserts that a number is inside the provided min and max bounds, inclusive. * * Performs no type guarding. * * @example * * ```ts * import {assert} from '@augment-vir/assert'; * * assert.isInBounds(5, {min: 1, max: 10}); // passes * assert.isInBounds(10, {min: 1, max: 10}); // passes * assert.isInBounds(11, {min: 1, max: 10}); // fails * assert.isInBounds(0, {min: 1, max: 10}); // fails * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assert.isOutBounds} : the opposite assertion. */ isInBounds(actual, { max, min }, failureMessage) { if (actual < min || max < actual) { throw new AssertionError(`${actual} is not within the bounds ${stringify({ min, max })}`, failureMessage); } }, /** * Asserts that a number is outside the provided min and max bounds, exclusive. * * Performs no type guarding. * * @example * * ```ts * import {assert} from '@augment-vir/assert'; * * assert.isOutBounds(5, {min: 1, max: 10}); // fails * assert.isOutBounds(10, {min: 1, max: 10}); // fails * assert.isOutBounds(11, {min: 1, max: 10}); // passes * assert.isOutBounds(0, {min: 1, max: 10}); // passes * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assert.isInBounds} : the opposite assertion. */ isOutBounds(actual, { min, max }, failureMessage) { if (min <= actual && actual <= max) { throw new AssertionError(`${actual} is not outside the bounds ${stringify({ min, max })}`, failureMessage); } }, /** * Asserts that a number is an integer. This has the same limitations as * https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger. * * Performs no type guarding. * * @example * * ```ts * import {assert} from '@augment-vir/assert'; * * assert.isInteger(5); // passes * assert.isInteger(5.0000000000000001); // passes * assert.isInteger(5.1); // fails * assert.isInteger(NaN); // fails * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assert.isNotInteger} : the opposite assertion. */ isInteger(actual, failureMessage) { if (typeof actual !== 'number' || isNaN(actual) || !Number.isInteger(actual)) { throw new AssertionError(`${actual} is not an integer.`, failureMessage); } }, /** * Asserts that a number is not an integer. This has the same limitations, as * https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger. * * Performs no type guarding. * * @example * * ```ts * import {assert} from '@augment-vir/assert'; * * assert.isNotInteger(5); // fails * assert.isNotInteger(5.0000000000000001); // fails * assert.isNotInteger(5.1); // passes * assert.isNotInteger(NaN); // passes * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assert.isInteger} : the opposite assertion. */ isNotInteger(actual, failureMessage) { if (Number.isInteger(actual)) { throw new AssertionError(`${actual} is an integer.`, failureMessage); } }, /** * Asserts that a number is above the expectation (`actual > expected`). * * Performs no type guarding. * * @example * * ```ts * import {assert} from '@augment-vir/assert'; * * assert.isAbove(10, 5); // passes * assert.isAbove(5, 5); // fails * assert.isAbove(5, 10); // fails * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assert.isBelow} : the opposite assertion. * - {@link assert.isAtLeast} : the more lenient assertion. */ isAbove(actual, expected, failureMessage) { if (actual <= expected) { throw new AssertionError(`${actual} is not above ${expected}`, failureMessage); } }, /** * Asserts that a number is at least the expectation (`actual >= expected`). * * Performs no type guarding. * * @example * * ```ts * import {assert} from '@augment-vir/assert'; * * assert.isAtLeast(10, 5); // passes * assert.isAtLeast(5, 5); // passes * assert.isAtLeast(5, 10); // fails * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assert.isAtMost} : the opposite assertion. * - {@link assert.isAbove} : the more restrictive assertion. */ isAtLeast(actual, expected, failureMessage) { if (actual < expected) { throw new AssertionError(`${actual} is not at least ${expected}`, failureMessage); } }, /** * Asserts that a number is below the expectation (`actual < expected`). * * Performs no type guarding. * * @example * * ```ts * import {assert} from '@augment-vir/assert'; * * assert.isBelow(10, 5); // fails * assert.isBelow(5, 5); // fails * assert.isBelow(5, 10); // passes * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assert.isAbove} : the opposite assertion. * - {@link assert.isAtMost} : the more lenient assertion. */ isBelow(actual, expected, failureMessage) { if (actual >= expected) { throw new AssertionError(`${actual} is not below ${expected}`, failureMessage); } }, /** * Asserts that a number is at most the expectation (`actual <= expected`). * * Performs no type guarding. * * @example * * ```ts * import {assert} from '@augment-vir/assert'; * * assert.isAtMost(10, 5); // fails * assert.isAtMost(5, 5); // passes * assert.isAtMost(5, 10); // passes * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assert.isAtLeast} : the opposite assertion. * - {@link assert.isBelow} : the more restrictive assertion. */ isAtMost(actual, expected, failureMessage) { if (actual > expected) { throw new AssertionError(`${actual} is not at most ${expected}`, failureMessage); } }, /** * Asserts that a number is * [`NaN`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/NaN). * * Performs no type guarding. * * @example * * ```ts * import {assert} from '@augment-vir/assert'; * * assert.isNaN(10); // fails * assert.isNaN(parseInt('invalid')); // passes * assert.isNaN(Infinity); // fails * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assert.isNumber} : can be used as the opposite assertion. */ isNaN(actual, failureMessage) { if (!isNaN(actual)) { throw new AssertionError(`${actual} is not NaN`, failureMessage); } }, /** * Asserts that a number is finite: meaning, not `NaN` and not `Infinity` or `-Infinity`. * * Performs no type guarding. * * @example * * ```ts * import {assert} from '@augment-vir/assert'; * * assert.isFinite(10); // passes * assert.isFinite(parseInt('invalid')); // fails * assert.isFinite(Infinity); // fails * assert.isFinite(-Infinity); // fails * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assert.isNaN} : an opposite assertion. * - {@link assert.isInfinite} : an opposite assertion. */ isFinite(actual, failureMessage) { if (isNaN(actual) || actual === Infinity || actual === -Infinity) { throw new AssertionError(`${actual} is not finite`, failureMessage); } }, /** * Asserts that a number is either `Infinity` or `-Infinity`. * * Performs no type guarding. * * @example * * ```ts * import {assert} from '@augment-vir/assert'; * * assert.isInfinite(10); // fails * assert.isInfinite(parseInt('invalid')); // fails * assert.isInfinite(Infinity); // passes * assert.isInfinite(-Infinity); // passes * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assert.isNaN} : an opposite assertion. * - {@link assert.isInfinite} : an opposite assertion. */ isInfinite(actual, failureMessage) { if (actual !== Infinity && actual !== -Infinity) { throw new AssertionError(`${actual} is not infinite`, failureMessage); } }, /** * Asserts that a number is within ±`delta` of the expectation. * * Performs no type guarding. * * @example * * ```ts * import {assert} from '@augment-vir/assert'; * * assert.isApproximately(10, 8, 4); // passes * assert.isApproximately(10, 12, 4); // passes * assert.isApproximately(10, 8, 1); // fails * assert.isApproximately(10, 12, 1); // fails * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assert.isNotApproximately} : the opposite assertion. */ isApproximately(actual, expected, delta, failureMessage) { if (actual < expected - delta || actual > expected + delta) { throw new AssertionError(`${actual} is not within ±${delta} of ${expected}`, failureMessage); } }, /** * Asserts that a number is outside ±`delta` of the expectation. * * Performs no type guarding. * * @example * * ```ts * import {assert} from '@augment-vir/assert'; * * assert.isNotApproximately(10, 8, 4); // fails * assert.isNotApproximately(10, 12, 4); // fails * assert.isNotApproximately(10, 8, 1); // passes * assert.isNotApproximately(10, 12, 1); // passes * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assert.isApproximately} : the opposite assertion. */ isNotApproximately(actual, expected, delta, failureMessage) { if (actual >= expected - delta && actual <= expected + delta) { throw new AssertionError(`${actual} is within ±${delta} of ${expected}`, failureMessage); } }, }; export const numericGuards = { assert: assertions, check: { /** * Checks that a number is inside the provided min and max bounds, inclusive. * * Performs no type guarding. * * @example * * ```ts * import {check} from '@augment-vir/assert'; * * check.isInBounds(5, {min: 1, max: 10}); // passes * check.isInBounds(10, {min: 1, max: 10}); // passes * check.isInBounds(11, {min: 1, max: 10}); // fails * check.isInBounds(0, {min: 1, max: 10}); // fails * ``` * * @see * - {@link check.isOutBounds} : the opposite check. */ isInBounds(actual, { max, min }) { return min <= actual && actual <= max; }, /** * Checks that a number is outside the provided min and max bounds, exclusive. * * Performs no type guarding. * * @example * * ```ts * import {check} from '@augment-vir/assert'; * * check.isOutBounds(5, {min: 1, max: 10}); // fails * check.isOutBounds(10, {min: 1, max: 10}); // fails * check.isOutBounds(11, {min: 1, max: 10}); // passes * check.isOutBounds(0, {min: 1, max: 10}); // passes * ``` * * @see * - {@link check.isInBounds} : the opposite check. */ isOutBounds(actual, { max, min }) { return actual < min || max < actual; }, /** * Checks that a number is an integer. This has the same limitations as * https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger. * * Performs no type guarding. * * @example * * ```ts * import {check} from '@augment-vir/assert'; * * check.isInteger(5); // passes * check.isInteger(5.0000000000000001); // passes * check.isInteger(5.1); // fails * check.isInteger(NaN); // fails * ``` * * @see * - {@link check.isNotInteger} : the opposite check. */ isInteger(actual) { return typeof actual === 'number' && !isNaN(actual) && Number.isInteger(actual); }, /** * Checks that a number is not an integer. This has the same limitations, as * https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger. * * Performs no type guarding. * * @example * * ```ts * import {check} from '@augment-vir/assert'; * * check.isNotInteger(5); // fails * check.isNotInteger(5.0000000000000001); // fails * check.isNotInteger(5.1); // passes * check.isNotInteger(NaN); // passes * ``` * * @see * - {@link check.isInteger} : the opposite check. */ isNotInteger(actual) { return typeof actual !== 'number' || isNaN(actual) || !Number.isInteger(actual); }, /** * Checks that a number is above the expectation (`actual > expected`). * * Performs no type guarding. * * @example * * ```ts * import {check} from '@augment-vir/assert'; * * check.isAbove(10, 5); // returns `true` * check.isAbove(5, 5); // returns `false` * check.isAbove(5, 10); // returns `false` * ``` * * @see * - {@link check.isBelow} : the opposite check. * - {@link check.isAtLeast} : the more lenient check. */ isAbove(actual, expected) { return actual > expected; }, /** * Checks that a number is at least the expectation (`actual >= expected`). * * Performs no type guarding. * * @example * * ```ts * import {check} from '@augment-vir/assert'; * * check.isAtLeast(10, 5); // returns `true` * check.isAtLeast(5, 5); // returns `true` * check.isAtLeast(5, 10); // returns `false` * ``` * * @see * - {@link check.isAtMost} : the opposite check. * - {@link check.isAbove} : the more restrictive check. */ isAtLeast(actual, expected) { return actual >= expected; }, /** * Checks that a number is below the expectation (`actual < expected`). * * Performs no type guarding. * * @example * * ```ts * import {check} from '@augment-vir/assert'; * * check.isBelow(10, 5); // returns `false` * check.isBelow(5, 5); // returns `false` * check.isBelow(5, 10); // returns `true` * ``` * * @see * - {@link check.isAbove} : the opposite check. * - {@link check.isAtMost} : the more lenient check. */ isBelow(actual, expected) { return actual < expected; }, /** * Checks that a number is at most the expectation (`actual <= expected`). * * Performs no type guarding. * * @example * * ```ts * import {check} from '@augment-vir/assert'; * * check.isAtMost(10, 5); // returns `false` * check.isAtMost(5, 5); // returns `true` * check.isAtMost(5, 10); // returns `true` * ``` * * @see * - {@link check.isAtLeast} : the opposite check. * - {@link check.isBelow} : the more restrictive check. */ isAtMost(actual, expected) { return actual <= expected; }, /** * Checks that a number is * [`NaN`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/NaN). * * Performs no type guarding. * * @example * * ```ts * import {check} from '@augment-vir/assert'; * * check.isNaN(10); // returns `false` * check.isNaN(parseInt('invalid')); // returns `true` * check.isNaN(Infinity); // returns `false` * ``` * * @see * - {@link check.isNumber} : can be used as the opposite check. */ isNaN(input) { return isNaN(input); }, /** * Checks that a number is finite: meaning, not `NaN` and not `Infinity` or `-Infinity`. * * Performs no type guarding. * * @example * * ```ts * import {check} from '@augment-vir/assert'; * * check.isFinite(10); // returns `true` * check.isFinite(parseInt('invalid')); // returns `false` * check.isFinite(Infinity); // returns `false` * check.isFinite(-Infinity); // returns `false` * ``` * * @see * - {@link check.isNaN} : an opposite check. * - {@link check.isInfinite} : an opposite check. */ isFinite(actual) { return !isNaN(actual) && actual !== Infinity && actual !== -Infinity; }, /** * Checks that a number is either `Infinity` or `-Infinity`. * * Performs no type guarding. * * @example * * ```ts * import {check} from '@augment-vir/assert'; * * check.isInfinite(10); // returns `false` * check.isInfinite(parseInt('invalid')); // returns `false` * check.isInfinite(Infinity); // returns `true` * check.isInfinite(-Infinity); // returns `true` * ``` * * @see * - {@link check.isNaN} : an opposite check. * - {@link check.isInfinite} : an opposite check. */ isInfinite(actual) { return actual === Infinity || actual === -Infinity; }, /** * Checks that a number is within ±`delta` of the expectation. * * Performs no type guarding. * * @example * * ```ts * import {check} from '@augment-vir/assert'; * * check.isApproximately(10, 8, 4); // returns `true` * check.isApproximately(10, 12, 4); // returns `true` * check.isApproximately(10, 8, 1); // returns `false` * check.isApproximately(10, 12, 1); // returns `false` * ``` * * @see * - {@link check.isNotApproximately} : the opposite check. */ isApproximately(actual, expected, delta) { return expected - delta <= actual && actual <= expected + delta; }, /** * Checks that a number is outside ±`delta` of the expectation. * * Performs no type guarding. * * @example * * ```ts * import {check} from '@augment-vir/assert'; * * check.isNotApproximately(10, 8, 4); // returns `false` * check.isNotApproximately(10, 12, 4); // returns `false` * check.isNotApproximately(10, 8, 1); // returns `true` * check.isNotApproximately(10, 12, 1); // returns `true` * ``` * * @see * - {@link check.isApproximately} : the opposite check. */ isNotApproximately(actual, expected, delta) { return actual < expected - delta || actual > expected + delta; }, }, assertWrap: { /** * Asserts that a number is inside the provided min and max bounds, inclusive. Returns the * number if the assertion passes. * * Performs no type guarding. * * @example * * ```ts * import {assertWrap} from '@augment-vir/assert'; * * assertWrap.isInBounds(5, {min: 1, max: 10}); // returns `5` * assertWrap.isInBounds(10, {min: 1, max: 10}); // returns `10` * assertWrap.isInBounds(11, {min: 1, max: 10}); // fails * assertWrap.isInBounds(0, {min: 1, max: 10}); // fails * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assertWrap.isOutBounds} : the opposite assertion. */ isInBounds(actual, { max, min }, failureMessage) { if (actual < min || max < actual) { throw new AssertionError(`${actual} is not within the bounds ${stringify({ min, max })}`, failureMessage); } return actual; }, /** * Asserts that a number is outside the provided min and max bounds, exclusive. Returns the * number if the assertion passes. * * Performs no type guarding. * * @example * * ```ts * import {assertWrap} from '@augment-vir/assert'; * * assertWrap.isOutBounds(5, {min: 1, max: 10}); // fails * assertWrap.isOutBounds(10, {min: 1, max: 10}); // fails * assertWrap.isOutBounds(11, {min: 1, max: 10}); // returns `11` * assertWrap.isOutBounds(0, {min: 1, max: 10}); // returns `0` * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assertWrap.isInBounds} : the opposite assertion. */ isOutBounds(actual, { min, max }, failureMessage) { if (min <= actual && actual <= max) { throw new AssertionError(`${actual} is not outside the bounds ${stringify({ min, max })}`, failureMessage); } return actual; }, /** * Asserts that a number is an integer. Returns the number if the assertion passes. This has * the same limitations as * https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger. * * Performs no type guarding. * * @example * * ```ts * import {assertWrap} from '@augment-vir/assert'; * * assertWrap.isInteger(5); // returns `5` * assertWrap.isInteger(5.0000000000000001); // returns `5` * assertWrap.isInteger(5.1); // fails * assertWrap.isInteger(NaN); // fails * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assertWrap.isNotInteger} : the opposite assertion. */ isInteger(actual, failureMessage) { if (typeof actual !== 'number' || isNaN(actual) || !Number.isInteger(actual)) { throw new AssertionError(`${actual} is not an integer.`, failureMessage); } return actual; }, /** * Asserts that a number is not an integer. Returns the number if the assertion passes. This * has the same limitations, as * https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger. * * Performs no type guarding. * * @example * * ```ts * import {assertWrap} from '@augment-vir/assert'; * * assertWrap.isNotInteger(5); // fails * assertWrap.isNotInteger(5.0000000000000001); // fails * assertWrap.isNotInteger(5.1); // returns `5.1` * assertWrap.isNotInteger(NaN); // returns `NaN` * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assertWrap.isInteger} : the opposite assertion. */ isNotInteger(actual, failureMessage) { if (Number.isInteger(actual)) { throw new AssertionError(`${actual} is an integer.`, failureMessage); } return actual; }, /** * Asserts that a number is above the expectation (`actual > expected`). Returns the number * if the assertion passes. * * Performs no type guarding. * * @example * * ```ts * import {assertWrap} from '@augment-vir/assert'; * * assertWrap.isAbove(10, 5); // returns `10` * assertWrap.isAbove(5, 5); // throws an error * assertWrap.isAbove(5, 10); // throws an error * ``` * * @returns The value if the assertion passes. * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assertWrap.isBelow} : the opposite assertion. * - {@link assertWrap.isAtLeast} : the more lenient assertion. */ isAbove(actual, expected, failureMessage) { if (actual <= expected) { throw new AssertionError(`${actual} is not above ${expected}`, failureMessage); } return actual; }, /** * Asserts that a number is at least the expectation (`actual >= expected`). Returns the * number if the assertion passes. * * Performs no type guarding. * * @example * * ```ts * import {assertWrap} from '@augment-vir/assert'; * * assertWrap.isAtLeast(10, 5); // returns `10` * assertWrap.isAtLeast(5, 5); // returns `5` * assertWrap.isAtLeast(5, 10); // throws an error * ``` * * @returns The value if the assertion passes. * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assertWrap.isAtMost} : the opposite assertion. * - {@link assertWrap.isAbove} : the more restrictive assertion. */ isAtLeast(actual, expected, failureMessage) { if (actual < expected) { throw new AssertionError(`${actual} is not at least ${expected}`, failureMessage); } return actual; }, /** * Asserts that a number is below the expectation (`actual < expected`). Returns the number * if the assertion passes. * * Performs no type guarding. * * @example * * ```ts * import {assertWrap} from '@augment-vir/assert'; * * assertWrap.isBelow(10, 5); // throws an error * assertWrap.isBelow(5, 5); // throws an error * assertWrap.isBelow(5, 10); // returns `5` * ``` * * @returns The value if the assertion passes. * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assertWrap.isAbove} : the opposite assertion. * - {@link assertWrap.isAtMost} : the more lenient assertion. */ isBelow(actual, expected, failureMessage) { if (actual >= expected) { throw new AssertionError(`${actual} is not below ${expected}`, failureMessage); } return actual; }, /** * Asserts that a number is at most the expectation (`actual <= expected`). Returns the * number if the assertion passes. * * Performs no type guarding. * * @example * * ```ts * import {assertWrap} from '@augment-vir/assert'; * * assertWrap.isAtMost(10, 5); // throws an error * assertWrap.isAtMost(5, 5); // returns `5` * assertWrap.isAtMost(5, 10); // returns `5` * ``` * * @returns The value if the assertion passes. * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assertWrap.isAtLeast} : the opposite assertion. * - {@link assertWrap.isBelow} : the more restrictive assertion. */ isAtMost(actual, expected, failureMessage) { if (actual > expected) { throw new AssertionError(`${actual} is not at most ${expected}`, failureMessage); } return actual; }, /** * Asserts that a number is * [`NaN`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/NaN). * Returns the number if the assertion passes. * * Performs no type guarding. * * @example * * ```ts * import {assertWrap} from '@augment-vir/assert'; * * assertWrap.isNaN(10); // throws an error * assertWrap.isNaN(parseInt('invalid')); // returns `NaN` * assertWrap.isNaN(Infinity); // throws an error * ``` * * @returns The value if the assertion passes. * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assertWrap.isNumber} : can be used as the opposite assertion. */ isNaN(actual, failureMessage) { if (!isNaN(actual)) { throw new AssertionError(`${actual} is not NaN`, failureMessage); } return actual; }, /** * Asserts that a number is finite: meaning, not `NaN` and not `Infinity` or `-Infinity`. * Returns the number if the assertion passes. * * Performs no type guarding. * * @example * * ```ts * import {assertWrap} from '@augment-vir/assert'; * * assertWrap.isFinite(10); // returns `10` * assertWrap.isFinite(parseInt('invalid')); // throws an error * assertWrap.isFinite(Infinity); // throws an error * assertWrap.isFinite(-Infinity); // throws an error * ``` * * @returns The value if the assertion passes. * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assertWrap.isNaN} : an opposite assertion. * - {@link assertWrap.isInfinite} : an opposite assertion. */ isFinite(actual, failureMessage) { if (isNaN(actual) || actual === Infinity || actual === -Infinity) { throw new AssertionError(`${actual} is not finite`, failureMessage); } return actual; }, /** * Asserts that a number is either `Infinity` or `-Infinity`. Returns the number if the * assertion passes. * * Performs no type guarding. * * @example * * ```ts * import {assertWrap} from '@augment-vir/assert'; * * assertWrap.isInfinite(10); // throws an error * assertWrap.isInfinite(parseInt('invalid')); // throws an error * assertWrap.isInfinite(Infinity); // returns `Infinity` * assertWrap.isInfinite(-Infinity); // returns `-Infinity` * ``` * * @returns The value if the assertion passes. * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assertWrap.isNaN} : an opposite assertion. * - {@link assertWrap.isInfinite} : an opposite assertion. */ isInfinite(actual, failureMessage) { if (actual !== Infinity && actual !== -Infinity) { throw new AssertionError(`${actual} is not infinite`, failureMessage); } return actual; }, /** * Asserts that a number is within ±`delta` of the expectation. Returns the number if the * assertion passes. * * Performs no type guarding. * * @example * * ```ts * import {assertWrap} from '@augment-vir/assert'; * * assertWrap.isApproximately(10, 8, 4); // returns `10` * assertWrap.isApproximately(10, 12, 4); // returns `10` * assertWrap.isApproximately(10, 8, 1); // throws an error * assertWrap.isApproximately(10, 12, 1); // throws an error * ``` * * @returns The value if the assertion passes. * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assertWrap.isNotApproximately} : the opposite assertion. */ isApproximately(actual, expected, delta, failureMessage) { if (actual < expected - delta || actual > expected + delta) { throw new AssertionError(`${actual} is not within ±${delta} of ${expected}`, failureMessage); } return actual; }, /** * Asserts that a number is outside ±`delta` of the expectation. Returns the number if the * assertion passes. * * Performs no type guarding. * * @example * * ```ts * import {assertWrap} from '@augment-vir/assert'; * * assertWrap.isNotApproximately(10, 8, 4); // throws an error * assertWrap.isNotApproximately(10, 12, 4); // throws an error * assertWrap.isNotApproximately(10, 8, 1); // returns `10` * assertWrap.isNotApproximately(10, 12, 1); // returns `10` * ``` * * @returns The value if the assertion passes. * @throws {@link AssertionError} If the assertion fails. * @see * - {@link assertWrap.isApproximately} : the opposite assertion. */ isNotApproximately(actual, expected, delta, failureMessage) { if (actual >= expected - delta && actual <= expected + delta) { throw new AssertionError(`${actual} is within ±${delta} of ${expected}`, failureMessage); } return actual; }, }, checkWrap: { /** * Checks that a number is inside the provided min and max bounds, inclusive. Returns the * number if the check passes, otherwise `undefined`. * * Performs no type guarding. * * @example * * ```ts * import {checkWrap} from '@augment-vir/assert'; * * checkWrap.isInBounds(5, {min: 1, max: 10}); // returns `5` * checkWrap.isInBounds(10, {min: 1, max: 10}); // returns `10` * checkWrap.isInBounds(11, {min: 1, max: 10}); // returns `undefined` * checkWrap.isInBounds(0, {min: 1, max: 10}); // returns `undefined` * ``` * * @see * - {@link checkWrap.isOutBounds} : the opposite check. */ isInBounds(actual, { max, min }) { if (min <= actual && actual <= max) { return actual; } else { return undefined; } }, /** * Checks that a number is outside the provided min and max bounds, exclusive. Returns the * number if the check passes, otherwise `undefined`. * * Performs no type guarding. * * @example * * ```ts * import {checkWrap} from '@augment-vir/assert'; * * checkWrap.isOutBounds(5, {min: 1, max: 10}); // returns `undefined` * checkWrap.isOutBounds(10, {min: 1, max: 10}); // returns `undefined` * checkWrap.isOutBounds(11, {min: 1, max: 10}); // returns `11` * checkWrap.isOutBounds(0, {min: 1, max: 10}); // returns `0` * ``` * * @see * - {@link checkWrap.isInBounds} : the opposite check. */ isOutBounds(actual, { max, min }) { if (actual < min || max < actual) { return actual; } else { return undefined; } }, /** * Checks that a number is an integer. Returns the number if the check passes, otherwise * `undefined`. This has the same limitations as * https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger. * * Performs no type guarding. * * @example * * ```ts * import {checkWrap} from '@augment-vir/assert'; * * checkWrap.isInteger(5); // returns `5` * checkWrap.isInteger(5.0000000000000001); // returns `5` * checkWrap.isInteger(5.1); // returns `undefined` * checkWrap.isInteger(NaN); // returns `undefined` * ``` * * @see * - {@link checkWrap.isNotInteger} : the opposite check. */ isInteger(actual) { if (typeof actual === 'number' && !isNaN(actual) && Number.isInteger(actual)) { return actual; } else { return undefined; } }, /** * Checks that a number is not an integer. Returns the number if the check passes, otherwise * `undefined`. This has the same limitations, as * https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger. * * Performs no type guarding. * * @example * * ```ts * import {checkWrap} from '@augment-vir/assert'; * * checkWrap.isNotInteger(5); // returns `undefined` * checkWrap.isNotInteger(5.0000000000000001); // returns `undefined` * checkWrap.isNotInteger(5.1); // returns `5.1` * checkWrap.isNotInteger(NaN); // returns `NaN` * ``` * * @see * - {@link checkWrap.isInteger} : the opposite check. */ isNotInteger(actual) { if (typeof actual !== 'number' || isNaN(actual) || !Number.isInteger(actual)) { return actual; } else { return undefined; } }, /** * Checks that a number is above the expectation (`actual > expected`). Returns the number * if the check passes, otherwise `undefined`. * * Performs no type guarding. * * @example * * ```ts * import {checkWrap} from '@augment-vir/assert'; * * checkWrap.isAbove(10, 5); // returns `10` * checkWrap.isAbove(5, 5); // returns `undefined` * checkWrap.isAbove(5, 10); // returns `undefined` * ``` * * @returns The value if the check passes, otherwise `undefined`. * @see * - {@link checkWrap.isBelow} : the opposite check. * - {@link checkWrap.isAtLeast} : the more lenient check. */ isAbove(actual, expected) { if (actual > expected) { return actual; } else { return undefined; } }, /** * Checks that a number is at least the expectation (`actual >= expected`). Returns the * number if the check passes, otherwise `undefined`. * * Performs no type guarding. * * @example * * ```ts * import {checkWrap} from '@augment-vir/assert'; * * checkWrap.isAtLeast(10, 5); // returns `10` * checkWrap.isAtLeast(5, 5); // returns `5` * checkWrap.isAtLeast(5, 10); // returns `undefined` * ``` * * @returns The value if the check passes, otherwise `undefined`. * @see * - {@link checkWrap.isAtMost} : the opposite check. * - {@link checkWrap.isAbove} : the more restrictive check. */ isAtLeast(actual, expected) { if (actual >= expected) { return actual; } else { return undefined; } }, /** * Checks that a number is below the expectation (`actual < expected`). Returns the number * if the check passes, otherwise `undefined`. * * Performs no type guarding. * * @example * * ```ts * import {checkWrap} from '@augment-vir/assert'; * * checkWrap.isBelow(10, 5); // returns `undefined` * checkWrap.isBelow(5, 5); // returns `undefined` * checkWrap.isBelow(5, 10); // returns `5` * ``` * * @returns The value if the check passes, otherwise `undefined`. * @see * - {@link checkWrap.isAbove} : the opposite check. * - {@link checkWrap.isAtMost} : the more lenient check. */ isBelow(actual, expected) { if (actual < expected) { return actual; } else { return undefined; } }, /** * Checks that a number is at most the expectation (`actual <= expected`). Returns the * number if the check passes, otherwise `undefined`. * * Performs no type guarding. * * @example * * ```ts * import {checkWrap} from '@augment-vir/assert'; * * checkWrap.isAtMost(10, 5); // returns `undefined` * checkWrap.isAtMost(5, 5); // returns `5` * checkWrap.isAtMost(5, 10); // returns `5` * ``` * * @returns The value if the check passes, otherwise `undefined`. * @see * - {@link checkWrap.isAtLeast} : the opposite check. * - {@link checkWrap.isBelow} : the more restrictive check. */ isAtMost(actual, expected) { if (actual <= expected) { return actual; } else { return undefined; } }, /** * Checks that a number is * [`NaN`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/NaN). * Returns the number if the check passes, otherwise `undefined`. * * Performs no type guarding. * * @example * * ```ts * import {checkWrap} from '@augment-vir/assert'; * * checkWrap.isNaN(10); // returns `undefined` * checkWrap.isNaN(parseInt('invalid')); // returns `NaN` * checkWrap.isNaN(Infinity); // returns `undefined` * ``` * * @returns The value if the check passes, otherwise `undefined`. * @see * - {@link checkWrap.isNumber} : can be used as the opposite check. */ isNaN(actual) { if (isNaN(actual)) { return actual; } else { return undefined; } }, /** * Checks that a number is finite: meaning, not `NaN` and not `Infinity` or `-Infinity`. * Returns the number if the check passes, otherwise `undefined`. * * Performs no type guarding. * * @example * * ```ts * import {checkWrap} from '@augment-vir/assert'; * * checkWrap.isFinite(10); // returns `10` * checkWrap.isFinite(parseInt('invalid')); // returns `undefined` * checkWrap.isFinite(Infinity); // returns `undefined` * checkWrap.isFinite(-Infinity); // returns `undefined` * ``` * * @returns The value if the check passes, otherwise `undefined`. * @see * - {@link checkWrap.isNaN} : an opposite check. * - {@link checkWrap.isInfinite} : an opposite check. */ isFinite(actual) { if (!isNaN(actual) && actual !== Infinity && actual !== -Infinity) { return actual; } else { return undefined; } }, /** * Checks that a number is either `Infinity` or `-Infinity`. Returns the number if the check * passes, otherwise `undefined`. * * Performs no type guarding. * * @example * * ```ts * import {checkWrap} from '@augment-vir/assert'; * * checkWrap.isInfinite(10); // returns `undefined` * checkWrap.isInfinite(parseInt('invalid')); // returns `undefined` * checkWrap.isInfinite(Infinity); // returns `Infinity` * checkWrap.isInfinite(-Infinity); // returns `-Infinity` * ``` * * @returns The value if the check passes, otherwise `undefined`. * @see * - {@link checkWrap.isNaN} : an opposite check. * - {@link checkWrap.isInfinite} : an opposite check. */ isInfinite(actual) { if (actual === Infinity || actual === -Infinity) { return actual; } else { return undefined; } }, /** * Checks that a number is within ±`delta` of the expectation. Returns the number if the * check passes, otherwise `undefined`. * * Performs no type guarding. * * @example * * ```ts * import {checkWrap} from '@augment-vir/assert'; * * checkWrap.isApproximately(10, 8, 4); // returns `10` * checkWrap.isApproximately(10, 12, 4); // returns `10` * checkWrap.isApproximately(10, 8, 1); // returns `undefined` * checkWrap.isApproximately(10, 12, 1); // returns `undefined` * ``` * * @returns The value if the check passes, otherwise `undefined`. * @see * - {@link checkWrap.isNotApproximately} : the opposite check. */ isApproximately(actual, expected, delta) { if (expected - delta <= actual && actual <= expected + delta) { return actual; } else { return undefined; } }, /** * Checks that a number is outside ±`delta` of the expectation. Returns the number if the * check passes, otherwise `undefined`. * * Performs no type guarding. * * @example * * ```ts * import {checkWrap} from '@augment-vir/assert'; * * checkWrap.isNotApproximately(10, 8, 4); // returns `undefined` * checkWrap.isNotApproximately(10, 12, 4); // returns `undefined` * checkWrap.isNotApproximately(10, 8, 1); // returns `10` * checkWrap.isNotApproximately(10, 12, 1); // returns `10` * ``` * * @returns The value if the check passes, otherwise `undefined`. * @see * - {@link checkWrap.isApproximately} : the opposite check. */ isNotApproximately(actual, expected, delta) { if (actual < expected - delta || actual > expected + delta) { return actual; } else { return undefined; } }, }, waitUntil: { /** * Repeatedly calls a callback until its output is a number is inside the provided min and * max bounds, inclusive. If the attempts time out, an error is thrown. * * Performs no type guarding. * * @example * * ```ts * import {waitUntil} from '@augment-vir/assert'; * * waitUntil.isInBounds(5, {min: 1, max: 10}); // passes * waitUntil.isInBounds(10, {min: 1, max: 10}); // passes * waitUntil.isInBounds(11, {min: 1, max: 10}); // fails * waitUntil.isInBounds(0, {min: 1, max: 10}); // fails * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link waitUntil.isOutBounds} : the opposite assertion. */ isInBounds: createWaitUntil(assertions.isInBounds), /** * Repeatedly calls a callback until its output is outside the provided min and max bounds, * exclusive. If the attempts time out, an error is thrown. * * Performs no type guarding. * * @example * * ```ts * import {waitUntil} from '@augment-vir/assert'; * * waitUntil.isOutBounds(5, {min: 1, max: 10}); // fails * waitUntil.isOutBounds(10, {min: 1, max: 10}); // fails * waitUntil.isOutBounds(11, {min: 1, max: 10}); // passes * waitUntil.isOutBounds(0, {min: 1, max: 10}); // passes * ``` * * @throws {@link AssertionError} If the assertion fails. * @see * - {@link waitUntil.isInBounds} : the opposite assertion. */ isOutBounds: createWaitUntil(assertions.isOutBounds), /** * Repeatedly calls a callback until its output is an integer. This has the same limitations * as * https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger. * If the attempts time out, an e