import { useRef } from "react";
import { useDidMount, useDidUpdate } from "@better-hooks/lifecycle";
import { render } from "@testing-library/react";
import { createHttpMockingServer, sleep } from "@hyper-fetch/testing";
import { useFetch } from "hooks/use-fetch";
import { client, createRequest, waitForRender } from "../../utils";
const { resetMocks, startServer, stopServer, mockRequest } = createHttpMockingServer();
// TODO fix error logs
const useWillMount = (fn: () => void) => {
const mounted = useRef(false);
if (!mounted.current) {
mounted.current = true;
fn();
}
};
describe("useFetch [ Rerender ]", () => {
let rerenders = 0;
let request = createRequest();
const fetchTime = 20;
const waitForDoubleFetch = async () => {
await waitForRender();
await sleep(fetchTime);
await waitForRender(fetchTime);
await sleep(fetchTime);
await waitForRender(fetchTime);
};
beforeAll(() => {
startServer();
});
afterEach(() => {
resetMocks();
});
afterAll(() => {
stopServer();
});
beforeEach(() => {
vi.resetModules();
rerenders = 0;
request = createRequest();
client.clear();
mockRequest(request, { delay: fetchTime });
});
// FIXES https://github.com/BetterTyped/hyper-fetch/issues/94
it("should start in loading state", async () => {
let isLoading = false;
function Page() {
const { loading } = useFetch(request);
useWillMount(() => {
isLoading = loading;
});
rerenders += 1;
return
{loading ? "loading" : "error"}
;
}
render();
await waitForDoubleFetch();
await sleep(200);
expect(isLoading).toBe(true);
expect(rerenders).toBe(2);
});
it("should not rerender when the same data is received from backend", async () => {
const Page = () => {
const { data } = useFetch(request, { refresh: false, refreshTime: 0 });
rerenders += 1;
return {JSON.stringify(data)}
;
};
render();
await waitForDoubleFetch();
expect(rerenders).toBe(2);
});
it("should not rerender when changed key is not used", async () => {
const Page = () => {
const { setError, setResponseTimestamp } = useFetch(request);
rerenders += 1;
useDidMount(() => {
setResponseTimestamp(new Date());
setTimeout(() => {
setError(new Error("test"));
}, fetchTime / 2);
});
return test
;
};
render();
await waitForDoubleFetch();
expect(rerenders).toBe(1);
});
it("should rerender when dependency tracking is off", async () => {
const Page = () => {
const { data } = useFetch(request, { dependencyTracking: false });
rerenders += 1;
return {JSON.stringify(data)}
;
};
render();
await waitForDoubleFetch();
expect(rerenders).toBe(2);
});
it("should rerender while using the changed key", async () => {
const Page = () => {
const { data, setData } = useFetch(request);
rerenders += 1;
useDidUpdate(() => {
if (data) {
setData(null);
}
}, [data]);
return {JSON.stringify(data)}
;
};
render();
await waitForDoubleFetch();
expect(rerenders).toBe(3);
});
});