Skip to content

Commit

Permalink
feat(assertion): Add .toBeInstanceOf(Constructor) matcher
Browse files Browse the repository at this point in the history
  • Loading branch information
JoseLion committed Aug 26, 2022
1 parent 3ec760a commit e0670de
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 1 deletion.
30 changes: 30 additions & 0 deletions src/lib/Assertion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,36 @@ export class Assertion<T> {
});
}

/**
* Check if the value is an instance of the the provided constructor.
*
* @example
* ```
* expect(pontiac).toBeInstanceOf(Car);
*
* expect(today).toBeInstanceOf(Date);
* ```
*
* @param Expected the constructor the value should be an instance
* @returns the assertion instance
*/
public toBeInstanceOf(Expected: new (...args: any[]) => any): this {
const error = new AssertionError({
actual: this.actual,
message: `Expected value to be an instance of <${Expected.name}>`
});
const invertedError = new AssertionError({
actual: this.actual,
message: `Expected value NOT to be an instance of <${Expected.name}>`
});

return this.execute({
assertWhen: this.actual instanceof Expected,
error,
invertedError
});
}

/**
* Check if the value is deep equal to another value.
*
Expand Down
2 changes: 1 addition & 1 deletion src/lib/ObjectAssertion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { isDeepStrictEqual } from "util";

import { Assertion } from "./Assertion";

export type JSObject = Record<keyof any, unknown>;
export type JSObject = Record<keyof any, any>;

export type Entry<T, K = keyof T> = K extends keyof T
? [K, T[K]]
Expand Down
47 changes: 47 additions & 0 deletions test/lib/Assertion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,19 @@ const BASE_DIFFS = [
["date", TODAY, new Date("2021-12-10T00:00:00.001Z")]
];

class Car {

private readonly model: string;

constructor(model: string) {
this.model = model;
}

public showModel(): string {
return this.model;
}
}

function truthyAsText(value: typeof TRUTHY_VALUES[number]): string {
if (Array.isArray(value) && value.length === 0) {
return "Empty array";
Expand Down Expand Up @@ -263,6 +276,40 @@ describe("[Unit] Assertion.test.ts", () => {
});
});

describe.only(".toBeInstanceOf", () => {
context("when the value is an instance of the constructor", () => {
const variants = [
[new Date(), Date],
[new Error("failed!"), Error],
[new Car("Pontiac GT-37"), Car]
] as const;

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

assert.deepStrictEqual(test.toBeInstanceOf(Constructor), test);
assert.throws(() => test.not.toBeInstanceOf(Constructor), {
message: `Expected value NOT to be an instance of <${Constructor.name}>`,
name: AssertionError.name
});
});
});
});

context("when the vlaue in not an instance of the constructor", () => {
it("throws an assertion error", () => {
const test = new Assertion(new Date());

assert.throws(() => test.toBeInstanceOf(Car), {
message: "Expected value to be an instance of <Car>",
name: AssertionError.name
});
assert.deepStrictEqual(test.not.toBeInstanceOf(Car), test);
});
});
});

describe(".toBeEqual", () => {
context("when the value is referentially, shallow, and deep equal", () => {
[
Expand Down

0 comments on commit e0670de

Please sign in to comment.