UNPKG

reblend-testing-library

Version:

Simple and complete Reblendjs testing utilities that encourage good testing practices.

145 lines (144 loc) 4.34 kB
import { Reblend, useEffect, useState } from "reblendjs"; import { render, cleanup } from "../"; test("cleans up the document", async () => { const spy = jest.fn(); const divId = "my-div"; class Test extends Reblend { componentWillUnmount() { expect(document.getElementById(divId)).toBeInTheDocument(); spy(); } html() { return Reblend.construct.bind(this)("div", { id: divId }); } } await render(Reblend.construct.bind(this)(Test, null)); await cleanup(); expect(document.body).toBeEmptyDOMElement(); expect(spy).toHaveBeenCalledTimes(1); }); test("cleanup does not error when an element is not a child", async () => { await render(Reblend.construct.bind(this)("div", null), { container: document.createElement("div") }); await cleanup(); }); test("cleanup runs effect cleanup functions", async () => { const spy = jest.fn(); //@reblendComponent const Test = class /* @Reblend: Transformed from function to class */ extends Reblend { static ELEMENT_NAME = "Test"; constructor() { super(); } async initState() { useEffect.bind(this)(() => spy); } async initProps() { this.props = {}; } async html() { return; } }; await render(Reblend.construct.bind(this)(Test, null)); await cleanup(); expect(spy).toHaveBeenCalledTimes(1); }); describe("fake timers and missing act warnings", () => { beforeEach(() => { jest.resetAllMocks(); jest.spyOn(console, "error").mockImplementation(() => { // assert messages explicitly }); jest.useFakeTimers(); }); afterEach(() => { jest.restoreAllMocks(); jest.useRealTimers(); }); test("cleanup does not flush microtasks", async () => { const microTaskSpy = jest.fn(); //@reblendComponent class Test extends Reblend { static ELEMENT_NAME = "Test"; constructor() { super(); } async initState() { const [counter, setDeferredCounter] = useState.bind(this)(1, "counter"); this.state.counter = counter; this.state.setDeferredCounter = setDeferredCounter; useEffect.bind(this)(() => { let cancelled = false; Promise.resolve().then(() => { microTaskSpy(); // eslint-disable-next-line jest/no-if, jest/no-conditional-in-test -- false positive if (!cancelled) { this.state.setDeferredCounter(this.state.counter); } }); return () => { cancelled = true; }; }, (() => [this.state.counter]).bind(this)); } async initProps() { this.props = {}; } async html() { return null; } } /* @Reblend: Transformed from function to class */ await render(Reblend.construct.bind(this)(Test, null)); await cleanup(); expect(microTaskSpy).toHaveBeenCalledTimes(1); // console.error is mocked // eslint-disable-next-line no-console expect(console.error).toHaveBeenCalledTimes(0); }); test("cleanup does not flush macrotasks", async () => { const deferredStateUpdateSpy = jest.fn(); //@reblendComponent class Test extends Reblend { static ELEMENT_NAME = "Test"; constructor() { super(); } async initState() { const [counter, setDeferredCounter] = useState.bind(this)(1, "counter"); this.state.counter = counter; this.state.setDeferredCounter = setDeferredCounter; useEffect.bind(this)(() => { let cancelled = false; setTimeout(() => { deferredStateUpdateSpy(); // eslint-disable-next-line jest/no-conditional-in-test -- false-positive if (!cancelled) { this.state.setDeferredCounter(this.state.counter); } }, 0); return () => { cancelled = true; }; }, (() => [this.state.counter]).bind(this)); } async initProps() { this.props = {}; } async html() { return null; } } /* @Reblend: Transformed from function to class */ await render(Reblend.construct.bind(this)(Test, null)); jest.runAllTimers(); await cleanup(); expect(deferredStateUpdateSpy).toHaveBeenCalledTimes(1); }); });