diff --git a/react-app/src/components/Opensearch/main/useOpensearch.ts b/react-app/src/components/Opensearch/main/useOpensearch.ts index 4a0006088b..103050029e 100644 --- a/react-app/src/components/Opensearch/main/useOpensearch.ts +++ b/react-app/src/components/Opensearch/main/useOpensearch.ts @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useEffect, useState, useRef } from "react"; import { useQuery } from "@tanstack/react-query"; import { UserRoles, opensearch } from "shared-types"; import { getOsData, useOsSearch, useGetUser } from "@/api"; @@ -50,8 +50,17 @@ export const useOsData = () => { opensearch.main.Field, opensearch.main.Response >(); + + const [tabLoading, setTabLoading] = useState(false); + const previousTab = useRef(params.state.tab); + const onRequest = async (query: opensearch.main.State, options?: any) => { try { + if (params.state.tab !== previousTab.current) { + setTabLoading(true); + previousTab.current = params.state.tab; + } + await mutateAsync( { index: "main", @@ -63,16 +72,23 @@ export const useOsData = () => { ...(DEFAULT_FILTERS[params.state.tab].filters || []), ], }, - { ...options, onSuccess: (res) => setData(res.hits) }, + { + ...options, + onSuccess: (res) => { + setData(res.hits); + setTabLoading(false); + }, + }, ); } catch (error) { console.error("Error occurred during search:", error); + setTabLoading(false); } }; useEffect(() => { onRequest(params.state); }, [params.queryString]); - return { data, isLoading, error, ...params }; + return { data, isLoading, error, ...params, tabLoading }; }; export const useOsAggregate = () => { const { data: user } = useGetUser(); diff --git a/react-app/src/features/dashboard/index.test.tsx b/react-app/src/features/dashboard/index.test.tsx index 44f4461e32..d2a66acde5 100644 --- a/react-app/src/features/dashboard/index.test.tsx +++ b/react-app/src/features/dashboard/index.test.tsx @@ -1,5 +1,11 @@ import { describe, expect, it, vi, beforeAll, afterAll, beforeEach, afterEach } from "vitest"; -import { screen, within, waitForElementToBeRemoved, cleanup } from "@testing-library/react"; +import { + screen, + within, + waitForElementToBeRemoved, + cleanup, + waitFor, +} from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { renderWithQueryClientAndMemoryRouter, @@ -173,12 +179,13 @@ describe("Dashboard", () => { it("should handle switching to the Waiver tab", async () => { const isWaiver = true; - const waiverTab = screen.queryByRole("heading", { level: 2, name: "Waivers" }); - - await user.click(waiverTab.parentElement); + await waitFor(async () => { + const waiverTab = await screen.findByRole("heading", { level: 2, name: "Waivers" }); + await user.click(waiverTab.parentElement); - expect(waiverTab).toBeInTheDocument(); - expect(waiverTab.parentElement.getAttribute("aria-selected")).toEqual("true"); + expect(waiverTab).toBeInTheDocument(); + expect(waiverTab.parentElement.getAttribute("aria-selected")).toEqual("true"); + }); const spaTab = screen.queryByRole("heading", { level: 2, name: "SPAs" }); expect(spaTab).toBeInTheDocument(); @@ -192,12 +199,13 @@ describe("Dashboard", () => { it("should handle switching back to the SPA tab", async () => { const isWaiver = false; - const spaTab = screen.queryByRole("heading", { level: 2, name: "SPAs" }); - - await user.click(spaTab.parentElement); + await waitFor(async () => { + const spaTab = await screen.findByRole("heading", { level: 2, name: "SPAs" }); + await user.click(spaTab.parentElement); - expect(spaTab).toBeInTheDocument(); - expect(spaTab.parentElement.getAttribute("aria-selected")).toEqual("true"); + expect(spaTab).toBeInTheDocument(); + expect(spaTab.parentElement.getAttribute("aria-selected")).toEqual("true"); + }); const waiverTab = screen.queryByRole("heading", { level: 2, name: "Waivers" }); expect(waiverTab).toBeInTheDocument(); @@ -266,11 +274,13 @@ describe("Dashboard", () => { it("should handle switching to the Waiver tab", async () => { const isWaiver = true; - const waiverTab = screen.queryByRole("heading", { level: 2, name: "Waivers" }); - await user.click(waiverTab.parentElement); + await waitFor(async () => { + const waiverTab = await screen.findByRole("heading", { level: 2, name: "Waivers" }); + await user.click(waiverTab.parentElement); - expect(waiverTab).toBeInTheDocument(); - expect(waiverTab.parentElement.getAttribute("aria-selected")).toEqual("true"); + expect(waiverTab).toBeInTheDocument(); + expect(waiverTab.parentElement.getAttribute("aria-selected")).toEqual("true"); + }); const spaTab = screen.queryByRole("heading", { level: 2, name: "SPAs" }); expect(spaTab).toBeInTheDocument(); @@ -284,11 +294,13 @@ describe("Dashboard", () => { it("should handle switching back to the SPA tab", async () => { const isWaiver = false; - const spaTab = screen.queryByRole("heading", { level: 2, name: "SPAs" }); - await user.click(spaTab.parentElement); + await waitFor(async () => { + const spaTab = screen.queryByRole("heading", { level: 2, name: "SPAs" }); + await user.click(spaTab.parentElement); - expect(spaTab).toBeInTheDocument(); - expect(spaTab.parentElement.getAttribute("aria-selected")).toEqual("true"); + expect(spaTab).toBeInTheDocument(); + expect(spaTab.parentElement.getAttribute("aria-selected")).toEqual("true"); + }); const waiverTab = screen.queryByRole("heading", { level: 2, name: "Waivers" }); expect(waiverTab).toBeInTheDocument(); diff --git a/react-app/src/features/dashboard/index.tsx b/react-app/src/features/dashboard/index.tsx index c3068c0202..5987f76545 100644 --- a/react-app/src/features/dashboard/index.tsx +++ b/react-app/src/features/dashboard/index.tsx @@ -55,7 +55,7 @@ export const Dashboard = () => { ); }; - if (isLoading) { + if (isLoading || osData.tabLoading) { return ; }