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/)

171 lines (156 loc) 4.75 kB
import { describe, expect, it, vi } from "vitest"; import { Resource } from "../Resource"; describe("useResource", () => { describe("Resource.constructor", () => { it("creates an empty resource", () => { const res = new Resource(); expect(res).toEqual({ state: "unresolved", data: undefined, loading: false, error: undefined, latest: undefined, }); }); it("correctly sets core data", () => { const res = new Resource({ data: "test1", loading: true, error: "test2", }); expect(res.data).toBe("test1"); expect(res.loading).toBe(true); expect(res.error).toBe("test2"); }); it("keeps latest data from previous resource", () => { let res = new Resource({ data: "test1", loading: false, error: undefined, }); res = new Resource({ data: undefined, loading: true, }, res); res = new Resource({ ...res, data: undefined, loading: false, error: "test2", }, res); expect(res.latest).toBe("test1"); }); it("updates resource state name with getState function", () => { const speGetState = vi.spyOn(Resource, "getState"); let res = new Resource<string>({ data: undefined, loading: true, error: undefined, }); expect(res.state).toBe("pending"); expect(speGetState).toBeCalledTimes(1); res = new Resource({ data: "test", loading: false, error: undefined, }, res); expect(res.state).toBe("ready"); expect(speGetState).toBeCalledTimes(2); }); }); describe("Resource.from", () => { it("creates a resource from sync data", () => { const res = Resource.from("test"); expect(res).toEqual({ data: "test", loading: false, error: undefined, latest: "test", state: "ready", }); expect(res).toBeInstanceOf(Resource); }); it("creates a resource with async data", () => { const res = Resource.from(Promise.resolve()); expect(res).toEqual({ data: undefined, loading: true, error: undefined, latest: undefined, state: "pending", }); expect(res).toBeInstanceOf(Resource); }); }); /* * | state | data | loading | error | * |:-----------|:-----:|:-------:|:-----:| * | unresolved | No | No | No | * | pending | No | Yes | No* | * | ready | Yes | No | No | * | refreshing | Yes | Yes | No* | * | errored | No* | No | Yes | */ describe("Resource.getState", () => { // we're using falsy values where possible, to check that they're told apart // from undefined correctly it("determines unresolved state", () => { expect(Resource.getState({ data: undefined, loading: false, error: undefined, })).toBe("unresolved"); }); it("determines pending state", () => { expect(Resource.getState({ data: undefined, loading: true, error: undefined, })).toBe("pending"); }); it("incorrectly reset error + loading still results in pending state", () => { // Though this example is impossible in this code, we still have this test // in case it was called on some 3d party implementation of Resource-like object. expect(Resource.getState({ data: undefined, loading: true, error: false, })).toBe("pending"); }); it("determines ready state", () => { expect(Resource.getState({ data: false, loading: false, error: undefined, })).toBe("ready"); }); it("determines refreshing state", () => { expect(Resource.getState({ data: false, loading: true, error: undefined, })).toBe("refreshing"); }); it("determines refreshing state with incorrectly set error", () => { expect(Resource.getState({ data: false, loading: true, error: false, })).toBe("refreshing"); }); it("determines errored state", () => { expect(Resource.getState({ data: null, loading: false, error: false, })).toBe("errored"); }); it("data + error results in errored state", () => { expect(Resource.getState({ data: true, loading: false, error: false, })).toBe("errored"); }); }); });