UNPKG

react-solid-flow

Version:

[SolidJS](https://www.solidjs.com/docs/latest/api#control-flow)-inspired basic control-flow components and everyday async state hook library for [React](https://reactjs.org/)

119 lines (109 loc) 4.58 kB
import { describe, it, expect } from "vitest"; import { renderHook, act } from "@testing-library/react"; import { useResourceReducer } from "../useResourceReducer"; import { NullishError } from "../../models/NullishError"; describe("useResourceReducer", () => { it("returns the initial state", () => { const { result } = renderHook(() => useResourceReducer<boolean>()); const [ resource, dispatch ] = result.current; expect(resource.loading).toBe(true); expect(resource.data).toBeUndefined(); expect(resource.error).toBeUndefined(); expect(resource.latest).toBeUndefined(); expect(resource.state).toBe("pending"); expect(dispatch).toBeInstanceOf(Function); }); it("accepts static sync initializer", () => { const { result } = renderHook(() => useResourceReducer<boolean>(true)); const [ resource ] = result.current; expect(resource.loading).toBe(true); expect(resource.data).toBe(true); expect(resource.state).toBe("refreshing"); }); it("accepts defered sync initializer", () => { const { result } = renderHook(() => useResourceReducer<boolean>(() => false)); const [ resource ] = result.current; expect(resource.loading).toBe(true); expect(resource.data).toBe(false); expect(resource.state).toBe("refreshing"); }); it("allows to change state to pending", () => { const { result } = renderHook(() => useResourceReducer<boolean>()); const [ , dispatch ] = result.current; act(() => dispatch({ type: "PEND" })); const [ resource ] = result.current; expect(resource.loading).toBe(true); expect(resource.data).toBeUndefined(); expect(resource.error).toBeUndefined(); expect(resource.latest).toBeUndefined(); expect(resource.state).toBe("pending"); }); it("allows to resolve pending state", async () => { const { result } = renderHook(() => useResourceReducer<boolean>()); const [ , dispatch ] = result.current; act(() => { dispatch({ type: "PEND" }); dispatch({ type: "RESOLVE", payload: true }); }); const [ resource ] = result.current; expect(resource.loading).toBe(false); expect(resource.data).toBe(true); expect(resource.error).toBeUndefined(); expect(resource.latest).toBe(true); expect(resource.state).toBe("ready"); }); it("'ready' -> 'refreshing' by the next 'PEND' call", () => { const { result } = renderHook(() => useResourceReducer<boolean>()); const [ , dispatch ] = result.current; act(() => { dispatch({ type: "PEND" }); dispatch({ type: "RESOLVE", payload: true }); dispatch({ type: "PEND" }); }); const [ resource ] = result.current; expect(resource.loading).toBe(true); expect(resource.data).toBe(true); expect(resource.error).toBeUndefined(); expect(resource.latest).toBe(true); expect(resource.state).toBe("refreshing"); }); it("allows to reject pending state", async () => { const { result } = renderHook(() => useResourceReducer<boolean>()); const [ , dispatch ] = result.current; act(() => { dispatch({ type: "PEND" }); dispatch({ type: "REJECT", payload: true }); }); const [ resource ] = result.current; expect(resource.loading).toBe(false); expect(resource.data).toBeUndefined(); expect(resource.error).toBe(true); expect(resource.latest).toBeUndefined(); expect(resource.state).toBe("errored"); }); it("puts a special error type into Error on nullish rejects", async () => { const { result } = renderHook(() => useResourceReducer<boolean>()); const [ , dispatch ] = result.current; act(() => { dispatch({ type: "REJECT", payload: null }); }); const [ resource ] = result.current; const { error } = resource; expect(error).toBeInstanceOf(NullishError); // As error object doesn't have a cause field in node <= 14, don't test for that if (process.version.slice(1).split(".")[0] > "14") { expect(error instanceof NullishError && error.cause).toBeNull(); } }); it("does nothing on wrong dispatch types", async () => { const { result } = renderHook(() => useResourceReducer<boolean>()); const [ , dispatch ] = result.current; const [ initial ] = result.current; act(() => { //@ts-expect-error fake dispatch dispatch({ type: "FAKE", payload: true }); }); const [ resource ] = result.current; expect(resource).toBe(initial); }); });