From b9fb9c905a5bad2e798cc73640d1751070d67bd2 Mon Sep 17 00:00:00 2001 From: ACoolmanTelicent Date: Mon, 24 Jun 2024 17:55:00 +0100 Subject: [PATCH] feat(tests): add --- src/api/assessments.js | 6 +- src/api/common.js | 10 +- src/api/flood-watch-areas.js | 2 +- src/components/Dataset/Assessments.jsx | 2 +- .../__tests__/AssessmentTypes.test.jsx | 126 +++++++ .../Dataset/__tests__/Assessments.test.jsx | 33 ++ .../Dataset/__tests__/Dataset.test.jsx | 26 ++ .../Dataset/__tests__/FloodAreas.test.jsx | 72 ++++ .../Dataset/__tests__/GroupedTypes.test.jsx | 123 +++++++ src/components/Grid/Grid.test.jsx | 82 +++++ .../SelectedElements/ElementDetails.jsx | 2 +- .../ResidentialInformation.jsx | 2 +- .../__tests__/ConnectedAssets.test.jsx | 67 ++++ .../__tests__/Dependents.test.jsx | 158 +++++++++ .../__tests__/ElementDetails.test.jsx | 255 ++++++++++++++ .../__tests__/Providers.test.jsx | 154 ++++++++ .../__tests__/ResidentialInformation.test.jsx | 220 ++++++++++++ .../__tests__/Residents.test.jsx | 175 ++++++++++ .../__tests__/SelectedElements.test.jsx | 181 ++++++++++ .../__snapshots__/Dependents.test.jsx.snap | 324 +++++++++++++++++ .../__snapshots__/Providers.test.jsx.snap | 148 ++++++++ .../SelectedElements.test.jsx.snap | 122 +++++++ .../InfoPanel/__tests__/InfoPanel.test.jsx | 50 +++ src/components/Map/FloodAreaWidget.jsx | 4 +- .../Map/__tests__/FloodWarningWidget.test.jsx | 21 ++ .../Map/__tests__/MapFeatures.test.jsx | 127 +++++++ .../Map/__tests__/PointAssets.test.jsx | 330 ++++++++++++++++++ .../__snapshots__/MapFeatures.test.jsx.snap | 45 +++ .../__snapshots__/PointAssets.test.jsx.snap | 138 ++++++++ .../NetworkGraph/GraphToolbar.test.js | 105 ++++++ .../__snapshots__/GraphToolbar.test.js.snap | 60 ++++ .../__tests__/useMapInteractions.test.js | 74 ++++ .../__tests__/useFloodAreaPolygons.test.js | 65 ++++ src/mocks/data/assessments.js | 9 + src/mocks/data/asset-details.js | 31 ++ src/mocks/data/electrical-power-complex.js | 111 ++++++ src/mocks/data/energy-connections.js | 27 ++ src/mocks/data/features/american-feature.js | 95 +++++ src/mocks/data/features/index.js | 2 + ...seal-bay-newland-and-seddon-on-american.js | 121 +++++++ src/mocks/data/index.js | 10 + src/mocks/data/medical-assets.js | 31 ++ src/mocks/data/medical-connections.js | 16 + src/mocks/data/segments.js | 92 +++++ src/mocks/data/transport-assets.js | 131 +++++++ src/mocks/data/transport-connections.js | 136 ++++++++ src/mocks/data/wow-asset-types.js | 49 +++ src/mocks/handlers.js | 25 ++ src/mocks/index.js | 4 + .../resolvers/assessments/assessments.js | 4 + .../resolvers/assessments/asset-types.js | 12 + src/mocks/resolvers/assessments/index.js | 2 + src/mocks/resolvers/asset/asset.js | 108 ++++++ src/mocks/resolvers/asset/dependents.js | 75 ++++ src/mocks/resolvers/asset/index.js | 4 + src/mocks/resolvers/asset/providers.js | 51 +++ src/mocks/resolvers/asset/residents.js | 22 ++ src/mocks/resolvers/connections.js | 19 + src/mocks/resolvers/empty-response.js | 2 + src/mocks/resolvers/errors.js | 4 + .../resolvers/flood-areas/all-flood-areas.js | 28 ++ .../flood-areas/flood-area-polygons.js | 37 ++ src/mocks/resolvers/flood-areas/index.js | 2 + src/mocks/resolvers/icon-styles.js | 47 +++ src/mocks/resolvers/index.js | 10 + src/mocks/resolvers/ontology-class.js | 33 ++ src/mocks/resolvers/ontology-styles.js | 51 +++ src/mocks/resolvers/person-residences.js | 32 ++ src/mocks/server.js | 5 + src/setupTests.js | 16 +- src/test-utils.js | 4 +- 71 files changed, 4743 insertions(+), 24 deletions(-) create mode 100644 src/components/Dataset/__tests__/AssessmentTypes.test.jsx create mode 100644 src/components/Dataset/__tests__/Assessments.test.jsx create mode 100644 src/components/Dataset/__tests__/Dataset.test.jsx create mode 100644 src/components/Dataset/__tests__/FloodAreas.test.jsx create mode 100644 src/components/Dataset/__tests__/GroupedTypes.test.jsx create mode 100644 src/components/Grid/Grid.test.jsx create mode 100644 src/components/InfoPanel/SelectedElements/__tests__/ConnectedAssets.test.jsx create mode 100644 src/components/InfoPanel/SelectedElements/__tests__/Dependents.test.jsx create mode 100644 src/components/InfoPanel/SelectedElements/__tests__/ElementDetails.test.jsx create mode 100644 src/components/InfoPanel/SelectedElements/__tests__/Providers.test.jsx create mode 100644 src/components/InfoPanel/SelectedElements/__tests__/ResidentialInformation.test.jsx create mode 100644 src/components/InfoPanel/SelectedElements/__tests__/Residents.test.jsx create mode 100644 src/components/InfoPanel/SelectedElements/__tests__/SelectedElements.test.jsx create mode 100644 src/components/InfoPanel/SelectedElements/__tests__/__snapshots__/Dependents.test.jsx.snap create mode 100644 src/components/InfoPanel/SelectedElements/__tests__/__snapshots__/Providers.test.jsx.snap create mode 100644 src/components/InfoPanel/SelectedElements/__tests__/__snapshots__/SelectedElements.test.jsx.snap create mode 100644 src/components/InfoPanel/__tests__/InfoPanel.test.jsx create mode 100644 src/components/Map/__tests__/FloodWarningWidget.test.jsx create mode 100644 src/components/Map/__tests__/MapFeatures.test.jsx create mode 100644 src/components/Map/__tests__/PointAssets.test.jsx create mode 100644 src/components/Map/__tests__/__snapshots__/MapFeatures.test.jsx.snap create mode 100644 src/components/Map/__tests__/__snapshots__/PointAssets.test.jsx.snap create mode 100644 src/components/NetworkGraph/GraphToolbar.test.js create mode 100644 src/components/NetworkGraph/__snapshots__/GraphToolbar.test.js.snap create mode 100644 src/hooks/__tests__/useMapInteractions.test.js create mode 100644 src/hooks/queries/flood-areas/__tests__/useFloodAreaPolygons.test.js create mode 100644 src/mocks/data/assessments.js create mode 100644 src/mocks/data/asset-details.js create mode 100644 src/mocks/data/electrical-power-complex.js create mode 100644 src/mocks/data/energy-connections.js create mode 100644 src/mocks/data/features/american-feature.js create mode 100644 src/mocks/data/features/index.js create mode 100644 src/mocks/data/features/seal-bay-newland-and-seddon-on-american.js create mode 100644 src/mocks/data/index.js create mode 100644 src/mocks/data/medical-assets.js create mode 100644 src/mocks/data/medical-connections.js create mode 100644 src/mocks/data/segments.js create mode 100644 src/mocks/data/transport-assets.js create mode 100644 src/mocks/data/transport-connections.js create mode 100644 src/mocks/data/wow-asset-types.js create mode 100644 src/mocks/handlers.js create mode 100644 src/mocks/index.js create mode 100644 src/mocks/resolvers/assessments/assessments.js create mode 100644 src/mocks/resolvers/assessments/asset-types.js create mode 100644 src/mocks/resolvers/assessments/index.js create mode 100644 src/mocks/resolvers/asset/asset.js create mode 100644 src/mocks/resolvers/asset/dependents.js create mode 100644 src/mocks/resolvers/asset/index.js create mode 100644 src/mocks/resolvers/asset/providers.js create mode 100644 src/mocks/resolvers/asset/residents.js create mode 100644 src/mocks/resolvers/connections.js create mode 100644 src/mocks/resolvers/empty-response.js create mode 100644 src/mocks/resolvers/errors.js create mode 100644 src/mocks/resolvers/flood-areas/all-flood-areas.js create mode 100644 src/mocks/resolvers/flood-areas/flood-area-polygons.js create mode 100644 src/mocks/resolvers/flood-areas/index.js create mode 100644 src/mocks/resolvers/icon-styles.js create mode 100644 src/mocks/resolvers/index.js create mode 100644 src/mocks/resolvers/ontology-class.js create mode 100644 src/mocks/resolvers/ontology-styles.js create mode 100644 src/mocks/resolvers/person-residences.js create mode 100644 src/mocks/server.js diff --git a/src/api/assessments.js b/src/api/assessments.js index 594f1d7..72bcec4 100644 --- a/src/api/assessments.js +++ b/src/api/assessments.js @@ -22,7 +22,7 @@ export const fetchAssetTypes = async (assessment) => { if (!response.ok) { throw new Error( - `An error occured while retrieving data types for ${assessment}` + `An error occurred while retrieving data types for ${assessment}` ); } @@ -43,7 +43,7 @@ export const fetchAssessmentAssets = async (assessment, types) => { if (!response.ok) { throw new Error( - `An error occured while retrieving assets for assessment ${assessment} and types ${types.toString()}` + `An error occurred while retrieving assets for assessment ${assessment} and types ${types.toString()}` ); } @@ -64,7 +64,7 @@ export const fetchAssessmentDependencies = async (assessment, types) => { if (!response.ok) { throw new Error( - `An error occured while retrieving dependencies for assessment ${assessment} and types ${typeParams.toString()}` + `An error occurred while retrieving dependencies for assessment ${assessment} and types ${typeParams.toString()}` ); } diff --git a/src/api/common.js b/src/api/common.js index f216965..53336b2 100644 --- a/src/api/common.js +++ b/src/api/common.js @@ -19,7 +19,7 @@ export const fetchResidentialInformation = async (personUri) => { fetchOptions ); if (!response.ok) { - throw new Error("An error occured while retrieving residential information"); + throw new Error("An error occurred while retrieving residential information"); } return response.json(); }; @@ -31,7 +31,7 @@ export const fetchFloodTimeline = async (floodArea) => { const response = await fetch(createParalogEndpoint(`states?${queryParam}`), fetchOptions); if (!response.ok) { - throw new Error(`An error occured while retrieving flood timeline for Flood Area ${floodArea}`); + throw new Error(`An error occurred while retrieving flood timeline for Flood Area ${floodArea}`); } return response.json(); @@ -39,12 +39,12 @@ export const fetchFloodTimeline = async (floodArea) => { export const fetchFloodMonitoringStations = async () => { const response = await fetch( - "https://environment.data.gov.uk/flood-monitoring/id/stations?catchmentName=Isle%20of%20Wight" + "https://environment.data.gov.uk/flood-monitoring/id/stations?catchmentName=Kangaroo%20Island" ); if (!response.ok) { throw new Error( - "An error occured while retrieving flood monitoring stations for the Island of Ice" + "An error occurred while retrieving flood monitoring stations for the Kangaroo Island" ); } return response.json(); @@ -54,7 +54,7 @@ export const fetchBuildingsEpcRating = async () => { const response = await fetch(createParalogEndpoint("buildings")); if (!response.ok) { - throw new Error("An error occured while retrieving building epc ratings for the Island of Ice"); + throw new Error("An error occurred while retrieving building epc ratings for the Kangaroo Island"); } return response.json(); }; diff --git a/src/api/flood-watch-areas.js b/src/api/flood-watch-areas.js index bc7110d..1c4c8f1 100644 --- a/src/api/flood-watch-areas.js +++ b/src/api/flood-watch-areas.js @@ -23,7 +23,7 @@ export const fetchFloodAreaPolygon = async (polygonUri) => { if (!response.ok) { throw new Error( - data?.detail || `An error occured while retrieving polygon ${polygonUri}` + data?.detail || `An error occurred while retrieving polygon ${polygonUri}` ); } return data; diff --git a/src/components/Dataset/Assessments.jsx b/src/components/Dataset/Assessments.jsx index d49794d..9f063bc 100644 --- a/src/components/Dataset/Assessments.jsx +++ b/src/components/Dataset/Assessments.jsx @@ -16,7 +16,7 @@ const Assessments = () => { if (isError) return (

- An error occured while retrieving assessments. Please try again. If problem persists contact + An error occurred while retrieving assessments. Please try again. If problem persists contact admin

); diff --git a/src/components/Dataset/__tests__/AssessmentTypes.test.jsx b/src/components/Dataset/__tests__/AssessmentTypes.test.jsx new file mode 100644 index 0000000..b3dd2a3 --- /dev/null +++ b/src/components/Dataset/__tests__/AssessmentTypes.test.jsx @@ -0,0 +1,126 @@ +import { rest } from "msw"; +import { screen, waitForElementToBeRemoved, within } from "@testing-library/react"; + +import { DatasetProvider, ElementsProvider } from "context"; +import { createParalogEndpoint } from "api/combined"; +import server, { ASSESSMENTS } from "mocks"; +import { mockEmptyResponse, mock400Error } from "mocks/resolvers"; +import { DSProvidersWrapper, renderWithQueryClient } from "test-utils"; + +import AssessmentTypes from "../AssessmentTypes"; + +const renderAssessmentTypes = () => + renderWithQueryClient( + + + + + , + { wrapper: ElementsProvider } + ); + +const waitForDataToLoad = async () => { + await waitForElementToBeRemoved(() => screen.queryByText(/fetching data types/i)); +}; + +describe("AssessmentTypes component", () => { + test("renders grouped types", async () => { + renderAssessmentTypes(); + await waitForDataToLoad(); + + expect( + screen.getByRole("button", { name: /Green grid/i }) + ).toBeInTheDocument(); + expect(screen.getByRole("button", { name: /Facility/i })).toBeInTheDocument(); + expect(screen.getByRole("button", { name: /Wastewater complex/i })).toBeInTheDocument(); + expect(screen.getByRole("button", { name: /Other/i })).toBeInTheDocument(); + }); + + test("renders green grid types with total count", async () => { + const { user } = renderAssessmentTypes(); + await waitForDataToLoad(); + + await user.click(screen.getByRole("button", { name: "Green grid" })); + const greenGridListItems = within( + screen.getByRole("treeitem", { + name: /Green Grid/i, + expanded: true, + }) + ).getAllByRole("listitem"); + + expect( + within(greenGridListItems[0]).getByLabelText( + /large wind farm \[8\]/i + ) + ).toBeInTheDocument(); + expect( + within(greenGridListItems[1]).getByLabelText( + /small wind farm \[9\]/i + ) + ).toBeInTheDocument(); + }); + + test("renders other types with total count", async () => { + const { user } = renderAssessmentTypes(); + await waitForDataToLoad(); + + await user.click(screen.getByRole("button", { name: "Other" })); + const otherListItems = within( + screen.getByRole("treeitem", { + name: /other/i, + expanded: true, + }) + ).getAllByRole("listitem"); + + expect(within(otherListItems[0]).getByLabelText(/tunnel \[2\]/i)).toBeInTheDocument(); + expect(within(otherListItems[1]).getByLabelText(/underpass \[2\]/i)).toBeInTheDocument(); + }); + + test("adds type to other when super class endpoint errors", async () => { + server.use( + rest.get(createParalogEndpoint("ontology/class"), (req, res, ctx) => { + const classUri = req.url.searchParams.get("classUri"); + if ( + classUri === "http://ies.example.com/ontology/ies#SmallWindFarm" + ) { + return res.once(ctx.status(404), ctx.json("Not found")); + } + }) + ); + const { user } = renderAssessmentTypes(); + await waitForDataToLoad(); + + await user.click(screen.getByRole("button", { name: "Other" })); + const otherListItems = within( + screen.getByRole("treeitem", { + name: /other/i, + expanded: true, + }) + ).getAllByRole("listitem"); + + expect(otherListItems).toHaveLength(3); + expect( + within(otherListItems[0]).getByLabelText(/small wind farm \[9\]/i) + ).toBeInTheDocument(); + }); + + test("renders message when asset types are not found", async () => { + server.use(rest.get(createParalogEndpoint("assessments/asset-types"), mockEmptyResponse)); + renderAssessmentTypes(); + await waitForDataToLoad(); + + expect(await screen.findByText("Dataset types not found")).toBeInTheDocument(); + }); + + test("renders error message when /assessments/asset-types api call fails", async () => { + server.use(rest.get(createParalogEndpoint("assessments/asset-types"), mock400Error)); + renderAssessmentTypes(); + await waitForDataToLoad(); + + expect( + screen.getByText( + "An error occurred while retrieving data types for https://www.example.com/Instruments#wowAssessment" + ) + ).toBeInTheDocument(); + }); +}); diff --git a/src/components/Dataset/__tests__/Assessments.test.jsx b/src/components/Dataset/__tests__/Assessments.test.jsx new file mode 100644 index 0000000..645a63d --- /dev/null +++ b/src/components/Dataset/__tests__/Assessments.test.jsx @@ -0,0 +1,33 @@ +import { rest } from "msw"; +import { screen, waitForElementToBeRemoved } from "@testing-library/react"; + +import server from "mocks"; +import { mockEmptyResponse, mockError } from "mocks/resolvers"; +import { renderWithQueryClient } from "test-utils"; + +import Assessments from "../Assessments"; +import { createParalogEndpoint } from "api/combined"; + +const assessmentsURL = createParalogEndpoint("assessments"); + +describe("Assessments component", () => { + test("renders message when /assessments are not found", async () => { + server.use(rest.get(assessmentsURL, mockEmptyResponse)); + renderWithQueryClient(); + + await waitForElementToBeRemoved(() => screen.queryByText(/fetching assessments/i)); + expect(await screen.findByText(/assessments not found/i)).toBeInTheDocument(); + }); + + test("renders error message when /assessments api call fails", async () => { + server.use(rest.get(assessmentsURL, mockError)); + renderWithQueryClient(); + + await waitForElementToBeRemoved(() => screen.queryByText(/fetching assessments/i)); + expect( + screen.getByText( + "An error occurred while retrieving assessments. Please try again. If problem persists contact admin" + ) + ).toBeInTheDocument(); + }); +}); diff --git a/src/components/Dataset/__tests__/Dataset.test.jsx b/src/components/Dataset/__tests__/Dataset.test.jsx new file mode 100644 index 0000000..3b20960 --- /dev/null +++ b/src/components/Dataset/__tests__/Dataset.test.jsx @@ -0,0 +1,26 @@ +import { screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { Provider as UseHttpProvider } from "use-http"; + +import { ElementsProvider } from "context"; +import { DSProvidersWrapper, renderWithQueryClient } from "test-utils"; +import Dataset from "../Dataset"; + +const user = userEvent.setup(); + +const AllProviders = ({ children }) => ( + + + {children} + + +); + +describe("Dataset panel", () => { + test("collapses", async () => { + renderWithQueryClient(, { wrapper: AllProviders }); + + await user.click(screen.getByRole("button", { name: "Close dataset panel" })); + expect(screen.queryByRole("checkbox", { name: "Energy [25]" })).not.toBeInTheDocument(); + }); +}); diff --git a/src/components/Dataset/__tests__/FloodAreas.test.jsx b/src/components/Dataset/__tests__/FloodAreas.test.jsx new file mode 100644 index 0000000..bcdb26c --- /dev/null +++ b/src/components/Dataset/__tests__/FloodAreas.test.jsx @@ -0,0 +1,72 @@ +import { screen, waitForElementToBeRemoved, within } from "@testing-library/react"; +import { rest } from "msw"; + +import { DatasetContext, DatasetProvider } from "context"; +import { createParalogEndpoint } from "api/combined"; +import { server } from "mocks"; +import { renderWithQueryClient } from "test-utils"; + +import FloodAreas from "../FloodAreas"; + +const waitForFloodAreasToLoad = async () => { + await waitForElementToBeRemoved(() => screen.queryByText("Fetching flood areas")); +}; + +describe("Flood areas component", () => { + test("renders flood watch and flood areas", async () => { + const { user } = renderWithQueryClient( + + + + ); + await waitForFloodAreasToLoad(); + + const floodWatchAreaListItems = screen.getAllByRole("listitem"); + const toggleBtns = screen.getAllByRole("button", { name: "Toggle" }); + + expect(floodWatchAreaListItems).toHaveLength(1); + expect( + within(floodWatchAreaListItems[0]).getByRole("checkbox", { name: "American" }) + ).toBeInTheDocument(); + + await user.click(toggleBtns[0]); + expect( + within(floodWatchAreaListItems[0]).getByRole("checkbox", { + name: "Seal bay, Newland, and Seddon on the American", + }) + ).toBeInTheDocument(); + expect( + within(floodWatchAreaListItems[0]).getByRole("checkbox", { + name: "Blackwell, Bordertown, Minipa, Bridgehaven on the American", + }) + ).toBeInTheDocument(); + }); + + test("renders error when flood watch and flood areas are not found", async () => { + server.use( + rest.get(createParalogEndpoint("flood-watch-areas"), (req, res, ctx) => { + return res.once(ctx.status(404), ctx.json({ detail: "Flood areas not found" })); + }) + ); + renderWithQueryClient( + + + + ); + await waitForFloodAreasToLoad(); + expect(screen.getByText("Flood areas not found")).toBeInTheDocument(); + }); + + test("renders calls addSelectedFloodAreas when checkbox is clicked", async () => { + const mockOnFloodAreaSelect = jest.fn(); + const { user } = renderWithQueryClient( + + + + ); + await waitForFloodAreasToLoad(); + + await user.click(screen.getByRole("checkbox", { name: "American" })); + expect(mockOnFloodAreaSelect).toHaveBeenCalled(); + }); +}); diff --git a/src/components/Dataset/__tests__/GroupedTypes.test.jsx b/src/components/Dataset/__tests__/GroupedTypes.test.jsx new file mode 100644 index 0000000..260f92b --- /dev/null +++ b/src/components/Dataset/__tests__/GroupedTypes.test.jsx @@ -0,0 +1,123 @@ +import { screen, render, waitFor } from "@testing-library/react"; +import { rest } from "msw"; +import userEvent from "@testing-library/user-event"; + +import { + ASSESSMENTS_ASSETS_ENDPOINT, + ASSESSMENTS_DEPENDENCIES_ENDPOINT, +} from "constants/endpoints"; +import server, { ASSESSMENTS } from "mocks"; +import { mockEmptyResponse, mockError } from "mocks/resolvers"; +import { ErrorNotification } from "lib"; +import { PanelProviders } from "test-utils"; + +import GroupedTypes from "../GroupedTypes"; +import * as datasetUtils from "../dataset-utils"; + +const user = userEvent.setup(); + +const waitForDataToLoad = async () => { + const spyOnCreateAssets = jest.spyOn(datasetUtils, "createAssets"); + const spyOnCreateDependencies = jest.spyOn(datasetUtils, "createDependencies"); + + await waitFor(() => { + expect(spyOnCreateAssets).toHaveReturned(); + expect(spyOnCreateDependencies).toHaveReturned(); + }); +}; + +const selectTunnelDataset = async (mockSetSelectedTypes) => { + const tunnelCheckbox = screen.getByRole("checkbox", { name: "tunnel [2]" }); + await user.click(tunnelCheckbox); + expect(mockSetSelectedTypes).toHaveBeenCalledTimes(1); +}; + +const renderGroupedTypes = ({ types, setSelectedTypes, selectedTypes }) => { + const modalRoot = document.createElement("div"); + modalRoot.setAttribute("id", "root"); + document.body.appendChild(modalRoot); + + render( + <> + + + , + { wrapper: PanelProviders, container: document.body.appendChild(modalRoot) } + ); +}; + +describe.skip("GroupedTypes component", () => { + test("renders error message when assessments/assets api call fails", async () => { + const mockSetSelectedTypes = jest.fn(); + server.use(rest.get(ASSESSMENTS_ASSETS_ENDPOINT, mockError)); + renderGroupedTypes({ + types: [ + { + uri: "http://ies.example.com/ontology/ies#Tunnel", + assetCount: 2, + subClassOf: null, + superClass: "other", + }, + ], + selectedTypes: [], + setSelectedTypes: mockSetSelectedTypes, + }); + await selectTunnelDataset(mockSetSelectedTypes); + + await waitForDataToLoad(); + expect( + screen.getByText("Could not add data. Reason: Failed to resolve the data") + ).toBeInTheDocument(); + }); + + test("renders error message when assessments/dependencies api call fails", async () => { + const mockSetSelectedTypes = jest.fn(); + server.use(rest.get(ASSESSMENTS_DEPENDENCIES_ENDPOINT, mockError)); + renderGroupedTypes({ + types: [ + { + uri: "http://ies.example.com/ontology/ies#Tunnel", + assetCount: 2, + subClassOf: null, + superClass: "other", + }, + ], + selectedTypes: [], + setSelectedTypes: mockSetSelectedTypes, + }); + await selectTunnelDataset(mockSetSelectedTypes); + + await waitForDataToLoad(); + expect( + screen.getByText("Could not add data. Reason: Failed to resolve the data") + ).toBeInTheDocument(); + }); + + test.skip("renders error message when assets/:id/parts api call fails", async () => { + server.use(rest.get("/assets/:id/parts", mockError)); + renderGroupedTypes({ + types: [ + { + uri: "http://ies.example.com/ontology/ies#Tunnel", + assetCount: 2, + subClassOf: null, + superClass: "other", + }, + ], + selectedTypes: ["http://ies.example.com/ontology/ies#Tunnel"], + }); + + await waitForDataToLoad(); + expect(screen.getByRole("checkbox", { name: "tunnel [2]" })).toBeChecked(); + expect( + screen.getByText("Could not add data. Reason: Failed to resolve the data") + ).toBeInTheDocument(); + }); +}); diff --git a/src/components/Grid/Grid.test.jsx b/src/components/Grid/Grid.test.jsx new file mode 100644 index 0000000..ad6eb7c --- /dev/null +++ b/src/components/Grid/Grid.test.jsx @@ -0,0 +1,82 @@ +import { screen, render, waitFor } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; + +import { Dataset } from "components"; +import { ElementsProvider } from "context"; + +import Grid from "./Grid"; +import * as utils from "../Dataset/dataset-utils"; + +const user = userEvent.setup(); + +describe.skip("Grid component", () => { + test("renders grid", async () => { + const spyOnCreateData = jest.spyOn(utils, "createData"); + render( + + + + + ); + + await user.click(await screen.findByRole("checkbox", { name: "Energy [25]" })); + await waitFor(() => expect(spyOnCreateData).toHaveBeenCalledTimes(1)); + expect(spyOnCreateData).toHaveReturned(); + expect(screen.getByTestId("grid")).toMatchSnapshot(); + }); +}); + +xdescribe("Grid should populate assets and connections", () => { + describe("Assets should", () => { + beforeEach(() => { + render( + + + + ); + }); + + it("populate first cell in row with asset id", () => { + const buttons = screen.getAllByRole("button", { name: /fed/i }); + expect(buttons).toHaveLength(2); + }); + + it("show human readable name", () => { + const cells = screen.getAllByRole("cell", { name: /fed/i }); + cells.forEach((cell) => { + expect(cell).toHaveTextContent(/federal reserve/i); + }); + }); + }); + + describe("connections should", () => { + beforeEach(() => { + render( + + + + ); + }); + + it("show criticality for both connections in the grid.", () => { + const buttons = screen.getAllByRole("button", { name: 3 }); + expect(buttons).toHaveLength(2); + }); + }); + + describe("when no data is passed grid should", () => { + beforeEach(() => { + render( + + + + ); + }); + it("should not render any connections if none are passed", () => { + const cells = screen.queryAllByRole("cell"); + const buttons = screen.queryAllByRole("button", { name: /3/ }); + expect(buttons).toHaveLength(0); + expect(cells).toHaveLength(0); + }); + }); +}); diff --git a/src/components/InfoPanel/SelectedElements/ElementDetails.jsx b/src/components/InfoPanel/SelectedElements/ElementDetails.jsx index 6b87630..5899c61 100644 --- a/src/components/InfoPanel/SelectedElements/ElementDetails.jsx +++ b/src/components/InfoPanel/SelectedElements/ElementDetails.jsx @@ -39,7 +39,7 @@ const ElementDetails = ({ element, expand, onViewDetails }) => { const isError = assetInfo.isError || dependentInfo.isError || providerInfo.isError; if (isLoading) return

Fetching element details

; - if (isError) return

An error has occured while fetching information for {element.uri}

; + if (isError) return

An error has occurred while fetching information for {element.uri}

; let details = undefined; if (elemIsAsset) details = element.getDetails(assetInfo.data); diff --git a/src/components/InfoPanel/SelectedElements/ResidentialInformation.jsx b/src/components/InfoPanel/SelectedElements/ResidentialInformation.jsx index 6f53a46..b26fb08 100644 --- a/src/components/InfoPanel/SelectedElements/ResidentialInformation.jsx +++ b/src/components/InfoPanel/SelectedElements/ResidentialInformation.jsx @@ -78,7 +78,7 @@ const Addresses = ({ residences, isLoading, isError, error }) => { {residences.length > LIMIT && ( )} diff --git a/src/components/InfoPanel/SelectedElements/__tests__/ConnectedAssets.test.jsx b/src/components/InfoPanel/SelectedElements/__tests__/ConnectedAssets.test.jsx new file mode 100644 index 0000000..77333a6 --- /dev/null +++ b/src/components/InfoPanel/SelectedElements/__tests__/ConnectedAssets.test.jsx @@ -0,0 +1,67 @@ +import { render, screen, within } from "@testing-library/react"; + +import { ElementsProvider } from "context"; +import { E001_DETAILS, E025_DETAILS } from "mocks"; +import { DSProvidersWrapper } from "test-utils"; +import ConnectedAssets from "../ConnectedAssets"; + +const CONNECTED_ASSETS = [E025_DETAILS, E001_DETAILS]; + +const renderConnectedAssets = ({ connectedAssets, assets = [] }) => { + return render( + + + + + , + { wrapper: ElementsProvider } + ); +}; + +describe("Connected assets component", () => { + test("does NOT render assets when connected assets are not provided", () => { + renderConnectedAssets([]); + expect(screen.queryByRole("list")).toBeEmptyDOMElement(); + }); + + test("does NOT render assets when connected assets is not an array", () => { + const { rerender } = renderConnectedAssets({}); + expect(screen.queryByRole("list")).toBeEmptyDOMElement(); + + rerender(); + expect(screen.queryByRole("list")).toBeEmptyDOMElement(); + }); + + test("renders connected asset details", () => { + renderConnectedAssets({ connectedAssets: [CONNECTED_ASSETS[0]] }); + + const listItems = screen.getAllByRole("listitem"); + expect(listItems).toHaveLength(1); + + expect(within(listItems[0]).getByRole("heading", { level: 4 })).toHaveTextContent( + "Hawk 123 kV Substation - Hands" + ); + expect( + within(listItems[0]).getByText("large wind farm") + ).toBeInTheDocument(); + expect(within(listItems[0]).getByText("E025")).toBeInTheDocument(); + expect(within(listItems[0]).getByText("Criticality: 2")).toBeInTheDocument(); + expect(within(listItems[0]).getByText("Connection Strength: 3")).toBeInTheDocument(); + }); + + test("renders added assets first", () => { + renderConnectedAssets({ + connectedAssets: CONNECTED_ASSETS, + assets: [{ uri: "https://www.example.com/Instruments#E001" }], + }); + + const listItems = screen.getAllByRole("listitem"); + expect(listItems).toHaveLength(2); + expect(within(listItems[0]).getByRole("heading", { level: 4 })).toHaveTextContent( + "Hawk 123 kV Substation - Hands" + ); + expect(within(listItems[1]).getByRole("heading", { level: 4 })).toHaveTextContent( + "Best Coleman Power Station" + ); + }); +}); diff --git a/src/components/InfoPanel/SelectedElements/__tests__/Dependents.test.jsx b/src/components/InfoPanel/SelectedElements/__tests__/Dependents.test.jsx new file mode 100644 index 0000000..6cc5054 --- /dev/null +++ b/src/components/InfoPanel/SelectedElements/__tests__/Dependents.test.jsx @@ -0,0 +1,158 @@ +import React from "react"; +import { screen, waitForElementToBeRemoved, within } from "@testing-library/react"; +import { rest } from "msw"; + +import { ElementsProvider } from "context"; +import { createParalogEndpoint } from "api/combined"; +import { + LARGE_WIND_FARM_ASSETS, + COAL_PLANT_COMPLEX_ASSETS, + server, +} from "mocks"; +import { DSProvidersWrapper, getCreatedAssets, renderWithQueryClient } from "test-utils"; +import { isAsset, isDependency } from "utils"; + +import Dependents from "../Dependents"; + +const renderAssetDependents = async ({ assets, element }) => + renderWithQueryClient( + + + + + + ); + +const renderE003AssetDetails = async (assets) => { + const createdAssets = await getCreatedAssets( + [ + ...LARGE_WIND_FARM_ASSETS, + ...COAL_PLANT_COMPLEX_ASSETS, + ], + assets + ); + const e003 = createdAssets.find((assets) => assets.id === "E003"); + return renderAssetDependents({ assets: createdAssets, element: e003 }); +}; + +const waitForDependentsToLoad = async () => { + await waitForElementToBeRemoved(() => screen.queryByText("Loading dependent assets")); +}; + +const toggleDependents = async (user) => { + await user.click(screen.getByRole("button", { name: /dependent assets/i })); +}; + +describe("Dependents component", () => { + beforeEach(() => { + jest.clearAllMocks(); + jest.resetAllMocks(); + }); + + test("does NOT render dependent assets when element is not defined", async () => { + await renderE003AssetDetails([]); + expect(screen.queryByTestId("dependent-assets")).not.toBeInTheDocument(); + }); + + test("can toggle dependents assets", async () => { + const { user } = await renderE003AssetDetails(["E003"]); + await waitForDependentsToLoad(); + + expect( + screen.getByRole("heading", { name: "4 dependent assets", level: 3 }) + ).toBeInTheDocument(); + expect(screen.queryByRole("list")).not.toBeInTheDocument(); + + await toggleDependents(user); + expect(screen.getByRole("list")).toBeInTheDocument(); + + const dependents = screen.getAllByRole("listitem"); + expect(dependents).toHaveLength(4); + + expect( + within(dependents[0]).getByRole("heading", { name: "Jose 20kv Substation" }) + ).toBeInTheDocument(); + expect(within(dependents[0]).getByText("E008")).toBeInTheDocument(); + + expect( + within(dependents[3]).getByRole("heading", { name: "Best Coleman Power Station" }) + ).toBeInTheDocument(); + expect(within(dependents[3]).getByText("E001")).toBeInTheDocument(); + + expect(dependents).toMatchSnapshot("dependents list"); + }); + + test("does NOT show dependents when none are found", async () => { + server.use( + rest.get(createParalogEndpoint("asset/dependents"), (req, res, ctx) => { + const assetUri = req.url.searchParams.get("assetUri"); + if (assetUri === "https://www.example.com/Instruments#E003") { + return res.once(ctx.status(200), ctx.json([])); + } + }) + ); + + await renderE003AssetDetails(["E001", "E003"]); + await waitForDependentsToLoad(); + + expect(screen.queryByTestId("dependent-assets")).not.toBeInTheDocument(); + }); + + test("renders error message when asset dependents cannot be retrieved", async () => { + server.use( + rest.get(createParalogEndpoint("asset/dependents"), (req, res, ctx) => { + const assetUri = req.url.searchParams.get("assetUri"); + if (assetUri === "https://www.example.com/Instruments#E003") { + return res.once( + ctx.status(404), + ctx.json({ + message: "Depedents for https://www.example.com/Instruments#E003 not found", + }) + ); + } + }) + ); + + await renderE003AssetDetails(["E001", "E003"]); + await waitForDependentsToLoad(); + + expect( + screen.getByText("Failed to retrieve dependents for https://www.example.com/Instruments#E003") + ).toBeInTheDocument(); + }); + + test("renders error message when one or more dependents returns an error", async () => { + server.use( + rest.get(createParalogEndpoint("asset"), (req, res, ctx) => { + const assetUri = req.url.searchParams.get("assetUri"); + if (assetUri === "https://www.example.com/Instruments#E001") { + return res.once( + ctx.status(404), + ctx.json({ + message: "Asset information for https://www.example.com/Instruments#E001 not found", + }) + ); + } + }) + ); + + const { user } = await renderE003AssetDetails(["E001", "E003"]); + await waitForDependentsToLoad(); + + await toggleDependents(user); + const dependents = screen.getAllByRole("listitem"); + expect(dependents).toHaveLength(4); + + expect( + within(dependents[3]).getByText( + "Failed to retrieve asset information for https://www.example.com/Instruments#E001" + ) + ).toBeInTheDocument(); + expect(dependents).toMatchSnapshot("dependents with error(s)"); + }); +}); diff --git a/src/components/InfoPanel/SelectedElements/__tests__/ElementDetails.test.jsx b/src/components/InfoPanel/SelectedElements/__tests__/ElementDetails.test.jsx new file mode 100644 index 0000000..4dde4a9 --- /dev/null +++ b/src/components/InfoPanel/SelectedElements/__tests__/ElementDetails.test.jsx @@ -0,0 +1,255 @@ +import React from "react"; +import { screen, waitForElementToBeRemoved, within } from "@testing-library/react"; + +import { ElementsProvider } from "context"; +import { + LARGE_WIND_FARMS_AND_COAL_PLANT_COMPLEX_DEPENDENCIES, + LARGE_WIND_FARM_ASSETS, + COAL_PLANT_COMPLEX_ASSETS, +} from "mocks"; +import { + DSProvidersWrapper, + getCreatedAssets, + getCreatedDependencies, + renderWithQueryClient, +} from "test-utils"; +import { createAssets } from "components/Dataset/dataset-utils"; + +import ElementDetails from "../ElementDetails"; + +const renderElementDetails = ({ element, expand }) => + renderWithQueryClient( + + + , + { wrapper: ElementsProvider } + ); + +const waitForDetailsToLoad = async () => { + await waitForElementToBeRemoved(() => screen.queryByText("Fetching element details")); +}; + +const renderAssetDetails = async ({ assets, ids, expand }) => { + const mockFindIcon = jest.fn().mockReturnValue({ + classUri: "http://telicent/test/ontology#elementDetails", + color: "#DDDDDD", + backgroundColor: "#121212", + iconFallbackText: "ED", + alt: "ElementDetailsIcon", + }); + const createdAssets = await getCreatedAssets(assets, ids, mockFindIcon); + return renderElementDetails({ element: createdAssets[0], expand }); +}; + +const renderConnectionDetails = ({ dependencies, ids, expand }) => { + const createdDependencies = getCreatedDependencies(dependencies, ids); + renderElementDetails({ element: createdDependencies[0], expand }); +}; + +const renderAndLoadE001Details = async () => { + await renderAssetDetails({ + assets: COAL_PLANT_COMPLEX_ASSETS, + ids: ["E001"], + expand: true, + }); + await waitForDetailsToLoad(); +}; + +const renderAndLoadE003Details = async () => { + await renderAssetDetails({ + assets: LARGE_WIND_FARM_ASSETS, + ids: ["E003"], + expand: true, + }); + await waitForDetailsToLoad(); +}; + +const renderAndLoadE001toE003ConnectionDetails = async () => { + renderConnectionDetails({ + dependencies: + LARGE_WIND_FARMS_AND_COAL_PLANT_COMPLEX_DEPENDENCIES, + ids: ["E001 - E003"], + expand: true, + }); + await waitForDetailsToLoad(); +}; + +describe("Element details component", () => { + test("renders asset icon", async () => { + const mockGetIconStyle = jest.fn().mockReturnValue({ + defaultStyles: { + dark: { + backgroundColor: "#FFFF00", + color: "black", + }, + light: { + backgroundColor: "#FFFF00", + color: "black", + }, + }, + defaultIcons: { + icon: "ri-cloudy-fill", + faIcon: "fa-regular fa-bolt-lightning", + faUnicode: "", + faClass: "fa-regular", + }, + }); + const createdAssets = ( + await createAssets(COAL_PLANT_COMPLEX_ASSETS, mockGetIconStyle, jest.fn()) + ).filter((asset) => asset.id === "E001"); + + renderElementDetails({ element: createdAssets[0], expand: true }); + await waitForDetailsToLoad(); + + expect(screen.getByTitle("CoalPlantComplex-icon")).toBeInTheDocument(); + + // checks dependents are loaded + expect(await screen.findByRole("heading", { name: "1 dependent asset" })).toBeInTheDocument(); + + // checks providers are loaded + expect(await screen.findByRole("heading", { name: "1 provider asset" })).toBeInTheDocument(); + }); + + test("renders summarised asset details", async () => { + await renderAssetDetails({ + assets: COAL_PLANT_COMPLEX_ASSETS, + ids: ["E001"], + expand: false, + }); + await waitForDetailsToLoad(); + + // checks asset name is present + expect(screen.getByRole("heading", { name: "Best Coleman Power Station" })).toBeInTheDocument(); + + // checks asset type is present + expect(screen.getByText("coal plant complex")).toBeInTheDocument(); + + // checks asset ID is present + expect(screen.getByText("E001")).toBeInTheDocument(); + + // checks asset criticality is not present + expect(screen.queryByText("Criticality: 3")).not.toBeInTheDocument(); + + // check description is not rendered + expect(screen.queryByTestId("description")).not.toBeInTheDocument(); + + // checks dependents are not present + expect(screen.queryByRole("heading", { name: "1 dependent asset" })).not.toBeInTheDocument(); + + // checks providers are not present + expect(screen.queryByRole("heading", { name: "1 provider asset" })).not.toBeInTheDocument(); + }); + + test("renders summarised connection details", async () => { + renderConnectionDetails({ + dependencies: + LARGE_WIND_FARMS_AND_COAL_PLANT_COMPLEX_DEPENDENCIES, + ids: ["E001 - E003"], + expand: false, + }); + await waitForDetailsToLoad(); + + // checks connection name is present + expect( + screen.getByRole("heading", { + name: "Best Coleman Power Station - West Coleman 50kV Substation", + }) + ).toBeInTheDocument(); + + // checks connection ID is present + expect(screen.getByText("E001 - E003")).toBeInTheDocument(); + + // checks asset criticality is not present + expect(screen.queryByText("Criticality: 3")).not.toBeInTheDocument(); + + // checks dependents are not present + expect(screen.queryByRole("heading", { name: "1 dependent asset" })).not.toBeInTheDocument(); + + // checks providers are not present + expect(screen.queryByRole("heading", { name: "1 provider asset" })).not.toBeInTheDocument(); + }); + + test("renders asset details", async () => { + await renderAndLoadE001Details(); + + // checks asset name is present + expect(screen.getByRole("heading", { name: "Best Coleman Power Station" })).toBeInTheDocument(); + + // checks asset type is present + expect(screen.getByText("coal plant complex")).toBeInTheDocument(); + + // checks asset ID is present + expect(screen.getByText("E001")).toBeInTheDocument(); + + // checks asset criticality is present + expect(screen.getByText("Criticality: 1")).toBeInTheDocument(); + + // checks asset description is present + expect(screen.getByTestId("description")).toHaveTextContent( + "Coleman power station (or Best power station) is a 1MW Gas Turbine station." + ); + + // checks dependents are loaded + expect(await screen.findByRole("heading", { name: "1 dependent asset" })).toBeInTheDocument(); + + // checks providers are loaded + expect(await screen.findByRole("heading", { name: "1 provider asset" })).toBeInTheDocument(); + }); + + test("does NOT render description when asset doesn't have description", async () => { + await renderAndLoadE003Details(); + + // checks asset name is present + expect( + screen.getByRole("heading", { name: "West Coleman 50kV Substation" }) + ).toBeInTheDocument(); + + // check description is not rendered + expect(screen.queryByTestId("description")).not.toBeInTheDocument(); + + // checks dependents are loaded + expect(await screen.findByRole("heading", { name: "4 dependent assets" })).toBeInTheDocument(); + + // checks providers are loaded + expect(await screen.findByRole("heading", { name: "2 provider assets" })).toBeInTheDocument(); + }); + + test("renders connection details", async () => { + await renderAndLoadE001toE003ConnectionDetails(); + + // checks connection name is present + expect( + screen.getByRole("heading", { + name: "Best Coleman Power Station - West Coleman 50kV Substation", + }) + ).toBeInTheDocument(); + + // checks connection ID is present + expect(screen.getByText("E001 - E003")).toBeInTheDocument(); + + // checks asset criticality is present + expect(screen.getByText("Criticality: 2")).toBeInTheDocument(); + + // checks dependents are loaded + expect(await screen.findByRole("heading", { name: "1 dependent asset" })).toBeInTheDocument(); + + // checks providers are loaded + expect(await screen.findByRole("heading", { name: "1 provider asset" })).toBeInTheDocument(); + }); + + test("renders error message when details are not found", async () => { + const uri = "https://www.wow.gov.uk/ReactTests#E001"; + await renderAssetDetails({ assets: [{ uri }], ids: ["E001"], expand: true }); + await waitForDetailsToLoad(); + expect( + screen.getByText(`An error has occurred while fetching information for ${uri}`) + ).toBeInTheDocument(); + }); + + test("render error message when an element in not provided", async () => { + renderElementDetails({ expand: true }); + expect( + screen.getByText("Unable to retrieve details for unknown element or details not found") + ).toBeInTheDocument(); + }); +}); diff --git a/src/components/InfoPanel/SelectedElements/__tests__/Providers.test.jsx b/src/components/InfoPanel/SelectedElements/__tests__/Providers.test.jsx new file mode 100644 index 0000000..3ebccfc --- /dev/null +++ b/src/components/InfoPanel/SelectedElements/__tests__/Providers.test.jsx @@ -0,0 +1,154 @@ +import React from "react"; +import { screen, waitForElementToBeRemoved, within } from "@testing-library/react"; +import { rest } from "msw"; + +import { ElementsProvider } from "context"; +import { createParalogEndpoint } from "api/combined"; +import { + LARGE_WIND_FARM_ASSETS, + COAL_PLANT_COMPLEX_ASSETS, + server, +} from "mocks"; +import { DSProvidersWrapper, getCreatedAssets, renderWithQueryClient } from "test-utils"; +import { isAsset, isDependency } from "utils"; + +import Providers from "../Providers"; + +const renderAssetProviders = async ({ assets, element }) => { + return renderWithQueryClient( + + + + + + ); +}; + +const renderE003ProviderDetails = async (assets) => { + const createdAssets = await getCreatedAssets( + [ + ...LARGE_WIND_FARM_ASSETS, + ...COAL_PLANT_COMPLEX_ASSETS, + ], + assets + ); + const e003 = createdAssets.find((assets) => assets.id === "E003"); + return renderAssetProviders({ assets: createdAssets, element: e003 }); +}; + +const waitForProvidersToLoad = async () => { + await waitForElementToBeRemoved(() => screen.queryByText("Loading provider assets")); +}; + +const toggleProviders = async (user) => { + await user.click(screen.getByRole("button", { name: /provider assets/i })); +}; + +describe("Providers component", () => { + test("does NOT render provider assets when element is not defined", async () => { + await renderE003ProviderDetails([]); + expect(screen.queryByTestId("provider-assets")).not.toBeInTheDocument(); + }); + + test("can toggle providers assets", async () => { + const { user } = await renderE003ProviderDetails(["E003"]); + await waitForProvidersToLoad(); + + expect( + screen.getByRole("heading", { name: "2 provider assets", level: 3 }) + ).toBeInTheDocument(); + expect(screen.queryByRole("list")).not.toBeInTheDocument(); + + await toggleProviders(user); + expect(screen.getByRole("list")).toBeInTheDocument(); + + const providers = screen.getAllByRole("listitem"); + expect(providers).toHaveLength(2); + + expect( + within(providers[0]).getByRole("heading", { name: "Hawk 123 kV Substation - Hands" }) + ).toBeInTheDocument(); + expect(within(providers[0]).getByText("E025")).toBeInTheDocument(); + + expect( + within(providers[1]).getByRole("heading", { name: "Best Coleman Power Station" }) + ).toBeInTheDocument(); + expect(within(providers[1]).getByText("E001")).toBeInTheDocument(); + + expect(providers).toMatchSnapshot("providers list"); + }); + + test("does NOT show providers when none are found", async () => { + server.use( + rest.get(createParalogEndpoint("asset/providers"), (req, res, ctx) => { + const assetUri = req.url.searchParams.get("assetUri"); + if (assetUri === "https://www.example.com/Instruments#E003") { + return res.once(ctx.status(200), ctx.json([])); + } + }) + ); + + await renderE003ProviderDetails(["E003"]); + await waitForProvidersToLoad(); + + expect(screen.queryByTestId("provider-assets")).not.toBeInTheDocument(); + }); + + test("renders error message when asset providers cannot be retrieved", async () => { + server.use( + rest.get(createParalogEndpoint("asset/providers"), (req, res, ctx) => { + const assetUri = req.url.searchParams.get("assetUri"); + if (assetUri === "https://www.example.com/Instruments#E003") { + return res.once( + ctx.status(404), + ctx.json({ + message: "Depedents for https://www.example.com/Instruments#E003 not found", + }) + ); + } + }) + ); + + await renderE003ProviderDetails(["E001", "E003"]); + await waitForProvidersToLoad(); + + expect( + screen.getByText("Failed to retrieve providers for https://www.example.com/Instruments#E003") + ).toBeInTheDocument(); + }); + + test("renders error message when one or more providers returns an error", async () => { + server.use( + rest.get(createParalogEndpoint("asset"), (req, res, ctx) => { + const assetUri = req.url.searchParams.get("assetUri"); + if (assetUri === "https://www.example.com/Instruments#E001") { + return res.once( + ctx.status(404), + ctx.json({ + message: "Asset information for https://www.example.com/Instruments#E001 not found", + }) + ); + } + }) + ); + + const { user } = await renderE003ProviderDetails(["E001", "E003"]); + await waitForProvidersToLoad(); + + await toggleProviders(user); + const providers = screen.getAllByRole("listitem"); + expect(providers).toHaveLength(2); + + expect( + within(providers[1]).getByText( + "Failed to retrieve asset information for https://www.example.com/Instruments#E001" + ) + ).toBeInTheDocument(); + expect(providers).toMatchSnapshot("providers with error(s)"); + }); +}); diff --git a/src/components/InfoPanel/SelectedElements/__tests__/ResidentialInformation.test.jsx b/src/components/InfoPanel/SelectedElements/__tests__/ResidentialInformation.test.jsx new file mode 100644 index 0000000..2fb3bcf --- /dev/null +++ b/src/components/InfoPanel/SelectedElements/__tests__/ResidentialInformation.test.jsx @@ -0,0 +1,220 @@ +import { rest } from "msw"; +import { screen, waitForElementToBeRemoved, within } from "@testing-library/react"; + +import { renderWithQueryClient } from "test-utils"; +import { server } from "mocks"; +import { createParalogEndpoint } from "api/combined"; +import { V013_RESIDENCES } from "mocks/resolvers/person-residences"; + +import ResidentialInformation from "../ResidentialInformation"; + +const waitForResidencesToLoad = async () => { + await waitForElementToBeRemoved(() => screen.queryByText("Fetching residential addresses")); +}; + +describe("Residential information component", () => { + test("does NOT render when element is not an asset", () => { + const { container } = renderWithQueryClient(); + expect(container).toBeEmptyDOMElement(); + }); + + test("does NOT render when primaryType is not defined", () => { + const { container } = renderWithQueryClient( + + ); + expect(container).toBeEmptyDOMElement(); + }); + + test("does NOT render when uri is not defined", () => { + const { container } = renderWithQueryClient( + + ); + expect(container).toBeEmptyDOMElement(); + }); + + test("does NOT render when primaryType is not person", () => { + const { container } = renderWithQueryClient( + + ); + expect(container).toBeEmptyDOMElement(); + }); + + test("renders residences address", async () => { + renderWithQueryClient( + + ); + + expect( + screen.getByRole("heading", { name: "Residential Information", level: 3 }) + ).toBeInTheDocument(); + await waitForResidencesToLoad(); + + const addresses = screen.getAllByRole("listitem"); + expect(addresses).toHaveLength(1); + expect(within(addresses[0]).getByText("Address 1")).toBeInTheDocument(); + expect( + within(addresses[0]).getByText("1 Daft Rd, Saltdean, BN51") + ).toBeInTheDocument(); + }); + + test("limits addresses displayed", async () => { + server.use( + rest.get(createParalogEndpoint("person/residences"), (req, res, ctx) => { + const personUri = req.url.searchParams.get("personUri"); + if (personUri === "https://www.example.com/Instruments%23V013") { + return res.once( + ctx.status(200), + ctx.json([ + ...V013_RESIDENCES, + { + uri: "https://www.example.com/Instruments#RT01", + assetType: "http://ies.example.com/ontology/ies#ResidentialBuilding", + address: "1 Telicent Rd, Freshwater, TO01 ABC", + }, + { + uri: "https://www.example.com/Instruments#RT02", + assetType: "http://ies.example.com/ontology/ies#ResidentialBuilding", + address: "2 Telicent Rd, Freshwater, T002 DEF", + }, + { + uri: "https://www.example.com/Instruments#RT03", + assetType: "http://ies.example.com/ontology/ies#ResidentialBuilding", + address: "3 Telicent Rd, Freshwater, T003 GHI", + }, + ]) + ); + } + }) + ); + const { user } = renderWithQueryClient( + + ); + expect( + screen.getByRole("heading", { name: "Residential Information", level: 3 }) + ).toBeInTheDocument(); + await waitForResidencesToLoad(); + + expect(screen.getByText("4 addresses found")).toBeInTheDocument(); + const showAllAddressesBtn = screen.getByRole("button", { name: "show all addresses" }); + expect(showAllAddressesBtn).toBeInTheDocument(); + + let addresses = screen.getAllByRole("listitem"); + expect(addresses).toHaveLength(3); + + expect(within(addresses[0]).getByText("Address 1")).toBeInTheDocument(); + expect( + within(addresses[0]).getByText("1 Daft Rd, Saltdean, BN51") + ).toBeInTheDocument(); + + expect(within(addresses[1]).getByText("Address 2")).toBeInTheDocument(); + expect( + within(addresses[1]).getByText("1 Telicent Rd, Freshwater, TO01 ABC") + ).toBeInTheDocument(); + + expect(within(addresses[2]).getByText("Address 3")).toBeInTheDocument(); + expect( + within(addresses[2]).getByText("2 Telicent Rd, Freshwater, T002 DEF") + ).toBeInTheDocument(); + + // show all addresses + await user.click(showAllAddressesBtn); + + addresses = screen.getAllByRole("listitem"); + expect(addresses).toHaveLength(4); + + expect(within(addresses[3]).getByText("Address 4")).toBeInTheDocument(); + expect( + within(addresses[3]).getByText("3 Telicent Rd, Freshwater, T003 GHI") + ).toBeInTheDocument(); + + // show fewer addresses + await user.click(screen.getByRole("button", { name: "show fewer addresses" })); + addresses = screen.getAllByRole("listitem"); + expect(addresses).toHaveLength(3); + }); + + test("renders error message when addresses cannot be found", async () => { + renderWithQueryClient( + + ); + + expect( + screen.getByRole("heading", { name: "Residential Information", level: 3 }) + ).toBeInTheDocument(); + await waitForResidencesToLoad(); + + expect( + screen.getByText("An error occurred while retrieving residential information") + ).toBeInTheDocument(); + }); + + // Adding this test because currently the api does not return a 404 when an address cannot be found + test("renders message when addresses are not found", async () => { + server.use( + rest.get(createParalogEndpoint("person/residences"), (req, res, ctx) => { + const personUri = req.url.searchParams.get("personUri"); + if (personUri === "https://www.example.com/Instruments%23V013") { + return res.once(ctx.status(200), ctx.json([])); + } + }) + ); + renderWithQueryClient( + + ); + expect( + screen.getByRole("heading", { name: "Residential Information", level: 3 }) + ).toBeInTheDocument(); + await waitForResidencesToLoad(); + + expect(screen.getByText("Residential information not found")).toBeInTheDocument(); + }); + + test("renders uri when address key is not in data", async () => { + const data = { ...V013_RESIDENCES[0] }; + delete data.address; + server.use( + rest.get(createParalogEndpoint("person/residences"), (req, res, ctx) => { + const personUri = req.url.searchParams.get("personUri"); + if (personUri === "https://www.example.com/Instruments%23V013") { + return res.once(ctx.status(200), ctx.json([data])); + } + }) + ); + + renderWithQueryClient( + + ); + expect( + screen.getByRole("heading", { name: "Residential Information", level: 3 }) + ).toBeInTheDocument(); + await waitForResidencesToLoad(); + + let addresses = screen.getAllByRole("listitem"); + expect(addresses).toHaveLength(1); + + expect(within(addresses[0]).getByText("Address 1")).toBeInTheDocument(); + expect( + within(addresses[0]).getByText("https://www.example.com/Instruments#R013") + ).toBeInTheDocument(); + }); +}); diff --git a/src/components/InfoPanel/SelectedElements/__tests__/Residents.test.jsx b/src/components/InfoPanel/SelectedElements/__tests__/Residents.test.jsx new file mode 100644 index 0000000..88340fc --- /dev/null +++ b/src/components/InfoPanel/SelectedElements/__tests__/Residents.test.jsx @@ -0,0 +1,175 @@ +import { screen, waitForElementToBeRemoved, within } from "@testing-library/react"; +import { rest } from "msw"; + +import { server } from "mocks"; +import { createParalogEndpoint } from "api/combined"; +import { renderWithQueryClient } from "test-utils"; +import { R013_RESIDENTS } from "mocks/resolvers/asset/residents"; +import { mockEmptyResponse } from "mocks/resolvers"; + +import Residents from "../Residents"; + +const waitForResidentsToLoad = async () => { + await waitForElementToBeRemoved(() => screen.queryByText("Fetching residents information")); +}; + +describe("Residents component", () => { + test("does NOT render residents when elements is not an asset", () => { + renderWithQueryClient( + + ); + expect(document.querySelector("body").firstElementChild).toBeEmptyDOMElement(); + }); + + test("does NOT render residents when primaryType is undefined", () => { + renderWithQueryClient(); + expect(document.querySelector("body").firstElementChild).toBeEmptyDOMElement(); + }); + + test("does NOT render residents when uri is undefined", () => { + renderWithQueryClient(); + expect(document.querySelector("body").firstElementChild).toBeEmptyDOMElement(); + }); + + test("does NOT render residents when primary type has no residents", () => { + renderWithQueryClient(); + expect(document.querySelector("body").firstElementChild).toBeEmptyDOMElement(); + }); + + test("can be toggled", async () => { + const { user } = renderWithQueryClient( + + ); + await waitForResidentsToLoad(); + + expect(screen.queryByRole("list")).not.toBeInTheDocument(); + await user.click(screen.getByRole("button", { name: "1 resident" })); + expect(screen.getByRole("list")).toBeInTheDocument(); + + await user.click(screen.getByRole("button", { name: "1 resident" })); + expect(screen.queryByRole("list")).not.toBeInTheDocument(); + }); + + test("renders residents", async () => { + const { user } = renderWithQueryClient( + + ); + await waitForResidentsToLoad(); + + expect(screen.getByRole("heading", { name: "1 resident", level: 3 })).toBeInTheDocument(); + await user.click(screen.getByRole("button", { name: "1 resident" })); + + const residents = screen.getAllByRole("listitem"); + expect(residents).toHaveLength(1); + + expect(within(residents[0]).getByText("Mrs Martha Clark")).toBeInTheDocument(); + }); + + test("renders more than one resident", async () => { + server.use( + rest.get(createParalogEndpoint("asset/residents"), (req, res, ctx) => { + const assetUri = req.url.searchParams.get("assetUri"); + if (assetUri === "https://www.example.com/Instruments#R013") { + return res.once( + ctx.status(200), + ctx.json([ + ...R013_RESIDENTS, + { + uri: "https://www.wow.gov.uk/Testing#V003", + name: "Mr Charles Berry", + }, + ]) + ); + } + }) + ); + + const { user } = renderWithQueryClient( + + ); + await waitForResidentsToLoad(); + + expect(screen.getByRole("heading", { name: "2 residents", level: 3 })).toBeInTheDocument(); + await user.click(screen.getByRole("button", { name: "2 residents" })); + + const residents = screen.getAllByRole("listitem"); + expect(residents).toHaveLength(2); + + expect(within(residents[0]).getByText("Mrs Martha Clark")).toBeInTheDocument(); + expect(within(residents[1]).getByText("Mr Charles Berry")).toBeInTheDocument(); + }); + + test("renders error message when resident(s) are not found", async () => { + renderWithQueryClient( + + ); + await waitForResidentsToLoad(); + expect( + screen.getByText("Failed to retrieve residents for https://www.wow.gov.uk/Testing#R013") + ).toBeInTheDocument(); + }); + + // Adding this test because currently the api does not return a 404 when an address cannot be found + test("does NOT render residents when none are found", async () => { + server.use(rest.get(createParalogEndpoint("asset/residents"), mockEmptyResponse)); + renderWithQueryClient( + + ); + await waitForResidentsToLoad(); + expect(document.querySelector("body").firstElementChild).toBeEmptyDOMElement(); + }); + + test("renders uri resident when name is not in data", async () => { + const data = { ...R013_RESIDENTS[0] }; + delete data.name; + server.use( + rest.get(createParalogEndpoint("asset/residents"), (req, res, ctx) => { + const assetUri = req.url.searchParams.get("assetUri"); + if (assetUri === "https://www.example.com/Instruments#R013") { + return res.once(ctx.status(200), ctx.json([data])); + } + }) + ); + + const { user } = renderWithQueryClient( + + ); + await waitForResidentsToLoad(); + await user.click(screen.getByRole("button", { name: "1 resident" })); + + const residents = screen.getAllByRole("listitem"); + expect(residents).toHaveLength(1); + + expect( + within(residents[0]).getByText("https://www.example.com/Instruments#V013") + ).toBeInTheDocument(); + }); +}); diff --git a/src/components/InfoPanel/SelectedElements/__tests__/SelectedElements.test.jsx b/src/components/InfoPanel/SelectedElements/__tests__/SelectedElements.test.jsx new file mode 100644 index 0000000..21bdcca --- /dev/null +++ b/src/components/InfoPanel/SelectedElements/__tests__/SelectedElements.test.jsx @@ -0,0 +1,181 @@ +import React from "react"; +import { screen, waitForElementToBeRemoved } from "@testing-library/react"; + +import { ElementsProvider } from "context"; +import { + LARGE_WIND_FARMS_AND_COAL_PLANT_COMPLEX_DEPENDENCIES, + LARGE_WIND_FARM_ASSETS, + COAL_PLANT_COMPLEX_ASSETS, +} from "mocks"; +import { + DSProvidersWrapper, + getCreatedAssets, + getCreatedDependencies, + renderWithQueryClient, +} from "test-utils"; + +import SelectedElements from "../SelectedElements"; + +const renderSelectedDetails = (selected) => + renderWithQueryClient( + + + , + { + wrapper: ElementsProvider, + } + ); + +const renderSelectedElementsList = async () => { + const selectedAssets = await getCreatedAssets( + [ + ...LARGE_WIND_FARM_ASSETS, + ...COAL_PLANT_COMPLEX_ASSETS, + ], + ["E001", "E003"], + jest.fn().mockReturnValue({ + backgroundColor: "#272727", + color: "#F2F2F2", + iconFallbackText: "D", + alt: "default", + }) + ); + const selectedDependencies = getCreatedDependencies( + LARGE_WIND_FARMS_AND_COAL_PLANT_COMPLEX_DEPENDENCIES, + ["E001 - E003"] + ); + return renderSelectedDetails([...selectedAssets, ...selectedDependencies]); +}; + +const waitForElementDetailsToLoad = async () => { + await waitForElementToBeRemoved(() => screen.queryAllByText("Fetching element details")); +}; + +describe("Selected Elements component", () => { + test("does NOT render component when selected elements are not an array", () => { + const { container } = renderSelectedDetails({}); + expect(container).toBeEmptyDOMElement(); + }); + + test("renders message when no elements are selected", () => { + renderSelectedDetails([]); + + expect( + screen.getByText(/click on an asset or connection to view details/i) + ).toBeInTheDocument(); + }); + + test("does NOT render total selected when elements aren't selected", async () => { + renderSelectedDetails([]); + expect(screen.queryByTestId("selected-badge")).not.toBeInTheDocument(); + }); + + test("renders total count of selected elements when panel in open", async () => { + await renderSelectedElementsList(); + + const selectedBadge = screen.getByTestId("selected-badge"); + expect(selectedBadge).toHaveTextContent("3"); + }); + + test("renders total count when element is selected", async () => { + const { user } = await renderSelectedElementsList(); + await waitForElementDetailsToLoad(); + await user.click(screen.getByRole("button", { name: "Best Coleman Power Station" })); + + const selectedBadge = screen.getByTestId("selected-badge"); + expect(selectedBadge).toHaveTextContent("3"); + }); + + test("renders a list of selected element details", async () => { + await renderSelectedElementsList(); + + expect( + screen.getByRole("heading", { name: "Selected Elements", level: 2 }) + ).toBeInTheDocument(); + + await waitForElementDetailsToLoad(); + expect( + screen.getByRole("heading", { name: "Best Coleman Power Station", level: 2 }) + ).toBeInTheDocument(); + expect( + screen.getByRole("heading", { name: "West Coleman 50kV Substation", level: 2 }) + ).toBeInTheDocument(); + expect( + screen.getByRole("heading", { + name: "Best Coleman Power Station - West Coleman 50kV Substation", + level: 2, + }) + ).toBeInTheDocument(); + expect(screen.queryAllByTestId("element-details")).toHaveLength(0); + expect(screen.getByRole("list")).toMatchSnapshot("selected elements"); + }); + + test("renders element details when a list item is clicked", async () => { + const { user } = await renderSelectedElementsList(); + + await waitForElementDetailsToLoad(); + await user.click(screen.getByRole("button", { name: "Best Coleman Power Station" })); + expect(screen.getByTestId("element-details")).toBeInTheDocument(); + }); + + test("renders all selected elements by click on back arrow", async () => { + const { user } = await renderSelectedElementsList(); + + await waitForElementDetailsToLoad(); + await user.click(screen.getByRole("button", { name: "Best Coleman Power Station" })); + expect(screen.getByTestId("element-details")).toBeInTheDocument(); + + await user.click(screen.getByRole("button", { name: "view all selected" })); + expect(screen.getAllByRole("listitem")).toHaveLength(3); + + await user.click( + screen.getByRole("button", { + name: "Best Coleman Power Station - West Coleman 50kV Substation", + }) + ); + expect(screen.getByTestId("element-details")).toBeInTheDocument(); + }); + + test("renders open street view link when element has lat lng", async () => { + const { user } = await renderSelectedElementsList(); + await waitForElementDetailsToLoad(); + + await user.click(screen.getByRole("button", { name: "Best Coleman Power Station" })); + expect(screen.getByTestId("element-details")).toBeInTheDocument(); + expect(screen.getByRole("link", { name: /open street view/i })).toHaveAttribute( + "href", + "https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=100.123123%2C10.1233333" + ); + }); + + test("does NOT render street view link when element has no lat lng", async () => { + const { user } = await renderSelectedElementsList(); + await waitForElementDetailsToLoad(); + + await user.click( + screen.getByRole("button", { + name: "Best Coleman Power Station - West Coleman 50kV Substation", + }) + ); + expect(screen.getByTestId("element-details")).toBeInTheDocument(); + expect(screen.queryByRole("link", { name: /open street view/i })).not.toBeInTheDocument(); + }); + + test("renders element details when one element is selected", async () => { + const selectedAssets = await getCreatedAssets( + COAL_PLANT_COMPLEX_ASSETS, + ["E001"], + jest.fn().mockReturnValue({ + backgroundColor: "#272727", + color: "#F2F2F2", + iconFallbackText: "D", + alt: "default", + }) + ); + + renderSelectedDetails(selectedAssets); + await waitForElementDetailsToLoad(); + + expect(screen.getByTestId("element-details")).toBeInTheDocument(); + }); +}); diff --git a/src/components/InfoPanel/SelectedElements/__tests__/__snapshots__/Dependents.test.jsx.snap b/src/components/InfoPanel/SelectedElements/__tests__/__snapshots__/Dependents.test.jsx.snap new file mode 100644 index 0000000..3a8b690 --- /dev/null +++ b/src/components/InfoPanel/SelectedElements/__tests__/__snapshots__/Dependents.test.jsx.snap @@ -0,0 +1,324 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Dependents component can toggle dependents assets: dependents list 1`] = ` +Array [ +
  • +
    +
    + +
    +
    +

    + Jose 20kv Substation +

    +

    + small wind farm +

    +

    + E008 +

    +
    +
    +

    + Criticality: + 6 +

    +

    + Connection Strength: + 3 +

    +
  • , +
  • +
    +
    + +
    +
    +

    + West Coleman 50kV Substation +

    +

    + small wind farm +

    +

    + E002 +

    +
    +
    +

    + Criticality: + 8 +

    +

    + Connection Strength: + 3 +

    +
  • , +
  • +
    +
    + +
    +
    +

    + Bluey 10kV Substation +

    +

    + small wind farm +

    +

    + E012 +

    +
    +
    +

    + Criticality: + 10 +

    +

    + Connection Strength: + 3 +

    +
  • , +
  • +
    +
    + +
    +
    +

    + Best Coleman Power Station +

    +

    + coal plant complex +

    +

    + E001 +

    +
    +
    +

    + Criticality: + 2 +

    +

    + Connection Strength: + 3 +

    +
  • , +] +`; + +exports[`Dependents component renders error message when one or more dependents returns an error: dependents with error(s) 1`] = ` +Array [ +
  • +
    +
    + +
    +
    +

    + Jose 20kv Substation +

    +

    + small wind farm +

    +

    + E008 +

    +
    +
    +

    + Criticality: + 6 +

    +

    + Connection Strength: + 3 +

    +
  • , +
  • +
    +
    + +
    +
    +

    + West Coleman 50kV Substation +

    +

    + small wind farm +

    +

    + E002 +

    +
    +
    +

    + Criticality: + 8 +

    +

    + Connection Strength: + 3 +

    +
  • , +
  • +
    +
    + +
    +
    +

    + Bluey 10kV Substation +

    +

    + small wind farm +

    +

    + E012 +

    +
    +
    +

    + Criticality: + 10 +

    +

    + Connection Strength: + 3 +

    +
  • , +
  • + Failed to retrieve asset information for https://www.example.com/Instruments#E001 +
  • , +] +`; diff --git a/src/components/InfoPanel/SelectedElements/__tests__/__snapshots__/Providers.test.jsx.snap b/src/components/InfoPanel/SelectedElements/__tests__/__snapshots__/Providers.test.jsx.snap new file mode 100644 index 0000000..8c719d5 --- /dev/null +++ b/src/components/InfoPanel/SelectedElements/__tests__/__snapshots__/Providers.test.jsx.snap @@ -0,0 +1,148 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Providers component can toggle providers assets: providers list 1`] = ` +Array [ +
  • +
    +
    + +
    +
    +

    + Hawk 123 kV Substation - Hands +

    +

    + large wind farm +

    +

    + E025 +

    +
    +
    +

    + Criticality: + 14 +

    +

    + Connection Strength: + 3 +

    +
  • , +
  • +
    +
    + +
    +
    +

    + Best Coleman Power Station +

    +

    + coal plant complex +

    +

    + E001 +

    +
    +
    +

    + Criticality: + 2 +

    +

    + Connection Strength: + 3 +

    +
  • , +] +`; + +exports[`Providers component renders error message when one or more providers returns an error: providers with error(s) 1`] = ` +Array [ +
  • +
    +
    + +
    +
    +

    + Hawk 123 kV Substation - Hands +

    +

    + large wind farm +

    +

    + E025 +

    +
    +
    +

    + Criticality: + 14 +

    +

    + Connection Strength: + 3 +

    +
  • , +
  • + Failed to retrieve asset information for https://www.example.com/Instruments#E001 +
  • , +] +`; diff --git a/src/components/InfoPanel/SelectedElements/__tests__/__snapshots__/SelectedElements.test.jsx.snap b/src/components/InfoPanel/SelectedElements/__tests__/__snapshots__/SelectedElements.test.jsx.snap new file mode 100644 index 0000000..6e4bdb2 --- /dev/null +++ b/src/components/InfoPanel/SelectedElements/__tests__/__snapshots__/SelectedElements.test.jsx.snap @@ -0,0 +1,122 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Selected Elements component renders a list of selected element details: selected elements 1`] = ` +
      +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    +`; diff --git a/src/components/InfoPanel/__tests__/InfoPanel.test.jsx b/src/components/InfoPanel/__tests__/InfoPanel.test.jsx new file mode 100644 index 0000000..e5f9072 --- /dev/null +++ b/src/components/InfoPanel/__tests__/InfoPanel.test.jsx @@ -0,0 +1,50 @@ +import React from "react"; +import { screen } from "@testing-library/react"; + +import { ElementsContext, ElementsProvider } from "context"; +import { getCreatedAssets, renderWithQueryClient } from "test-utils"; +import { + LARGE_WIND_FARM_ASSETS, + COAL_PLANT_COMPLEX_ASSETS, +} from "mocks"; + +import InfoPanel from "../InfoPanel"; + +describe("Information panel component", () => { + test("is closed by default", () => { + renderWithQueryClient(, { wrapper: ElementsProvider }); + + expect(screen.getByRole("button", { name: /open information panel/i })).toBeInTheDocument(); + expect(screen.queryByRole("heading", { name: "Information" })).not.toBeInTheDocument(); + }); + + test("opens and closes", async () => { + const { user } = renderWithQueryClient(, { wrapper: ElementsProvider }); + + await user.click(screen.getByRole("button", { name: /open information panel/i })); + expect(screen.getByRole("button", { name: /close information panel/i })).toBeInTheDocument(); + expect(screen.getByRole("heading", { name: "Information" })).toBeInTheDocument(); + + await user.click(screen.getByRole("button", { name: "Close information panel" })); + expect(screen.getByRole("button", { name: /open information panel/i })).toBeInTheDocument(); + expect(screen.queryByRole("heading", { name: "Information" })).not.toBeInTheDocument(); + }); + + test("renders total count of selected elements when panel in closed", async () => { + const assets = await getCreatedAssets( + [ + ...LARGE_WIND_FARM_ASSETS, + ...COAL_PLANT_COMPLEX_ASSETS, + ], + ["E001", "E003"] + ); + renderWithQueryClient( + + + + ); + + const selectedBadge = screen.getByTestId("selected-badge"); + expect(selectedBadge).toHaveTextContent("2"); + }); +}); diff --git a/src/components/Map/FloodAreaWidget.jsx b/src/components/Map/FloodAreaWidget.jsx index 3112229..471d60b 100644 --- a/src/components/Map/FloodAreaWidget.jsx +++ b/src/components/Map/FloodAreaWidget.jsx @@ -18,10 +18,10 @@ const FloodWarningWidget = () => {