Skip to content

Commit

Permalink
feat(expect): add anything function
Browse files Browse the repository at this point in the history
  • Loading branch information
TomokiMiyauci committed Nov 30, 2021
1 parent eb9f47b commit d9b495b
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 11 deletions.
1 change: 1 addition & 0 deletions dev_deps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { assertThrows } from "https://deno.land/std@0.115.1/testing/asserts.ts";
export {
assert,
assertExists,
assertRejects,
assertThrows,
} from "https://deno.land/std@0.115.1/testing/asserts.ts";
Expand Down
21 changes: 13 additions & 8 deletions expect/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,18 @@ expect(10).toBeGreaterThan(3);

This allows TypeScript to do some of the assertions for you.

## Differences from jest
## anything

Unitest prefers to be loosely coupled, simple and low on code.
`anything()` matches anything but `null` or `undefined`.

It does not implement some of the things implemented in jest, and provides other
ways.

| jest | unitest |
| ----------------------------------------------------------------- | -------------- |
| [expect.anything()](https://jestjs.io/docs/expect#expectanything) | toBeAnything() |
```ts
import {
anything,
expect,
test,
} from "https://deno.land/x/unitest@$VERSION/mod.ts";

test("should not be null or undefined", () => {
expect(actual).toEqual(anything());
});
```
22 changes: 22 additions & 0 deletions expect/anything.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2021-Present the Unitest authors. All rights reserved. MIT license.
import { equality } from "../helper/equal.ts";
import { isNil } from "../deps.ts";
import type { Equality } from "../helper/equal.ts";

/** equal to anything */
class Anything implements Equality {
[equality](actual: unknown): boolean {
return !isNil(actual);
}

toString(): string {
return "except undefined or null";
}
}

/** make Anything */
function anything(): Anything {
return new Anything();
}

export { Anything, anything };
25 changes: 25 additions & 0 deletions expect/anything_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2021-Present the Unitest authors. All rights reserved. MIT license.
import { Anything, anything } from "./anything.ts";
import { equality } from "../helper/equal.ts";
import { assertEquals, assertExists } from "../dev_deps.ts";

Deno.test({
name: "Anything",
fn: () => {
const anything = new Anything();
assertExists(anything.toString);
assertExists(anything[equality]);

assertEquals(anything.toString(), "except undefined or null");
assertEquals(anything[equality](undefined), false);
assertEquals(anything[equality](null), false);
assertEquals(anything[equality]({}), true);
},
});

Deno.test({
name: "anything",
fn: () => {
assertEquals(anything(), new Anything());
},
});
6 changes: 4 additions & 2 deletions expect/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { jestMatcherMap } from "../matcher/preset.ts";
import { jestModifierMap } from "../modifier/preset.ts";
import { AssertionError, isPromise } from "../deps.ts";
import { stringify, stringifyResult } from "../helper/format.ts";
import { anything } from "./anything.ts";

import type {
AnyFn,
Expand All @@ -25,6 +26,7 @@ import {
expectTo,
promiseExpectTo,
} from "./_utils.ts";
import { stringifyEquality } from "../helper/equal.ts";
import type { ModifierMap } from "../modifier/types.ts";
import type { MatcherMap } from "../matcher/types.ts";
import type { StringifyResultArgs } from "../helper/format.ts";
Expand Down Expand Up @@ -108,7 +110,7 @@ function defineExpect<
matcherArgs,
matcher: String(name),
actualValue,
expectedValue,
expectedValue: stringifyEquality(expectedValue),
expectedHint,
actualHint,
preModifier: pre?.[0],
Expand Down Expand Up @@ -159,5 +161,5 @@ function expect<T>(actual: T) {
})(actual);
}

export { defineExpect, expect };
export { anything, defineExpect, expect };
export type { Expected, MatcherMap };
38 changes: 38 additions & 0 deletions helper/equal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2021-Present the Unitest authors. All rights reserved. MIT license.
import { equal as eq, isObject } from "../deps.ts";

/** Symbol for equality */
const equality = Symbol.for("equality");

interface Equality {
[equality]: (actual: unknown) => boolean;
toString: () => string;
}

/** Whatever argument is `Equality` or not */
function isEquality(value: object): value is Equality {
return equality in value;
}

/** safe stringify for `Equality` */
function stringifyEquality<T>(value: T): T | string {
if (isObject(value) && isEquality(value)) {
return value.toString();
}

return value;
}

/** Deep equality comparison used in assertions */
function equal(
a: unknown,
b: unknown,
): boolean {
if (isObject(b) && isEquality(b)) {
return b[equality](a);
}
return eq(a, b);
}

export { equal, equality, isEquality, stringifyEquality };
export type { Equality };
67 changes: 67 additions & 0 deletions helper/equal_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2021-Present the Unitest authors. All rights reserved. MIT license.
import { equal, equality, isEquality, stringifyEquality } from "./equal.ts";
import { anything } from "../expect/anything.ts";
import { fn } from "../mock/fn.ts";
import { assertEquals } from "../dev_deps.ts";

Deno.test("equality", () => assertEquals(equality, Symbol.for("equality")));

Deno.test("isEquality", () => {
const table: [
...Parameters<typeof isEquality>,
ReturnType<typeof isEquality>,
][] = [
[{}, false],
[[], false],
[{
[equality]: true,
}, true],
[{
[equality]: () => true,
}, true],
];

table.forEach(([value, result]) => assertEquals(isEquality(value), result));
});

Deno.test("equal", () => {
const table: [
...Parameters<typeof equal>,
ReturnType<typeof equal>,
][] = [
[null, anything(), false],
[{}, anything(), true],
[{}, {}, true],
];

table.forEach(([a, b, result]) => assertEquals(equal(a, b), result));

const mock = fn();
equal({}, {
[equality]: mock,
});

assertEquals(mock.mock.calls.length, 1);
});

Deno.test("stringifyEquality", () => {
const table: [
...Parameters<typeof stringifyEquality>,
ReturnType<typeof stringifyEquality>,
][] = [
[false, false],
[[], []],
[{
[equality]: true,
toString: () => "equal",
}, "equal"],
[{
[equality]: true,
toString: () => "any",
}, "any"],
];

table.forEach(([value, result]) =>
assertEquals(stringifyEquality(value), result)
);
});
6 changes: 5 additions & 1 deletion mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,14 @@ export * from "./matcher/utils.ts";

export * from "./mock/fn.ts";
export * from "./mock/types.ts";
export * from "./expect/mod.ts";
export { defineExpect, expect } from "./expect/mod.ts";
export type { Expected, MatcherMap } from "./expect/mod.ts";
export { anything } from "./expect/anything.ts";

export { not } from "./modifier/not.ts";
export { rejects } from "./modifier/rejects.ts";
export { resolves } from "./modifier/resolves.ts";
export * from "./modifier/preset.ts";
export * from "./test/mod.ts";

export { equal, equality } from "./helper/equal.ts";

0 comments on commit d9b495b

Please sign in to comment.