743 lines
16 KiB
TypeScript
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);
|
|
},
|
|
);
|
|
},
|
|
});
|