/** * @jest-environment jsdom */ import { render, act } from "@testing-library/react" import { useAsyncTask, FINISHED, RUNNING, ERROR } from "../src/index" const TASK_1_RESULT = "TASK_1_RESULT" const TASK_1 = () => delay(10).then(() => TASK_1_RESULT) const TASK_2_RESULT = "TASK_2_RESULT" const TASK_2 = () => delay(10).then(() => TASK_2_RESULT) const results = [] const TestComponent = ({ task }) => { const taskState = useAsyncTask(task) results.push(taskState) return <> } describe("useAsyncTask", () => { beforeEach(() => { results.length = 0 }) test("shows the children when the checkbox is checked", async () => { render() await act(() => delay(20)) expect(results.length).toBe(2) expect(results[0]).toEqual({ status: RUNNING }) expect(results[1]).toEqual({ status: FINISHED, result: TASK_1_RESULT }) }) test("should finish task", async () => { render() await act(() => delay(20)) expect(results.length).toBe(2) expect(results[0]).toEqual({ status: RUNNING }) expect(results[1]).toEqual({ status: FINISHED, result: TASK_1_RESULT }) }) test("should cancel task", async () => { const { unmount } = render() unmount() await act(() => delay(20)) expect(results.length).toBe(1) expect(results[0]).toEqual({ status: RUNNING }) }) test("should not re-run task on rerender", async () => { const { rerender } = render() await act(() => delay(20)) rerender() await act(() => delay(20)) expect(results.length).toBe(3) expect(results[0]).toEqual({ status: RUNNING }) expect(results[1]).toEqual({ status: FINISHED, result: TASK_1_RESULT }) expect(results[2]).toEqual({ status: FINISHED, result: TASK_1_RESULT }) }) test("should run another task after first task", async () => { const { rerender } = render() await act(() => delay(20)) rerender() await act(() => delay(20)) expect(results.length).toBe(4) expect(results[0]).toEqual({ status: RUNNING }) expect(results[1]).toEqual({ status: FINISHED, result: TASK_1_RESULT }) expect(results[2]).toEqual({ status: RUNNING }) expect(results[3]).toEqual({ status: FINISHED, result: TASK_2_RESULT }) }) test("should run another task after first task cancelled", async () => { const { rerender } = render() rerender() await act(() => delay(20)) expect(results.length).toBe(3) expect(results[0]).toEqual({ status: RUNNING }) expect(results[1]).toEqual({ status: RUNNING }) expect(results[2]).toEqual({ status: FINISHED, result: TASK_2_RESULT }) }) test("should return error on error", async () => { render( delay(10).then(() => { throw new Error("This is an error") }) } /> ) await act(() => delay(20)) expect(results.length).toBe(2) expect(results[0]).toEqual({ status: RUNNING }) expect(results[1]).toEqual({ status: ERROR, error: new Error("This is an error") }) }) }) function delay(time) { return new Promise((resolve) => setTimeout(() => resolve(), time)) }