Fix back-to-host-details button on report details page (#39727) (#45238)

Resolves #39727 

Fixed bug on QueryDetailsPage's backPath() implementation, so the "Back
to host details" button does not followed the stale filteredQueriesPath
set when the user previously visited the reports page.
This commit is contained in:
Juan Fernandez
2026-05-12 14:08:59 -04:00
committed by GitHub
parent 1fb91ab2d5
commit 1dc0ee2ea4
3 changed files with 116 additions and 3 deletions
@@ -0,0 +1,113 @@
import React from "react";
import { screen } from "@testing-library/react";
import { http, HttpResponse } from "msw";
import {
createCustomRenderer,
baseUrl,
createMockRouter,
} from "test/test-utils";
import mockServer from "test/mock-server";
import createMockUser from "__mocks__/userMock";
import createMockConfig from "__mocks__/configMock";
import createMockSchedulableQuery from "__mocks__/scheduleableQueryMock";
import createMockQueryReport from "__mocks__/queryReportMock";
import QueryDetailsPage from "./QueryDetailsPage";
// Render BackButton as a button exposing its `path` prop so we can assert on the
// computed back URL without depending on react-router's browserHistory.
jest.mock("components/BackButton", () => ({
__esModule: true,
default: ({ text, path }: { text: string; path?: string }) => (
<button type="button" data-testid="back-button" data-path={path ?? ""}>
{text}
</button>
),
}));
const QUERY_ID = 1;
const HOST_ID = 42;
const FILTERED_QUERIES_PATH = "/queries/manage?fleet_id=1";
const setupQueryHandlers = () => {
mockServer.use(
http.get(baseUrl(`/reports/${QUERY_ID}`), () =>
HttpResponse.json({
query: createMockSchedulableQuery({ id: QUERY_ID, team_id: null }),
})
),
http.get(baseUrl(`/reports/${QUERY_ID}/report`), () =>
HttpResponse.json(
createMockQueryReport({ query_id: QUERY_ID, results: [] })
)
)
);
};
const createProps = (hostId?: number) => ({
router: createMockRouter(),
params: { id: String(QUERY_ID) },
location: {
pathname: `/reports/${QUERY_ID}`,
search: hostId !== undefined ? `?host_id=${hostId}` : "",
query: hostId !== undefined ? { host_id: String(hostId) } : {},
},
});
const baseAppContext = {
isGlobalAdmin: true,
isOnGlobalTeam: true,
// Free tier short-circuits useTeamIdParam's redirect logic when no fleet_id is set,
// keeping the test focused on backPath() rather than team reconciliation.
isFreeTier: true,
isPremiumTier: false,
currentUser: createMockUser({ global_role: "admin" }),
config: createMockConfig(),
availableTeams: [],
};
const renderPage = (
appOverrides: { filteredQueriesPath?: string } = {},
hostId?: number
) => {
const render = createCustomRenderer({
withBackendMock: true,
context: { app: { ...baseAppContext, ...appOverrides } },
});
render(<QueryDetailsPage {...(createProps(hostId) as any)} />);
return screen.findByTestId("back-button");
};
describe("QueryDetailsPage - back navigation", () => {
beforeEach(() => setupQueryHandlers());
it.each([
{
name: "hostId wins over filteredQueriesPath",
app: { filteredQueriesPath: FILTERED_QUERIES_PATH },
hostId: HOST_ID,
expectText: "Back to host details",
expectPathContains: `/hosts/${HOST_ID}/details`,
},
{
name: "falls back to filteredQueriesPath when no hostId",
app: { filteredQueriesPath: FILTERED_QUERIES_PATH },
hostId: undefined,
expectText: "Back to reports",
expectPathContains: FILTERED_QUERIES_PATH,
},
{
name:
"falls back to manage reports when neither hostId nor filteredQueriesPath is set",
app: {},
hostId: undefined,
expectText: "Back to reports",
expectPathContains: "/reports/manage",
},
])("$name", async ({ app, hostId, expectText, expectPathContains }) => {
const back = await renderPage(app, hostId);
expect(back).toHaveTextContent(expectText);
expect(back.getAttribute("data-path")).toContain(expectPathContains);
});
});
@@ -251,15 +251,14 @@ const QueryDetailsPage = ({
isGlobalTechnician ||
isTeamTechnician;
// Function instead of constant eliminates race condition with filteredQueriesPath
const backPath = () => {
if (filteredQueriesPath) return filteredQueriesPath;
if (hostId)
return getPathWithQueryParams(
PATHS.HOST_DETAILS(hostId, currentTeamId)
);
if (filteredQueriesPath) return filteredQueriesPath;
return getPathWithQueryParams(PATHS.MANAGE_REPORTS, {
fleet_id: currentTeamId,
});