deno.land / x / solid@v1.5.6 / web / test / suspense.spec.tsx
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426/** * @jsxImportSource solid-js * @jest-environment jsdom */
import "../../test/MessageChannel";import { lazy, createSignal, createResource, useTransition, enableScheduling } from "../../src";import { render, Suspense, SuspenseList } from "../src";import { createStore } from "../../store/src";
enableScheduling();
beforeEach(() => { jest.useFakeTimers();});afterEach(() => { jest.useRealTimers();});describe("Testing Basics", () => { test("Children are reactive", () => { let div = document.createElement("div"); let increment: () => void; render(() => { const [count, setCount] = createSignal(0); increment = () => setCount(count() + 1); return <Suspense>{count()}</Suspense>; }, div); expect(div.innerHTML).toBe("0"); increment!(); expect(div.innerHTML).toBe("1"); });});describe("Testing Suspense", () => { let div = document.createElement("div"), disposer: () => void, resolvers: Function[] = [], [triggered, trigger] = createSignal<string>(); const LazyComponent = lazy<typeof ChildComponent>(() => new Promise(r => resolvers.push(r))), ChildComponent = (props: { greeting: string }) => { const [value] = createResource<string, string>( triggered, () => new Promise(r => setTimeout(() => r("Jo"), 300)), { initialValue: "" } ); return () => `${props.greeting} ${value()}`; }, Component = () => ( <Suspense fallback="Loading"> <LazyComponent greeting="Hi," />. <LazyComponent greeting="Hello" /> </Suspense> );
test("Create Suspense control flow", () => { disposer = render(Component, div); expect(div.innerHTML).toBe("Loading"); });
test("Toggle Suspense control flow", async () => { for (const r of resolvers) r({ default: ChildComponent });
await Promise.resolve(); jest.runAllTimers(); await Promise.resolve();
expect(div.innerHTML).toBe("Hi, .Hello "); });
test("Toggle with refresh transition", async () => { const [pending, start] = useTransition(); let finished = false;
start(() => trigger("Jo")).then(() => (finished = true)); expect(div.innerHTML).toBe("Hi, .Hello "); expect(finished).toBe(false); // wait trigger resource refetch await Promise.resolve();
expect(div.innerHTML).toBe("Hi, .Hello "); expect(pending()).toBe(true); expect(finished).toBe(false);
// Exhausts create-resource setTimeout jest.runAllTimers(); // wait update suspence state await Promise.resolve(); // wait update computation jest.runAllTimers(); // wait write signal suc await Promise.resolve();
jest.runAllTimers(); await Promise.resolve();
expect(div.innerHTML).toBe("Hi, Jo.Hello Jo"); expect(pending()).toBe(false); expect(finished).toBe(true); });
test("Toggle with store and refresh transition", async () => { const [store, setStore] = createStore({ count: 0 }); const [pending, start] = useTransition(); let finished = false;
start(() => { setStore({ count: 1 }); trigger("Jack"); }).then(() => (finished = true));
expect(store.count).toBe(0); expect(finished).toBe(false); // wait trigger resource refetch await Promise.resolve();
expect(store.count).toBe(0); expect(pending()).toBe(true); expect(finished).toBe(false);
// Exhausts create-resource setTimeout jest.runAllTimers(); // wait update suspence state await Promise.resolve(); // wait update computation jest.runAllTimers();
// Await the rest of the things, TODO: figure out what these are await Promise.resolve(); jest.runAllTimers(); await Promise.resolve();
expect(pending()).toBe(false); expect(finished).toBe(true); expect(store.count).toBe(1); });
test("dispose", () => { div.innerHTML = ""; disposer(); });});
describe("SuspenseList", () => { const promiseFactory = (time: number) => { return (v: string) => new Promise<string>(r => { setTimeout(() => { r(v); }, time); }); }, A = () => { const [value] = createResource("A", promiseFactory(200)); return <div>{value()}</div>; }, B = () => { const [value] = createResource("B", promiseFactory(100)); return <div>{value()}</div>; }, C = () => { const [value] = createResource("C", promiseFactory(300)); return <div>{value()}</div>; };
test("revealOrder together", async () => { const div = document.createElement("div"), Comp = () => ( <SuspenseList revealOrder="together"> <Suspense fallback={<div>Loading 1</div>}> <A /> </Suspense> <Suspense fallback={<div>Loading 2</div>}> <B /> </Suspense> <Suspense fallback={<div>Loading 3</div>}> <C /> </Suspense> </SuspenseList> ); const dispose = render(Comp, div); expect(div.innerHTML).toBe("<div>Loading 1</div><div>Loading 2</div><div>Loading 3</div>"); jest.advanceTimersByTime(110); await Promise.resolve(); expect(div.innerHTML).toBe("<div>Loading 1</div><div>Loading 2</div><div>Loading 3</div>"); jest.advanceTimersByTime(100); await Promise.resolve(); expect(div.innerHTML).toBe("<div>Loading 1</div><div>Loading 2</div><div>Loading 3</div>"); jest.advanceTimersByTime(100); // wait effect update await Promise.resolve(); expect(div.innerHTML).toBe("<div>A</div><div>B</div><div>C</div>"); dispose(); });
test("revealOrder forwards", async () => { const div = document.createElement("div"), Comp = () => ( <SuspenseList revealOrder="forwards"> <Suspense fallback={<div>Loading 1</div>}> <A /> </Suspense> <Suspense fallback={<div>Loading 2</div>}> <B /> </Suspense> <Suspense fallback={<div>Loading 3</div>}> <C /> </Suspense> </SuspenseList> ); const dispose = render(Comp, div); expect(div.innerHTML).toBe("<div>Loading 1</div><div>Loading 2</div><div>Loading 3</div>");
jest.advanceTimersByTime(110); await Promise.resolve(); expect(div.innerHTML).toBe("<div>Loading 1</div><div>Loading 2</div><div>Loading 3</div>");
jest.advanceTimersByTime(100); await Promise.resolve(); expect(div.innerHTML).toBe("<div>A</div><div>B</div><div>Loading 3</div>");
jest.advanceTimersByTime(100); await Promise.resolve(); expect(div.innerHTML).toBe("<div>A</div><div>B</div><div>C</div>"); dispose(); });
test("revealOrder forwards hidden", async () => { const div = document.createElement("div"), Comp = () => ( <SuspenseList revealOrder="forwards" tail="hidden"> <Suspense fallback={<div>Loading 1</div>}> <A /> </Suspense> <Suspense fallback={<div>Loading 2</div>}> <B /> </Suspense> <Suspense fallback={<div>Loading 3</div>}> <C /> </Suspense> </SuspenseList> ); const dispose = render(Comp, div); expect(div.innerHTML).toBe("");
jest.advanceTimersByTime(110); await Promise.resolve(); expect(div.innerHTML).toBe("");
jest.advanceTimersByTime(100); await Promise.resolve(); expect(div.innerHTML).toBe("<div>A</div><div>B</div>");
jest.advanceTimersByTime(100); await Promise.resolve(); expect(div.innerHTML).toBe("<div>A</div><div>B</div><div>C</div>"); dispose(); });
test("revealOrder forwards", async () => { const div = document.createElement("div"), Comp = () => ( <SuspenseList revealOrder="forwards"> <Suspense fallback={<div>Loading 1</div>}> <A /> </Suspense> <Suspense fallback={<div>Loading 2</div>}> <B /> </Suspense> <Suspense fallback={<div>Loading 3</div>}> <C /> </Suspense> </SuspenseList> ); const dispose = render(Comp, div); expect(div.innerHTML).toBe("<div>Loading 1</div><div>Loading 2</div><div>Loading 3</div>");
jest.advanceTimersByTime(110); await Promise.resolve(); expect(div.innerHTML).toBe("<div>Loading 1</div><div>Loading 2</div><div>Loading 3</div>");
jest.advanceTimersByTime(100); await Promise.resolve(); expect(div.innerHTML).toBe("<div>A</div><div>B</div><div>Loading 3</div>");
jest.advanceTimersByTime(100); await Promise.resolve(); expect(div.innerHTML).toBe("<div>A</div><div>B</div><div>C</div>"); dispose(); });
test("revealOrder forwards collapse", async () => { const div = document.createElement("div"), Comp = () => ( <SuspenseList revealOrder="forwards" tail="collapsed"> <Suspense fallback={<div>Loading 1</div>}> <A /> </Suspense> <Suspense fallback={<div>Loading 2</div>}> <B /> </Suspense> <Suspense fallback={<div>Loading 3</div>}> <C /> </Suspense> </SuspenseList> ); const dispose = render(Comp, div); expect(div.innerHTML).toBe("<div>Loading 1</div>");
jest.advanceTimersByTime(110); await Promise.resolve(); expect(div.innerHTML).toBe("<div>Loading 1</div>");
jest.advanceTimersByTime(100); await Promise.resolve(); expect(div.innerHTML).toBe("<div>A</div><div>B</div><div>Loading 3</div>");
jest.advanceTimersByTime(100); await Promise.resolve(); expect(div.innerHTML).toBe("<div>A</div><div>B</div><div>C</div>"); dispose(); });
test("revealOrder backwards collapse", async () => { const div = document.createElement("div"), Comp = () => ( <SuspenseList revealOrder="backwards" tail="collapsed"> <Suspense fallback={<div>Loading 1</div>}> <A /> </Suspense> <Suspense fallback={<div>Loading 2</div>}> <B /> </Suspense> <Suspense fallback={<div>Loading 3</div>}> <C /> </Suspense> </SuspenseList> ); const dispose = render(Comp, div); expect(div.innerHTML).toBe("<div>Loading 3</div>");
jest.advanceTimersByTime(110); await Promise.resolve(); expect(div.innerHTML).toBe("<div>Loading 3</div>");
jest.advanceTimersByTime(100); await Promise.resolve(); expect(div.innerHTML).toBe("<div>Loading 3</div>");
jest.advanceTimersByTime(100); await Promise.resolve(); expect(div.innerHTML).toBe("<div>A</div><div>B</div><div>C</div>"); dispose(); });
test("nested SuspenseList together", async () => { const div = document.createElement("div"), Comp = () => ( <SuspenseList revealOrder="together"> <SuspenseList revealOrder="together"> <Suspense fallback={<div>Loading 1</div>}> <A /> </Suspense> </SuspenseList> <SuspenseList revealOrder="together"> <Suspense fallback={<div>Loading 2</div>}> <B /> </Suspense> <Suspense fallback={<div>Loading 3</div>}> <C /> </Suspense> </SuspenseList> </SuspenseList> ); const dispose = render(Comp, div); expect(div.innerHTML).toBe("<div>Loading 1</div><div>Loading 2</div><div>Loading 3</div>");
jest.advanceTimersByTime(110); await Promise.resolve(); expect(div.innerHTML).toBe("<div>Loading 1</div><div>Loading 2</div><div>Loading 3</div>");
jest.advanceTimersByTime(100); await Promise.resolve(); expect(div.innerHTML).toBe("<div>Loading 1</div><div>Loading 2</div><div>Loading 3</div>");
jest.advanceTimersByTime(100); await Promise.resolve(); expect(div.innerHTML).toBe("<div>A</div><div>B</div><div>C</div>"); dispose(); });
test("nested SuspenseList forwards", async () => { const div = document.createElement("div"), Comp = () => ( <SuspenseList revealOrder="forwards"> <SuspenseList revealOrder="forwards"> <Suspense fallback={<div>Loading 1</div>}> <A /> </Suspense> </SuspenseList> <SuspenseList revealOrder="forwards"> <Suspense fallback={<div>Loading 2</div>}> <B /> </Suspense> <Suspense fallback={<div>Loading 3</div>}> <C /> </Suspense> </SuspenseList> </SuspenseList> ); const dispose = render(Comp, div); expect(div.innerHTML).toBe("<div>Loading 1</div><div>Loading 2</div><div>Loading 3</div>");
jest.advanceTimersByTime(110); await Promise.resolve(); expect(div.innerHTML).toBe("<div>Loading 1</div><div>Loading 2</div><div>Loading 3</div>");
jest.advanceTimersByTime(100); await Promise.resolve(); expect(div.innerHTML).toBe("<div>A</div><div>B</div><div>Loading 3</div>");
jest.advanceTimersByTime(100); await Promise.resolve(); expect(div.innerHTML).toBe("<div>A</div><div>B</div><div>C</div>"); dispose(); });});
Version Info