UNPKG

zigbee-herdsman

Version:

An open source ZigBee gateway solution with node.js.

228 lines (194 loc) 7.59 kB
import {Queue, Utils, Waitress, wait} from "../src/utils"; import {logger, setLogger} from "../src/utils/logger"; const mockLogger = { debug: vi.fn(), info: vi.fn(), warning: vi.fn(), error: vi.fn(), }; describe("Utils", () => { it("Is Number Array", () => { expect(Utils.isNumberArray([1, 2, 3])).toBeTruthy(); expect(Utils.isNumberArray([1, 2, "3"])).toBeFalsy(); expect(Utils.isNumberArray("nonarray")).toBeFalsy(); }); it("Is Number Array of length", () => { expect(Utils.isNumberArrayOfLength([1, 2, 3], 3)).toBeTruthy(); expect(Utils.isNumberArrayOfLength([1, 2], 3)).toBeFalsy(); expect(Utils.isNumberArrayOfLength([1, 2, "3"], 3)).toBeFalsy(); expect(Utils.isNumberArrayOfLength("nonarray", 3)).toBeFalsy(); }); it("Is object empty", () => { expect(Utils.isObjectEmpty({})).toBeTruthy(); expect(Utils.isObjectEmpty({a: 1})).toBeFalsy(); }); it("Assert string", () => { expect(Utils.assertString("bla")).toBeUndefined(); expect(() => { Utils.assertString(1); }).toThrow("Input must be a string!"); }); it("Test wait", async () => { const setTimeoutSpy = vi.spyOn(globalThis, "setTimeout").mockImplementationOnce( // @ts-expect-error mocked () => {}, ); wait(1000).then(() => {}); expect(setTimeout).toHaveBeenCalledTimes(1); expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 1000); setTimeoutSpy.mockRestore(); }); it("Test waitress", async () => { vi.useFakeTimers(); const validator = (payload: string, matcher: number): boolean => { if (payload === "one" && matcher === 1) return true; if (payload === "two" && matcher === 2) return true; return false; }; const waitress = new Waitress<string, number>(validator, (_, timeout) => `Timedout '${timeout}'`); const wait1 = waitress.waitFor(1, 10000).start(); waitress.resolve("one"); expect(await wait1.promise).toBe("one"); const wait2_1 = waitress.waitFor(2, 10000).start(); const wait2_2 = waitress.waitFor(2, 10000).start(); const wait2_3 = waitress.waitFor(2, 10000).start(); const wait2_4 = waitress.waitFor(2, 5000).start(); const wait2_5 = waitress.waitFor(2, 5000).start(); waitress.remove(wait2_3.ID); vi.advanceTimersByTime(6000); waitress.remove(wait2_5.ID); waitress.resolve("two"); expect(await wait2_1.promise).toBe("two"); expect(await wait2_2.promise).toBe("two"); let error2; try { await wait2_4.promise; } catch (e) { error2 = e; } expect(error2).toStrictEqual(new Error("Timedout '5000'")); let error3; try { await wait2_5.promise; } catch (e) { error3 = e; } expect(error3).toStrictEqual(new Error("Timedout '5000'")); vi.useRealTimers(); // reject test const wait1b = waitress.waitFor(1, 5000).start(); let error1_; wait(1000).then(() => { waitress.reject("one", "drop"); }); try { await wait1b.promise; } catch (e) { error1_ = e; } expect(error1_).toStrictEqual(new Error("drop")); vi.useFakeTimers(); const wait2 = waitress.waitFor(2, 5000).start(); const handled1 = waitress.reject("tree", "drop"); expect(handled1).toBe(false); let error2_; vi.advanceTimersByTime(6000); try { await wait2.promise; } catch (e) { error2_ = e; } expect(error2_).toStrictEqual(new Error("Timedout '5000'")); const handled2 = waitress.reject("two", "drop"); expect(handled2).toBe(false); waitress.waitFor(2, 10000).start().promise; waitress.waitFor(2, 10000).start().promise; await vi.advanceTimersByTimeAsync(2000); waitress.clear(); await vi.advanceTimersByTimeAsync(12000); // @ts-expect-error private expect(waitress.waiters.size).toStrictEqual(0); vi.useRealTimers(); }); it("Test queue", async () => { const queue = new Queue(4); const finished = []; let job1Promise; let job2Promise; const job1 = new Promise((resolve) => { job1Promise = resolve; }); const job2 = new Promise((resolve) => { job2Promise = resolve; }); const job5 = new Promise((_resolve) => {}); const job6 = new Promise((_resolve) => {}); const job7 = new Promise((_resolve) => {}); const job1Result = queue.execute<string>(async () => { await job1; finished.push(1); return "finished"; }); const job2Result = queue.execute<void>(async () => { await job2; finished.push(2); }, "mykey"); queue.execute<void>(async () => { finished.push(3); await Promise.resolve(); }, "mykey"); queue.execute<void>(async () => { finished.push(4); await Promise.resolve(); }, "mykey2"); queue.execute<void>(async () => { await job5; finished.push(5); }); queue.execute<void>(async () => { await job6; finished.push(6); }); queue.execute<void>(async () => { await job7; finished.push(7); }); queue.execute<void>(async () => { finished.push(8); await Promise.resolve(); }); expect(finished).toEqual([4]); job1Promise(); expect(await job1Result).toBe("finished"); await job1Result; expect(finished).toEqual([4, 1]); job2Promise(); await job2Result; expect(finished).toEqual([4, 1, 2, 3]); expect(queue.count()).toBe(5); }); it("Logs", () => { const debugSpy = vi.spyOn(console, "debug"); const infoSpy = vi.spyOn(console, "info"); const warningSpy = vi.spyOn(console, "warn"); const errorSpy = vi.spyOn(console, "error"); logger.debug("debug", "zh"); expect(debugSpy).toHaveBeenCalledWith(expect.stringMatching(/^\[\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\d\d\dZ\] zh: debug$/)); logger.info("info", "zh"); expect(infoSpy).toHaveBeenCalledWith(expect.stringMatching(/^\[\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\d\d\dZ\] zh: info$/)); logger.warning("warning", "zh"); expect(warningSpy).toHaveBeenCalledWith(expect.stringMatching(/^\[\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\d\d\dZ\] zh: warning$/)); logger.error("error", "zh"); expect(errorSpy).toHaveBeenCalledWith(expect.stringMatching(/^\[\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\d\d\dZ\] zh: error$/)); setLogger(mockLogger); expect(logger).toEqual(mockLogger); logger.debug("debug", "zh"); expect(mockLogger.debug).toHaveBeenCalledWith("debug", "zh"); logger.info("info", "zh"); expect(mockLogger.info).toHaveBeenCalledWith("info", "zh"); logger.warning("warning", "zh"); expect(mockLogger.warning).toHaveBeenCalledWith("warning", "zh"); logger.error("error", "zh"); expect(mockLogger.error).toHaveBeenCalledWith("error", "zh"); }); });