@augment-vir/assert
Version:
A collection of assertions for test and production code alike.
1,423 lines • 60.8 kB
JavaScript
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