import { describe, it } from "./blocks.ts"; import { expect } from "./assertions.ts"; import { mock, mockfn, patch } from "./mock.ts"; class Obj { called = 0; func(x: number) { this.called += 1; return x * 2; } } function checkRestored(o: Obj) { const called = o.called; const result = o.func(4); expect(o.called).toEqual(called + 1); expect(result).toEqual(8); } describe("patch", () => { it("calls through by default", () => { const o = new Obj(); patch(o, "func", (mock) => { const result = o.func(3); expect(o.called).toEqual(1); expect(result).toEqual(6); expect(mock).toHaveBeenCalledTimes(1); expect(mock).toHaveBeenCalledWith(3); }); patch(o, "func", (mock) => { const result = o.func(1); expect(o.called).toEqual(2); expect(result).toEqual(2); expect(mock).toHaveBeenCalledTimes(1); expect(mock).toHaveBeenCalledWith(1); }); checkRestored(o); }); it("calls sequential stubs before passing through", () => { const o = new Obj(); patch(o, "func", (mock) => { mock.stub((a) => a * 3); mock.stub((a) => a * 4); let result = o.func(2); expect(result).toEqual(6); result = o.func(2); expect(result).toEqual(8); expect(o.called).toEqual(0); result = o.func(2); expect(result).toEqual(4); expect(o.called).toEqual(1); expect(mock).toHaveBeenCalledTimes(3); }); checkRestored(o); }); it("calls stubs in loop", () => { const o = new Obj(); patch(o, "func", (mock) => { mock.stub((a) => a * 3, true); let result = o.func(2); expect(result).toEqual(6); result = o.func(2); expect(result).toEqual(6); result = o.func(2); expect(result).toEqual(6); expect(o.called).toEqual(0); expect(mock).toHaveBeenCalledTimes(3); }); checkRestored(o); }); it("can reset the mock", () => { const o = new Obj(); patch(o, "func", (mock) => { mock.stub((a) => a + 1, true); let result = o.func(3); expect(o.called).toEqual(0); expect(result).toEqual(4); expect(mock).toHaveBeenCalledTimes(1); expect(mock).toHaveBeenCalledWith(3); result = o.func(2); expect(o.called).toEqual(0); expect(result).toEqual(3); expect(mock).toHaveBeenCalledTimes(2); expect(mock).toHaveBeenCalledWith(2); mock.reset(); mock.stub((a) => a + 10, true); result = o.func(4); expect(o.called).toEqual(0); expect(result).toEqual(14); expect(mock).toHaveBeenCalledTimes(1); expect(mock).toHaveBeenCalledWith(4); mock.reset(); result = o.func(4); expect(o.called).toEqual(1); expect(result).toEqual(8); expect(mock).toHaveBeenCalledTimes(1); expect(mock).toHaveBeenCalledWith(4); }); checkRestored(o); }); }); describe("mock", () => { it("puts a no-op stub by default", () => { const o = new Obj(); mock(o, "func", undefined, (mock) => { let result = o.func(2); expect(result).toBeUndefined(); expect(o.called).toEqual(0); expect(mock).toHaveBeenCalledTimes(1); }); checkRestored(o); const f = mock(o, "func", undefined, () => o.func(2)); expect(f).toHaveBeenCalledTimes(1); checkRestored(o); }); it("stubs with a fixed value", () => { const o = new Obj(); mock(o, "func", 17, (mock) => { let result = o.func(2); expect(result).toBe(17); result = o.func(2); expect(result).toBe(17); expect(o.called).toEqual(0); expect(mock).toHaveBeenCalledTimes(2); }); checkRestored(o); }); it("stubs with a function result", () => { const o = new Obj(); let i = 9; mock(o, "func", () => ++i, (mock) => { let result = o.func(2); expect(result).toBe(10); result = o.func(2); expect(result).toBe(11); expect(o.called).toEqual(0); expect(mock).toHaveBeenCalledTimes(2); }); checkRestored(o); }); }); describe("mockfn", () => { it("constructs a simple mock function", () => { let mock = mockfn(); expect(mock).toHaveBeenCalledTimes(0); mock(); expect(mock).toHaveBeenCalledTimes(1); mock = mockfn(() => 2); expect(mock).toHaveBeenCalledTimes(0); let result = mock(); expect(result).toEqual(2); expect(mock).toHaveBeenCalledTimes(1); result = mock(); expect(result).toEqual(2); expect(mock).toHaveBeenCalledTimes(2); mock = mockfn((x: number) => x + 1); result = mock(5); expect(result).toEqual(6); expect(mock).toHaveBeenCalledTimes(1); expect(mock).toHaveBeenCalledWith(5); }); });