Skip to content

Commit

Permalink
* getActual() now returns a specific type instead of unknown.
Browse files Browse the repository at this point in the history
* Moved TestGlobalConfiguration out of published source-code.
* Test that invalid type comparisons result in compile-time errors.
* Bugfix: StringValidator.toString() should not cast null to "null" if the validator contains failures.
  • Loading branch information
cowwoc committed Nov 23, 2023
1 parent 0bac9f2 commit 1bf4b4e
Show file tree
Hide file tree
Showing 72 changed files with 1,114 additions and 846 deletions.
1 change: 1 addition & 0 deletions .mocharc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ module.exports = {
exclude: [
"**/*.d.mts"
]
// slow: 0
};
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[![npm version](https://badge.fury.io/js/%40cowwoc%2Frequirements.svg)](https://badge.fury.io/js/%40cowwoc%2Frequirements)
[![build-status](https://github.com/cowwoc/requirements.js/workflows/Build/badge.svg)](https://github.com/cowwoc/requirements.js/actions?query=workflow%3ABuild)

# <img src="https://raw.githubusercontent.com/cowwoc/requirements.js/release-3.2.1/wiki/checklist.svg?sanitize=true" width=64 height=64 alt="checklist"> Fluent API for Design Contracts
# <img src="https://raw.githubusercontent.com/cowwoc/requirements.js/release-3.2.2/wiki/checklist.svg?sanitize=true" width=64 height=64 alt="checklist"> Fluent API for Design Contracts

[![API](https://img.shields.io/badge/api_docs-5B45D5.svg)](https://cowwoc.github.io/requirements.js/3.2.1/docs/api/)
[![API](https://img.shields.io/badge/api_docs-5B45D5.svg)](https://cowwoc.github.io/requirements.js/3.2.2/docs/api/)
[![Changelog](https://img.shields.io/badge/changelog-A345D5.svg)](wiki/Changelog.md)
[![java](https://img.shields.io/badge/other%20languages-java-457FD5.svg)](../../../requirements.java)

Expand All @@ -17,13 +17,13 @@ A [fluent API](https://en.wikipedia.org/wiki/Fluent_interface) for enforcing
To get started, add this dependency:

```shell
npm install --save @cowwoc/[email protected].1
npm install --save @cowwoc/[email protected].2
```

or [pnpm](https://pnpm.io/):

```shell
pnpm add @cowwoc/[email protected].1
pnpm add @cowwoc/[email protected].2
```

The contents of the API classes depend on which [modules](wiki/Supported_Libraries.md) are enabled.
Expand Down Expand Up @@ -67,13 +67,13 @@ Actual: 15
The best way to learn about the API is using your IDE's auto-complete engine.
There are six entry points you can navigate from:

* [requireThat(value, name)](https://cowwoc.github.io/requirements.js/3.2.1/docs/api/module-DefaultRequirements.html#~requireThat)
* [validateThat(value, name)](https://cowwoc.github.io/requirements.js/3.2.1/docs/api/module-DefaultRequirements.html#~validateThat)
* [assertThat(Function)](https://cowwoc.github.io/requirements.js/3.2.1/docs/api/module-DefaultRequirements.html#~assertThat)
* [assertThatAndReturn(Function)](https://cowwoc.github.io/requirements.js/3.2.1/docs/api/module-DefaultRequirements.html#~assertThatAndReturn)
* [requireThat(value, name)](https://cowwoc.github.io/requirements.js/3.2.2/docs/api/module-DefaultRequirements.html#~requireThat)
* [validateThat(value, name)](https://cowwoc.github.io/requirements.js/3.2.2/docs/api/module-DefaultRequirements.html#~validateThat)
* [assertThat(Function)](https://cowwoc.github.io/requirements.js/3.2.2/docs/api/module-DefaultRequirements.html#~assertThat)
* [assertThatAndReturn(Function)](https://cowwoc.github.io/requirements.js/3.2.2/docs/api/module-DefaultRequirements.html#~assertThatAndReturn)

* [Requirements](https://cowwoc.github.io/requirements.js/3.2.1/docs/api/module-Requirements-Requirements.html)
* [GlobalRequirements](https://cowwoc.github.io/requirements.js/3.2.1/docs/api/module-GlobalRequirements-GlobalRequirements.html)
* [Requirements](https://cowwoc.github.io/requirements.js/3.2.2/docs/api/module-Requirements-Requirements.html)
* [GlobalRequirements](https://cowwoc.github.io/requirements.js/3.2.2/docs/api/module-GlobalRequirements-GlobalRequirements.html)

## Best practices

Expand Down
6 changes: 4 additions & 2 deletions build.mts
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,10 @@ class Build

// tsconfig.json references the tests to suppress an ESLint warning, but we don't actually want to publish
// them.
const index = config.include.indexOf("test/**/*.mts", 0);
config.include.splice(index, 1);
config.include = config.include.filter((element: string) =>
{
return element !== "build.mts" && !element.startsWith("test/");
});
config.compilerOptions.outDir = "target/publish/node/";
config.compilerOptions.declaration = true;

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cowwoc/requirements",
"version": "3.2.1",
"version": "3.2.2",
"keywords": [
"preconditions",
"postconditions",
Expand Down
53 changes: 38 additions & 15 deletions src/ArrayValidator.mts
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,24 @@ import type {
* exceptions.
*
* All methods (except those found in {@link ObjectValidator}) imply {@link isNotNull}.
*
* @typeParam E - the type the array elements
*/
interface ArrayValidator extends ExtensibleObjectValidator<ArrayValidator>
interface ArrayValidator<E> extends ExtensibleObjectValidator<ArrayValidator<E>, E[]>
{
/**
* Ensures that the actual value is empty.
*
* @returns the updated validator
*/
isEmpty(): ArrayValidator;
isEmpty(): ArrayValidator<E>;

/**
* Ensures that the actual value is not empty.
*
* @returns the updated validator
*/
isNotEmpty(): ArrayValidator;
isNotEmpty(): ArrayValidator<E>;

/**
* Ensures that the array contains an element.
Expand All @@ -39,7 +41,7 @@ interface ArrayValidator extends ExtensibleObjectValidator<ArrayValidator>
* @throws TypeError if <code>name</code> is null
* @throws RangeError if <code>name</code> is empty
*/
contains(element: unknown, name?: string): ArrayValidator;
contains(element: E, name?: string): ArrayValidator<E>;

/**
* Ensures that the array contains exactly the specified elements; nothing less, nothing more.
Expand All @@ -50,7 +52,7 @@ interface ArrayValidator extends ExtensibleObjectValidator<ArrayValidator>
* @throws TypeError if <code>name</code> is null
* @throws RangeError if <code>name</code> is empty
*/
containsExactly(expected: unknown[], name?: string): ArrayValidator;
containsExactly(expected: E[], name?: string): ArrayValidator<E>;

/**
* Ensures that the array contains any of the specified elements.
Expand All @@ -61,7 +63,7 @@ interface ArrayValidator extends ExtensibleObjectValidator<ArrayValidator>
* @throws TypeError if <code>name</code> is null
* @throws RangeError if <code>name</code> is empty
*/
containsAny(expected: unknown[], name?: string): ArrayValidator;
containsAny(expected: E[], name?: string): ArrayValidator<E>;

/**
* Ensures that the array contains all the specified elements.
Expand All @@ -72,7 +74,7 @@ interface ArrayValidator extends ExtensibleObjectValidator<ArrayValidator>
* @throws TypeError if <code>name</code> is null
* @throws RangeError if <code>name</code> is empty
*/
containsAll(expected: unknown[], name?: string): ArrayValidator;
containsAll(expected: E[], name?: string): ArrayValidator<E>;

/**
* Ensures that the array does not contain an element.
Expand All @@ -83,7 +85,7 @@ interface ArrayValidator extends ExtensibleObjectValidator<ArrayValidator>
* @throws TypeError if <code>name</code> is null
* @throws RangeError if <code>name</code> is empty
*/
doesNotContain(element: unknown, name?: string): ArrayValidator;
doesNotContain(element: E, name?: string): ArrayValidator<E>;

/**
* Ensures that the array does not contain any of the specified elements.
Expand All @@ -94,7 +96,7 @@ interface ArrayValidator extends ExtensibleObjectValidator<ArrayValidator>
* @throws TypeError if <code>name</code> is null
* @throws RangeError if <code>name</code> is empty
*/
doesNotContainAny(elements: unknown[], name?: string): ArrayValidator;
doesNotContainAny(elements: E[], name?: string): ArrayValidator<E>;

/**
* Ensures that the array does not contain all the specified elements.
Expand All @@ -105,14 +107,14 @@ interface ArrayValidator extends ExtensibleObjectValidator<ArrayValidator>
* @throws TypeError if <code>name</code> is null
* @throws RangeError if <code>name</code> is empty
*/
doesNotContainAll(elements: unknown[], name?: string): ArrayValidator;
doesNotContainAll(elements: E[], name?: string): ArrayValidator<E>;

/**
* Ensures that the array does not contain any duplicate elements.
*
* @returns the updated validator
*/
doesNotContainDuplicates(): ArrayValidator;
doesNotContainDuplicates(): ArrayValidator<E>;

/**
* @returns a validator for the length of the array
Expand All @@ -124,23 +126,44 @@ interface ArrayValidator extends ExtensibleObjectValidator<ArrayValidator>
* @returns the updated validator
* @throws TypeError if <code>consumer</code> is not set
*/
lengthConsumer(consumer: (length: NumberValidator) => void): ArrayValidator;
lengthConsumer(consumer: (length: NumberValidator) => void): ArrayValidator<E>;

/**
* @returns a validator for the <code>Array</code>
* @deprecated returns this
*/
asArray(): ArrayValidator<E>;

asArray<E>(): ArrayValidator<E>;

/**
* @param consumer - a function that accepts a {@link ArrayValidator} for the actual value
* @returns the updated validator
* @throws TypeError if <code>consumer</code> is not set
*/
asArrayConsumer(consumer: (input: ArrayValidator<E>) => void): ArrayValidator<E>;

asArrayConsumer<E>(consumer: (input: ArrayValidator<E>) => void): ArrayValidator<E>;

/**
* Verifies the Set representation of the array.
*
* @returns a <code>Set</code> validator
*/
asSet(): SetValidator;
asSet(): SetValidator<E>;

asSet<E>(): SetValidator<E>;

/**
* @param consumer - a function that accepts a {@link SetValidator} for the Set representation of the array
* @returns the updated validator
* @throws TypeError if <code>consumer</code> is not set
*/
asSetConsumer(consumer: (actual: SetValidator) => void): ArrayValidator;
asSetConsumer(consumer: (actual: SetValidator<E>) => void): ArrayValidator<E>;

asSetConsumer<E>(consumer: (actual: SetValidator<E>) => void): ArrayValidator<E>;

getActual(): unknown[] | void;
getActual(): E[] | undefined;
}

export {type ArrayValidator};
55 changes: 40 additions & 15 deletions src/ArrayVerifier.mts
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,26 @@ import type {
* Verifies the requirements of an array.
*
* All methods (except those found in {@link ObjectVerifier}) imply {@link isNotNull}.
*
* @typeParam E - the type the array elements
*/
interface ArrayVerifier extends ExtensibleObjectVerifier<ArrayVerifier>
interface ArrayVerifier<E> extends ExtensibleObjectVerifier<ArrayVerifier<E>, E[]>
{
/**
* Ensures that the actual value is empty.
*
* @returns the updated verifier
* @throws RangeError if the actual value is not empty
*/
isEmpty(): ArrayVerifier;
isEmpty(): ArrayVerifier<E>;

/**
* Ensures that the actual value is not empty.
*
* @returns the updated verifier
* @throws RangeError if the actual value is empty
*/
isNotEmpty(): ArrayVerifier;
isNotEmpty(): ArrayVerifier<E>;

/**
* Ensures that the array contains an element.
Expand All @@ -37,7 +39,7 @@ interface ArrayVerifier extends ExtensibleObjectVerifier<ArrayVerifier>
* @throws RangeError if <code>name</code> is empty.
* If the array does not contain <code>element</code>.
*/
contains(element: unknown, name?: string): ArrayVerifier;
contains(element: E, name?: string): ArrayVerifier<E>;

/**
* Ensures that the array contains exactly the specified elements; nothing less, nothing more.
Expand All @@ -51,7 +53,7 @@ interface ArrayVerifier extends ExtensibleObjectVerifier<ArrayVerifier>
* If the array is missing any elements in <code>expected</code>.
* If the array contains elements not found in <code>expected</code>.
*/
containsExactly(expected: unknown[], name?: string): ArrayVerifier;
containsExactly(expected: E[], name?: string): ArrayVerifier<E>;

/**
* Ensures that the array contains any of the specified elements.
Expand All @@ -65,7 +67,7 @@ interface ArrayVerifier extends ExtensibleObjectVerifier<ArrayVerifier>
* If the array is missing any elements in <code>expected</code>.
* If the array contains elements not found in <code>expected</code>.
*/
containsAny(expected: unknown[], name?: string): ArrayVerifier;
containsAny(expected: E[], name?: string): ArrayVerifier<E>;

/**
* Ensures that the array contains all the specified elements.
Expand All @@ -78,7 +80,7 @@ interface ArrayVerifier extends ExtensibleObjectVerifier<ArrayVerifier>
* @throws RangeError if <code>name</code> is empty.
* If the array does not contain all of <code>expected</code>.
*/
containsAll(expected: unknown[], name?: string): ArrayVerifier;
containsAll(expected: E[], name?: string): ArrayVerifier<E>;

/**
* Ensures that the array does not contain an element.
Expand All @@ -90,7 +92,7 @@ interface ArrayVerifier extends ExtensibleObjectVerifier<ArrayVerifier>
* @throws RangeError if <code>name</code> is empty.
* If the array contains <code>element</code>.
*/
doesNotContain(element: unknown, name?: string): ArrayVerifier;
doesNotContain(element: E, name?: string): ArrayVerifier<E>;

/**
* Ensures that the array does not contain any of the specified elements.
Expand All @@ -103,7 +105,7 @@ interface ArrayVerifier extends ExtensibleObjectVerifier<ArrayVerifier>
* @throws RangeError if <code>name</code> is empty.
* If the array contains any of <code>elements</code>.
*/
doesNotContainAny(elements: unknown[], name?: string): ArrayVerifier;
doesNotContainAny(elements: E[], name?: string): ArrayVerifier<E>;

/**
* Ensures that the array does not contain all the specified elements.
Expand All @@ -116,15 +118,15 @@ interface ArrayVerifier extends ExtensibleObjectVerifier<ArrayVerifier>
* @throws RangeError if <code>name</code> is empty.
* If the array contains all of <code>elements</code>.
*/
doesNotContainAll(elements: unknown[], name?: string): ArrayVerifier;
doesNotContainAll(elements: E[], name?: string): ArrayVerifier<E>;

/**
* Ensures that the array does not contain any duplicate elements.
*
* @returns the updated verifier
* @throws RangeError if the array contains any duplicate elements
*/
doesNotContainDuplicates(): ArrayVerifier;
doesNotContainDuplicates(): ArrayVerifier<E>;

/**
* @returns a verifier for the length of the array
Expand All @@ -136,23 +138,46 @@ interface ArrayVerifier extends ExtensibleObjectVerifier<ArrayVerifier>
* @returns the updated verifier
* @throws TypeError if <code>consumer</code> is not set
*/
lengthConsumer(consumer: (actual: NumberVerifier) => void): ArrayVerifier;
lengthConsumer(consumer: (actual: NumberVerifier) => void): ArrayVerifier<E>;

/**
* @returns a verifier for the <code>Array</code>
* @throws TypeError if the actual value is not an <code>Array</code>
* @deprecated returns this
*/
asArray(): ArrayVerifier<E>;

asArray<E>(): ArrayVerifier<E>;

/**
* @param consumer - a function that accepts a {@link ArrayVerifier} for the actual value
* @returns the updated verifier
* @throws TypeError if <code>consumer</code> is not set.
* If the actual value is not an <code>Array</code>.
*/
asArrayConsumer(consumer: (actual: ArrayVerifier<E>) => void): ArrayVerifier<E>;

asArrayConsumer<E>(consumer: (actual: ArrayVerifier<E>) => void): ArrayVerifier<E>;

/**
* Verifies the Set representation of the array.
*
* @returns a <code>Set</code> verifier
*/
asSet(): SetVerifier;
asSet(): SetVerifier<E>;

asSet<E>(): SetVerifier<E>;

/**
* @param consumer - a function that accepts a {@link SetVerifier} for the Set representation of the array
* @returns the updated verifier
* @throws TypeError if <code>consumer</code> is not set
*/
asSetConsumer(consumer: (actual: SetVerifier) => void): ArrayVerifier;
asSetConsumer(consumer: (actual: SetVerifier<E>) => void): ArrayVerifier<E>;

asSetConsumer<E>(consumer: (actual: SetVerifier<E>) => void): ArrayVerifier<E>;

getActual(): unknown[];
getActual(): E[];
}

export {type ArrayVerifier};
4 changes: 2 additions & 2 deletions src/BooleanValidator.mts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type {ExtensibleObjectValidator} from "./internal/internal.mjs";
*
* All methods (except those found in {@link ObjectValidator}) imply {@link isNotNull}.
*/
interface BooleanValidator extends ExtensibleObjectValidator<BooleanValidator>
interface BooleanValidator extends ExtensibleObjectValidator<BooleanValidator, boolean>
{
/**
* Ensures that the actual value is true.
Expand All @@ -26,7 +26,7 @@ interface BooleanValidator extends ExtensibleObjectValidator<BooleanValidator>
*/
isFalse(): BooleanValidator;

getActual(): boolean | void;
getActual(): boolean | undefined;
}

export {type BooleanValidator};
Loading

0 comments on commit 1bf4b4e

Please sign in to comment.