From ea201d4361b41af88ae8540423bb826a268032dd Mon Sep 17 00:00:00 2001
From: Christina Jenks <christina.jenks@ess.eu>
Date: Wed, 13 Sep 2023 11:29:50 +0000
Subject: [PATCH] CE-2065: replace useIoc hook with common

---
 src/__tests__/backend-mock-setup.test.js      | 34 -------------------
 src/api/SwaggerApi.js                         |  7 ----
 .../IOC/AlertMessages/AlertMessages.js        |  2 +-
 .../IOC/IOCLiveStatus/IOCLiveStatus.spec.js   | 19 +++++++++--
 src/components/IOC/IOCTable/IOCDescription.js | 26 +++++++++++---
 .../views/IOC/IocDetailsView.stories.js       | 15 ++++++++
 src/views/IOC/IOCDetailsContainer.js          | 31 ++++++++++++++---
 7 files changed, 80 insertions(+), 54 deletions(-)
 delete mode 100644 src/__tests__/backend-mock-setup.test.js
 create mode 100644 src/stories/views/IOC/IocDetailsView.stories.js

diff --git a/src/__tests__/backend-mock-setup.test.js b/src/__tests__/backend-mock-setup.test.js
deleted file mode 100644
index 9b3d8d3c..00000000
--- a/src/__tests__/backend-mock-setup.test.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import React from "react";
-import { act, render, screen } from "@testing-library/react";
-import { SnackbarProvider } from "notistack";
-import { APIProvider, useIOCList } from "../api/SwaggerApi";
-
-function APIHarness({ children }) {
-  // We need a snackbar provider at the moment
-  return (
-    <SnackbarProvider>
-      <APIProvider>{children}</APIProvider>
-    </SnackbarProvider>
-  );
-}
-
-// This component will just try to use a hook from our API
-// We want to check that we can get a response from the mock backend
-function DisplayIOCs() {
-  const [iocs] = useIOCList();
-  return JSON.stringify(iocs);
-}
-
-test("that using OpenAPIBackend and MSW works with Swagger-Client and our API hooks", async () => {
-  // render and wait for the state changes
-  await act(async () => {
-    render(
-      <APIHarness>
-        <DisplayIOCs />
-      </APIHarness>
-    );
-  });
-
-  // check that we got the example IOCList from the OpenAPI spec back
-  expect(await screen.findByText(/activeDeployment/i)).toBeInTheDocument();
-});
diff --git a/src/api/SwaggerApi.js b/src/api/SwaggerApi.js
index 91e1b6b3..6f5457f4 100644
--- a/src/api/SwaggerApi.js
+++ b/src/api/SwaggerApi.js
@@ -240,13 +240,6 @@ export function useIOCSearch() {
   return useAsync({ fcn: method, call: false, init: emptyIocListResponse });
 }
 
-export function useIOC(id, onError) {
-  const api = useContext(apiContext);
-  const method = useCallAndUnpack(api.apis.IOCs.getIoc, unpackIOC);
-  const boundMethod = useCallback(method.bind(null, { ioc_id: id }), [id]);
-  return useAsync({ fcn: boundMethod, onError: onError });
-}
-
 export function useCreateIOC(onError) {
   const api = useContext(apiContext);
   const method = useCallAndUnpack(
diff --git a/src/components/IOC/AlertMessages/AlertMessages.js b/src/components/IOC/AlertMessages/AlertMessages.js
index 9496d633..e06128b2 100644
--- a/src/components/IOC/AlertMessages/AlertMessages.js
+++ b/src/components/IOC/AlertMessages/AlertMessages.js
@@ -35,7 +35,7 @@ export default function AlertMessages({ alerts }) {
       spacing={1}
       direction="column"
     >
-      {alerts.map((alert) => (
+      {alerts?.map((alert) => (
         <Grid
           item
           key={alert?.message || alert}
diff --git a/src/components/IOC/IOCLiveStatus/IOCLiveStatus.spec.js b/src/components/IOC/IOCLiveStatus/IOCLiveStatus.spec.js
index bf6fce40..07d67abf 100644
--- a/src/components/IOC/IOCLiveStatus/IOCLiveStatus.spec.js
+++ b/src/components/IOC/IOCLiveStatus/IOCLiveStatus.spec.js
@@ -1,14 +1,27 @@
-import React from "react";
-import { useIOC } from "../../../api/SwaggerApi";
+import React, { useContext, useMemo } from "react";
 import { AppHarness } from "../../../mocks/AppHarness";
 import { IOCLiveStatus } from ".";
+import { apiContext } from "../../../api/DeployApi";
+import { useAPIMethod } from "@ess-ics/ce-ui-common/dist/hooks/API";
 
 function mountIntoHarness(children) {
   cy.mount(<AppHarness>{children}</AppHarness>);
 }
 
 function IOCLiveStatusContainer() {
-  const [ioc] = useIOC(2);
+  const client = useContext(apiContext);
+
+  const params = useMemo(
+    () => ({
+      ioc_id: 2
+    }),
+    []
+  );
+
+  const { value: ioc } = useAPIMethod({
+    fcn: client.apis.IOCs.getIoc,
+    params
+  });
 
   return ioc ? <IOCLiveStatus ioc={ioc} /> : null;
 }
diff --git a/src/components/IOC/IOCTable/IOCDescription.js b/src/components/IOC/IOCTable/IOCDescription.js
index 980dd0dc..6db104ff 100644
--- a/src/components/IOC/IOCTable/IOCDescription.js
+++ b/src/components/IOC/IOCTable/IOCDescription.js
@@ -1,6 +1,7 @@
-import React from "react";
-import { useIOC } from "../../../api/SwaggerApi";
+import React, { useContext, useMemo } from "react";
+import { apiContext } from "../../../api/SwaggerApi";
 import { Skeleton, Tooltip, Typography } from "@mui/material";
+import { useAPIMethod } from "@ess-ics/ce-ui-common";
 
 function createIocDescription(description) {
   return (
@@ -29,10 +30,27 @@ function createIocDescription(description) {
 }
 
 export const IOCDescription = ({ id }) => {
-  const [ioc, , , loading] = useIOC(id);
+  const client = useContext(apiContext);
 
-  if (loading) {
+  const params = useMemo(
+    () => ({
+      ioc_id: id
+    }),
+    [id]
+  );
+
+  const {
+    value: ioc,
+    loading,
+    dataReady
+  } = useAPIMethod({
+    fcn: client.apis.IOCs.getIoc,
+    params
+  });
+
+  if (loading || !dataReady) {
     return <Skeleton width="100%" />;
   }
+
   return createIocDescription(ioc?.description);
 };
diff --git a/src/stories/views/IOC/IocDetailsView.stories.js b/src/stories/views/IOC/IocDetailsView.stories.js
new file mode 100644
index 00000000..ea0221de
--- /dev/null
+++ b/src/stories/views/IOC/IocDetailsView.stories.js
@@ -0,0 +1,15 @@
+import React from "react";
+import { AppHarness } from "../../../mocks/AppHarness";
+import { IOCDetailsContainer } from "../../../views/IOC/IOCDetailsContainer";
+
+export default {
+  title: "Views/IOC/IOCDetailsView"
+};
+
+const Template = () => (
+  <AppHarness>
+    <IOCDetailsContainer id={346} />
+  </AppHarness>
+);
+
+export const Default = () => <Template />;
diff --git a/src/views/IOC/IOCDetailsContainer.js b/src/views/IOC/IOCDetailsContainer.js
index ab907931..00aee004 100644
--- a/src/views/IOC/IOCDetailsContainer.js
+++ b/src/views/IOC/IOCDetailsContainer.js
@@ -1,22 +1,43 @@
-import React, { useEffect, useContext, useState } from "react";
+import React, { useEffect, useContext, useState, useMemo } from "react";
 import { IOCDetailsView } from "./IOCDetailsView";
 import { LinearProgress } from "@mui/material";
 import NotFoundView from "../../components/navigation/NotFoundView/NotFoundView";
 import { onFetchEntityError } from "../../components/common/Helper";
-import { useIOC } from "../../api/SwaggerApi";
 import { userContext } from "@ess-ics/ce-ui-common/dist/contexts/User";
 import useUrlState from "@ahooksjs/use-url-state";
+import { apiContext } from "../../api/DeployApi";
+import { useAPIMethod } from "@ess-ics/ce-ui-common";
 
 export function IOCDetailsContainer({ id }) {
   const { user } = useContext(userContext);
   const [urlState] = useUrlState();
   const [error, setError] = useState(null);
 
-  const [ioc, getIOC /* reset*/, , loading] = useIOC(id, (m, s) => {
-    // handle error code 404, and define custom message on the UI because BE sends back generic error message
-    onFetchEntityError(m, s, setError);
+  const client = useContext(apiContext);
+
+  const params = useMemo(
+    () => ({
+      ioc_id: id
+    }),
+    [id]
+  );
+
+  const {
+    value: ioc,
+    wrapper: getIOC,
+    loading,
+    error: fetchError
+  } = useAPIMethod({
+    fcn: client.apis.IOCs.getIoc,
+    params
   });
 
+  useEffect(() => {
+    if (fetchError) {
+      onFetchEntityError(fetchError?.message, fetchError?.status, setError);
+    }
+  }, [fetchError]);
+
   useEffect(() => {
     // user logs in => clear error message, and try to re-request userInfo
     if (user) {
-- 
GitLab