Skip to content

Commit

Permalink
feat(assertion): Add typeof based matcher (#91)
Browse files Browse the repository at this point in the history
  • Loading branch information
JoseLion authored Jul 24, 2023
1 parent 25a7589 commit 6e07131
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 1 deletion.
48 changes: 48 additions & 0 deletions package/src/lib/Assertion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ export interface Constructor<T> extends Function {
prototype: T;
}

export type DataType =
| "array"
| "bigint"
| "boolean"
| "function"
| "number"
| "object"
| "string"
| "symbol"
| "undefined";

export interface ExecuteOptions {
/**
* The condition for when the assertion should pass. The negation of this
Expand Down Expand Up @@ -429,6 +440,43 @@ export class Assertion<T> {
});
}

/**
* Checks if the value is of a specific data type. The supported data types
* are the same as the `typeof` operator, plus an additional `array` which
* allows desabiguation between `object` (which can also be an array).
*
* @example
* ```
* const arr = [1, 2, 3];
*
* expect(arr).toBeOfType("array");
* expect(arr[0]).toBeOfType("number");
* expect(arr[9]).toBeOfType("undefined");
* ```
*
* @param expected the expected data type
* @returns the assertion instance
*/
public toBeOfType(expected: DataType): this {
const error = new AssertionError({
actual: typeof this.actual,
expected,
message: `Expected <${prettify(this.actual)}> to be of type <${expected}>`,
});
const invertedError = new AssertionError({
actual: typeof this.actual,
message: `Expected <${prettify(this.actual)}> NOT to be of type <${expected}>`,
});

return this.execute({
assertWhen: expected === "array"
? Array.isArray(this.actual)
: typeof this.actual === expected,
error,
invertedError,
});
}

/**
* Check first if the value is of some specific type, in which case returns
* an assertion instance for that specific type. The new assertion is built
Expand Down
57 changes: 56 additions & 1 deletion package/test/lib/Assertion.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Assertion } from "../../src/lib/Assertion";
import { Assertion, DataType } from "../../src/lib/Assertion";
import { StringAssertion } from "../../src/lib/StringAssertion";
import { UnsupportedOperationError } from "../../src/lib/errors/UnsupportedOperationError";
import { TypeFactories } from "../../src/lib/helpers/TypeFactories";
import { prettify } from "../../src/lib/helpers/messages";

import assert, { AssertionError } from "assert";

Expand Down Expand Up @@ -471,6 +472,60 @@ describe("[Unit] Assertion.test.ts", () => {
});
});

describe(".toBeOfType", () => {
context("when the type of the value is of the expected type", () => {
const variants: Array<[DataType, unknown]> = [
["array", [1, 2, 3]],
["bigint", BigInt(9)],
["boolean", true],
["function", () => undefined],
["number", 10],
["object", { foo: 1 }],
["string", "foo"],
["symbol", Symbol("id")],
["undefined", undefined],
];

variants.forEach(([expected, value]) => {
it(`[${expected}] returns the assertion instance`, () => {
const test = new Assertion(value);

assert.deepStrictEqual(test.toBeOfType(expected), test);
assert.throws(() => test.not.toBeOfType(expected), {
message: `Expected <${prettify(value)}> NOT to be of type <${expected}>`,
name: AssertionError.name,
});
});
});
});

context("when the type of the value is NOT of the expected type", () => {
const variants: Array<[DataType, unknown]> = [
["array", { x: [1, 2, 3] }],
["bigint", 9],
["boolean", "false"],
["function", { foo: () => undefined }],
["number", BigInt(10)],
["object", "foo"],
["string", Symbol("id")],
["symbol", undefined],
["undefined", null],
];

variants.forEach(([expected, value]) => {
it(`[${expected}] throws an assertion error`, () => {
const test = new Assertion(value);

assert.throws(() => test.toBeOfType(expected), {
message: `Expected <${prettify(value)}> to be of type <${expected}>`,
name: AssertionError.name,
});
assert.deepStrictEqual(test.not.toBeOfType(expected), test);
});
});
});
});

describe(".asType", () => {
context("when the type predicate is true", () => {
it("returns a new instance of the assertion passed to the type factory", () => {
Expand Down

0 comments on commit 6e07131

Please sign in to comment.