diff --git a/ui/src/Hooks/useFetchGet.js b/ui/src/Hooks/useFetchGet.js
index f39f98119..71cd8856c 100644
--- a/ui/src/Hooks/useFetchGet.js
+++ b/ui/src/Hooks/useFetchGet.js
@@ -45,27 +45,27 @@ const useFetchGet = (uri, { autorun = true, deps = [] } = {}) => {
FetchRetryConfig
);
- let body;
- const contentType = res.headers.get("content-type");
- if (contentType && contentType.indexOf("application/json") !== -1) {
- body = await res.json();
- } else {
- body = await res.text();
- }
-
- if (res.ok) {
- setResponse(body);
- } else {
- setError(body);
- }
- setIsLoading(false);
- setIsRetrying(false);
- } catch (error) {
if (!isCanceled.current) {
- setError(error.message);
+ let body;
+ const contentType = res.headers.get("content-type");
+ if (contentType && contentType.indexOf("application/json") !== -1) {
+ body = await res.json();
+ } else {
+ body = await res.text();
+ }
+
+ if (res.ok) {
+ setResponse(body);
+ } else {
+ setError(body);
+ }
setIsLoading(false);
setIsRetrying(false);
}
+ } catch (error) {
+ setError(error.message);
+ setIsLoading(false);
+ setIsRetrying(false);
}
}, [uri]);
diff --git a/ui/src/Hooks/useFetchGet.test.js b/ui/src/Hooks/useFetchGet.test.js
index 195285f02..8fc8f749f 100644
--- a/ui/src/Hooks/useFetchGet.test.js
+++ b/ui/src/Hooks/useFetchGet.test.js
@@ -204,6 +204,32 @@ describe("useFetchGet", () => {
expect(result.current.isRetrying).toBe(false);
});
+ it("error is updated on uparsable JSON", async () => {
+ fetchMock.mock("http://localhost/json/invalid", {
+ headers: { "Content-Type": "application/json" },
+ body: "this is not a valid JSON body",
+ });
+
+ const { result, waitForNextUpdate } = renderHook(() =>
+ useFetchGet("http://localhost/json/invalid")
+ );
+
+ expect(result.current.response).toBe(null);
+ expect(result.current.error).toBe(null);
+ expect(result.current.isLoading).toBe(true);
+ expect(result.current.isRetrying).toBe(false);
+
+ jest.runOnlyPendingTimers();
+ await waitForNextUpdate();
+
+ expect(result.current.response).toBe(null);
+ expect(result.current.error).toBe(
+ "invalid json response body at http://localhost/json/invalid reason: Unexpected token h in JSON at position 1"
+ );
+ expect(result.current.isLoading).toBe(false);
+ expect(result.current.isRetrying).toBe(false);
+ });
+
it("doesn't update response on 200 response after cleanup", async () => {
fetchMock.mock("http://localhost/slow/ok", {
delay: 1000,
@@ -288,4 +314,57 @@ describe("useFetchGet", () => {
await fetchMock.flush(true);
}
});
+
+ it("doesn't update error on unparsable JSON after cleanup", async () => {
+ fetchMock.mock("http://localhost/slow/json/invalid", {
+ delay: 1000,
+ headers: { "Content-Type": "application/json" },
+ body: "this is not a valid JSON body",
+ });
+
+ const Component = () => {
+ const { response, error, isLoading } = useFetchGet(
+ "http://localhost/slow/json/invalid"
+ );
+ return (
+
+ {response}
+ {error}
+ {isLoading}
+
+ );
+ };
+
+ const tree = mount();
+ tree.unmount();
+
+ jest.runOnlyPendingTimers();
+ await fetchMock.flush(true);
+ });
+
+ it("doesn't update response after cleanup", async () => {
+ fetchMock.mock("http://localhost/slow/text", {
+ delay: 1000,
+ body: "ok",
+ });
+
+ const Component = () => {
+ const { response, error, isLoading } = useFetchGet(
+ "http://localhost/slow/text"
+ );
+ return (
+
+ {response}
+ {error}
+ {isLoading}
+
+ );
+ };
+
+ const tree = mount();
+ tree.unmount();
+
+ jest.runOnlyPendingTimers();
+ await fetchMock.flush(true);
+ });
});