testing/src/expect/expect_test.ts

743 lines
16 KiB
TypeScript

import {
assertEquals,
AssertionError,
assertThrows,
} from "https://deno.land/std@0.106.0/testing/asserts.ts";
import { addMatchers, expect } from "./expect.ts";
import * as mock from "./mock.ts";
async function assertPass(fn: Function) {
try {
assertEquals(await fn(), undefined);
} catch (err) {
throw new AssertionError(
`expected ${fn.toString()} to pass but it failed with ${err}`,
);
}
}
async function assertAllPass(...fns: Function[]) {
for (let fn of fns) {
await assertPass(fn);
}
}
async function assertFail(fn: Function) {
let thrown = true;
try {
let resolution = await fn();
thrown = false;
throw new AssertionError(
`expected ${fn.toString()} to throw but it resolved with ${resolution}`,
);
} catch (err) {
// expected
if (!thrown) throw err;
}
}
async function assertAllFail(...fns: Function[]) {
for (let fn of fns) {
await assertFail(fn);
}
}
Deno.test({
name: "exportsFunction",
fn: () => {
assertEquals(typeof expect, "function");
},
});
Deno.test({
name: "throwsWhenNoMatcherFound",
fn: () => {
assertThrows(
//@ts-ignore
() => expect(true).toBeFancy(),
TypeError,
"matcher not found: toBeFancy",
);
},
});
Deno.test({
name: "allowsExtendingMatchers",
fn: () => {
addMatchers({
toBeFancy(value: any) {
if (value === "fancy") {
return { pass: true };
} else {
return { pass: false, message: "was not fancy" };
}
},
});
// @ts-ignore
assertPass(() => expect("fancy").toBeFancy());
},
});
Deno.test({
name: "toBe",
fn: async () => {
const obj = {};
assertEquals(typeof expect(obj).toBe, "function");
await assertAllPass(
() => expect(obj).toBe(obj),
() => expect(obj).not.toBe({}),
() => expect(Promise.resolve(1)).resolves.toBe(1),
() => expect(Promise.reject(1)).rejects.toBe(1),
);
await assertFail(() => expect(obj).toBe({}));
await assertFail(() => expect(obj).not.toBe(obj));
},
});
Deno.test({
name: "toEqual",
fn: async () => {
const obj = {};
await assertAllPass(
() => expect(1).toEqual(1),
() => expect(obj).toEqual({}),
() => expect(obj).toEqual(obj),
() => expect({ a: 1 }).toEqual({ a: 1 }),
() => expect([1]).toEqual([1]),
() => expect(Promise.resolve(1)).resolves.toEqual(1),
() => expect(Promise.reject(1)).rejects.toEqual(1),
);
await assertAllFail(
() => expect(1).toEqual(2),
() => expect(1).toEqual(true),
() => expect({}).toEqual(true),
() => expect(1).not.toEqual(1),
() => expect(true).not.toEqual(true),
);
},
});
Deno.test({
name: "resolves",
fn: async () => {
const resolves = expect(Promise.resolve(true)).resolves;
for (let method of ["toEqual", "toBe", "toBeTruthy", "toBeFalsy"]) {
assertEquals(
typeof (resolves as any)[method],
"function",
`missing ${method}`,
);
}
},
});
Deno.test({
name: "rejects",
fn: async () => {
const rejects = expect(Promise.reject(true)).rejects;
for (
let method of ["toEqual", "toBe", "toBeTruthy", "toBeFalsy"]
) {
assertEquals(typeof (rejects as any)[method], "function");
}
},
});
Deno.test({
name: "toBeDefined",
fn: async () => {
await assertAllPass(
() => expect(true).toBeDefined(),
() => expect({}).toBeDefined(),
() => expect([]).toBeDefined(),
() => expect(undefined).not.toBeDefined(),
() => expect(Promise.resolve({})).resolves.toBeDefined(),
() => expect(Promise.reject({})).rejects.toBeDefined(),
);
await assertAllFail(
() => expect(undefined).toBeDefined(),
() => expect(true).not.toBeDefined(),
);
},
});
Deno.test({
name: "toBeUndefined",
fn: async () => {
await assertAllPass(
() => expect(undefined).toBeUndefined(),
() => expect(null).not.toBeUndefined(),
() => expect(Promise.resolve(undefined)).resolves.toBeUndefined(),
() => expect(Promise.reject(undefined)).rejects.toBeUndefined(),
);
await assertAllFail(
() => expect(null).toBeUndefined(),
() => expect(undefined).not.toBeUndefined(),
() => expect(false).toBeUndefined(),
);
},
});
Deno.test({
name: "toBeTruthy",
fn: async () => {
await assertAllPass(
() => expect(true).toBeTruthy(),
() => expect(false).not.toBeTruthy(),
() => expect(Promise.resolve(true)).resolves.toBeTruthy(),
() => expect(Promise.reject(true)).rejects.toBeTruthy(),
);
await assertAllFail(
() => expect(false).toBeTruthy(),
() => expect(true).not.toBeTruthy(),
);
},
});
Deno.test({
name: "toBeFalsy",
fn: async () => {
await assertAllPass(
() => expect(false).toBeFalsy(),
() => expect(true).not.toBeFalsy(),
() => expect(Promise.resolve(false)).resolves.toBeFalsy(),
() => expect(Promise.reject(false)).rejects.toBeFalsy(),
);
await assertAllFail(
() => expect(true).toBeFalsy(),
() => expect(false).not.toBeFalsy(),
);
},
});
Deno.test({
name: "toBeGreaterThan",
fn: async () => {
await assertAllPass(
() => expect(2).toBeGreaterThan(1),
() => expect(1).not.toBeGreaterThan(2),
() => expect(Promise.resolve(2)).resolves.toBeGreaterThan(1),
() => expect(Promise.reject(2)).rejects.toBeGreaterThan(1),
);
await assertAllFail(
() => expect(1).toBeGreaterThan(1),
() => expect(1).toBeGreaterThan(2),
() => expect(2).not.toBeGreaterThan(1),
);
},
});
Deno.test({
name: "toBeLessThan",
fn: async () => {
await assertAllPass(
() => expect(1).toBeLessThan(2),
() => expect(2).not.toBeLessThan(1),
() => expect(Promise.resolve(1)).resolves.toBeLessThan(2),
() => expect(Promise.reject(1)).rejects.toBeLessThan(2),
);
await assertAllFail(
() => expect(1).toBeLessThan(1),
() => expect(2).toBeLessThan(1),
() => expect(1).not.toBeLessThan(2),
);
},
});
Deno.test({
name: "toBeGreaterThanOrEqual",
fn: async () => {
await assertAllPass(
() => expect(2).toBeGreaterThanOrEqual(1),
() => expect(1).toBeGreaterThanOrEqual(1),
() => expect(1).not.toBeGreaterThanOrEqual(2),
() => expect(Promise.resolve(2)).resolves.toBeGreaterThanOrEqual(2),
() => expect(Promise.reject(2)).rejects.toBeGreaterThanOrEqual(2),
);
await assertAllFail(
() => expect(1).toBeGreaterThanOrEqual(2),
() => expect(2).not.toBeGreaterThanOrEqual(1),
);
},
});
Deno.test({
name: "toBeLessThanOrEqual",
fn: async () => {
await assertAllPass(
() => expect(1).toBeLessThanOrEqual(2),
() => expect(1).toBeLessThanOrEqual(1),
() => expect(2).not.toBeLessThanOrEqual(1),
() => expect(Promise.resolve(1)).resolves.toBeLessThanOrEqual(2),
() => expect(Promise.reject(1)).rejects.toBeLessThanOrEqual(2),
);
await assertAllFail(
() => expect(2).toBeLessThanOrEqual(1),
() => expect(1).not.toBeLessThanOrEqual(1),
() => expect(1).not.toBeLessThanOrEqual(2),
);
},
});
Deno.test({
name: "toBeNull",
fn: async () => {
await assertAllPass(
() => expect(null).toBeNull(),
() => expect(undefined).not.toBeNull(),
() => expect(false).not.toBeNull(),
() => expect(Promise.resolve(null)).resolves.toBeNull(),
() => expect(Promise.reject(null)).rejects.toBeNull(),
);
await assertAllFail(
() => expect({}).toBeNull(),
() => expect(null).not.toBeNull(),
() => expect(undefined).toBeNull(),
);
},
});
Deno.test({
name: "toBeInstanceOf",
fn: async () => {
class A {}
class B {}
await assertAllPass(
() => expect(new A()).toBeInstanceOf(A),
() => expect(new A()).not.toBeInstanceOf(B),
);
await assertAllFail(
() => expect({}).toBeInstanceOf(A),
() => expect(null).toBeInstanceOf(A),
);
},
});
Deno.test({
name: "toBeNaN",
fn: async () => {
await assertAllPass(
() => expect(NaN).toBeNaN(),
() => expect(10).not.toBeNaN(),
() => expect(Promise.resolve(NaN)).resolves.toBeNaN(),
);
await assertAllFail(() => expect(10).toBeNaN(), () => expect(10).toBeNaN());
},
});
Deno.test({
name: "toBeMatch",
fn: async () => {
await assertAllPass(
() => expect("hello").toMatch(/^hell/),
() => expect("hello").toMatch("hello"),
() => expect("hello").toMatch("hell"),
);
await assertAllFail(() => expect("yo").toMatch(/^hell/));
},
});
Deno.test({
name: "toHaveProperty",
fn: async () => {
await assertAllPass(() => expect({ a: "10" }).toHaveProperty("a"));
await assertAllFail(() => expect({ a: 1 }).toHaveProperty("b"));
},
});
Deno.test({
name: "toHaveLength",
fn: async () => {
await assertAllPass(
() => expect([1, 2]).toHaveLength(2),
() => expect({ length: 10 }).toHaveLength(10),
);
await assertAllFail(() => expect([]).toHaveLength(10));
},
});
Deno.test({
name: "toContain",
fn: async () => {
await assertAllPass(
() => expect([1, 2, 3]).toContain(2),
() => expect([]).not.toContain(2),
);
await assertAllFail(
() => expect([1, 2, 3]).toContain(4),
() => expect([]).toContain(4),
);
},
});
Deno.test({
name: "toThrow",
fn: async () => {
await assertAllPass(
() =>
expect(() => {
throw new Error("TEST");
}).toThrow("TEST"),
() => expect(Promise.reject(new Error("TEST"))).rejects.toThrow("TEST"),
);
await assertAllFail(() => expect(() => true).toThrow());
},
});
Deno.test({
name: "toHaveBeenCalled",
fn: async () => {
await assertAllPass(
() => {
const m = mock.fn();
m(10);
m(20);
expect(m).toHaveBeenCalled();
},
() => {
const m = mock.fn();
expect(m).not.toHaveBeenCalled();
},
);
await assertAllFail(() => {
const m = mock.fn();
expect(m).toHaveBeenCalled();
});
},
});
Deno.test({
name: "toHaveBeenCalledTimes",
fn: async () => {
await assertAllPass(
() => {
const m = mock.fn();
expect(m).toHaveBeenCalledTimes(0);
},
() => {
const m = mock.fn();
m();
m();
expect(m).toHaveBeenCalledTimes(2);
},
);
await assertAllFail(
() => {
const m = mock.fn();
expect(m).toHaveBeenCalledTimes(1);
},
() => {
const m = mock.fn();
m();
m();
expect(m).toHaveBeenCalledTimes(3);
},
);
},
});
Deno.test({
name: "toHaveBeenCalledWith",
fn: async () => {
await assertAllPass(
() => {
const m = mock.fn();
m(1, 2, 3);
expect(m).toHaveBeenCalledWith(1, 2, 3);
},
() => {
const m = mock.fn();
m(1, 2, 3);
m(2, 3, 4);
expect(m).toHaveBeenCalledWith(1, 2, 3);
expect(m).toHaveBeenCalledWith(2, 3, 4);
},
);
await assertAllFail(
() => {
const m = mock.fn();
expect(m).toHaveBeenCalledWith(1);
},
() => {
const m = mock.fn();
m(2);
expect(m).toHaveBeenCalledWith(1);
},
);
},
});
Deno.test({
name: "toHaveBeenLastCalledWith",
fn: async () => {
await assertAllPass(
() => {
const m = mock.fn();
m(1, 2, 3);
expect(m).toHaveBeenLastCalledWith(1, 2, 3);
},
() => {
const m = mock.fn();
m(1, 2, 3);
m(2, 3, 4);
expect(m).not.toHaveBeenLastCalledWith(1, 2, 3);
expect(m).toHaveBeenLastCalledWith(2, 3, 4);
},
);
await assertAllFail(
() => {
const m = mock.fn();
expect(m).toHaveBeenLastCalledWith(1);
},
() => {
const m = mock.fn();
m(2);
expect(m).toHaveBeenLastCalledWith(1);
},
);
},
});
Deno.test({
name: "toHaveBeenNthCalledWith",
fn: async () => {
await assertAllPass(
() => {
const m = mock.fn();
m(1, 2, 3);
expect(m).toHaveBeenNthCalledWith(1, 1, 2, 3);
},
() => {
const m = mock.fn();
m(1, 2, 3);
m(2, 3, 4);
expect(m).not.toHaveBeenNthCalledWith(2, 1, 2, 3);
expect(m).toHaveBeenNthCalledWith(2, 2, 3, 4);
},
);
await assertAllFail(
() => {
const m = mock.fn();
expect(m).toHaveBeenNthCalledWith(1, 1, 2);
},
() => {
const m = mock.fn();
m(2);
expect(m).toHaveBeenNthCalledWith(1, 1);
},
);
},
});
Deno.test({
name: "toHaveReturnedWith",
fn: async () => {
await assertAllPass(
() => {
const m = mock.fn();
m();
expect(m).toHaveReturnedWith(undefined);
},
() => {
const m = mock.fn(() => true);
m();
expect(m).not.toHaveReturnedWith(false);
expect(m).toHaveReturnedWith(true);
},
() => {
const m = mock.fn(() => {
throw new Error("TEST");
});
try {
m();
} catch (err) {}
expect(m).not.toHaveReturnedWith(10);
},
);
await assertAllFail(
() => {
const m = mock.fn();
expect(m).toHaveReturnedWith(1);
},
() => {
const m = mock.fn();
m(2);
expect(m).toHaveReturnedWith(1);
},
);
},
});
Deno.test({
name: "toHaveReturnedTimes",
fn: async () => {
await assertAllPass(
() => {
const m = mock.fn();
m();
expect(m).toHaveReturnedTimes(1);
},
() => {
const m = mock.fn(() => true);
expect(m).toHaveReturnedTimes(0);
},
() => {
const m = mock.fn(() => {
throw new Error("TEST");
});
try {
m();
} catch (err) {}
expect(m).toHaveReturnedTimes(0);
},
);
await assertAllFail(
() => {
const m = mock.fn();
expect(m).toHaveReturnedTimes(1);
},
() => {
const m = mock.fn();
m(2);
expect(m).not.toHaveReturnedTimes(1);
},
);
},
});
Deno.test({
name: "toHaveReturned",
fn: async () => {
await assertAllPass(
() => {
const m = mock.fn();
m();
expect(m).toHaveReturned();
},
() => {
const m = mock.fn();
expect(m).not.toHaveReturned();
},
() => {
const m = mock.fn(() => {
throw new Error("TEST");
});
try {
m();
} catch (err) {}
expect(m).not.toHaveReturned();
},
);
await assertAllFail(
() => {
const m = mock.fn();
expect(m).toHaveReturned();
},
() => {
const m = mock.fn();
m();
expect(m).not.toHaveReturned();
},
() => {
const m = mock.fn(() => {
throw new Error("TEST");
});
m();
expect(m).not.toHaveReturned();
},
);
},
});
Deno.test({
name: "toHaveLastReturnedWith",
fn: async () => {
await assertAllPass(
() => {
const m = mock.fn((x: number) => x);
m(1);
m(2);
expect(m).toHaveLastReturnedWith(2);
},
() => {
const m = mock.fn((x: number) => x);
m(1);
m(2);
expect(m).toHaveLastReturnedWith(2);
},
);
await assertAllFail(
() => {
const m = mock.fn((x: number) => x);
expect(m).toHaveLastReturnedWith(1);
},
() => {
const m = mock.fn((x: number) => x);
m(2);
expect(m).toHaveLastReturnedWith(1);
},
);
},
});
Deno.test({
name: "toHaveNthReturnedWith",
fn: async () => {
await assertAllPass(
() => {
const m = mock.fn((x: number) => x);
m(1, 2, 3);
expect(m).toHaveNthReturnedWith(1, 1);
},
() => {
const m = mock.fn((x: number) => x);
m(1, 2, 3);
m(2, 3, 4);
expect(m).not.toHaveNthReturnedWith(2, 1);
expect(m).toHaveNthReturnedWith(2, 2);
},
);
await assertAllFail(
() => {
const m = mock.fn();
expect(m).toHaveNthReturnedWith(1, 1);
},
() => {
const m = mock.fn();
m(2);
expect(m).toHaveNthReturnedWith(1, 1);
},
);
},
});