Compare commits

...

3 Commits

Author SHA1 Message Date
Vinícius Lourenço
292a46163d test(dashboards): fix dashboards tests usage of use safe navigate 2026-08-17 15:41:55 -03:00
Vinícius Lourenço
f737bde5d6 fix(query-builder): use getUnstableCurrentSearchParams get fresh query params 2026-08-17 15:17:45 -03:00
Vinícius Lourenço
46c4e8df8d refactor(hooks): move getUnstableCurrentSearchParams to global hooks 2026-08-17 15:17:36 -03:00
13 changed files with 92 additions and 65 deletions

View File

@@ -37,7 +37,7 @@ import { useInfraMonitoringFontSize } from './useInfraMonitoringTablePreferences
import styles from './K8sExpandedRow.module.scss';
import { buildExpressionFromGroupMeta } from './utils';
import { logInfraColumnSortedEvent } from 'container/InfraMonitoringK8sV2/Base/events';
import { getUnstableCurrentSearchParams } from 'container/TopNav/DateTimeSelectionV2/utils/getUnstableCurrentSearchParams';
import { getUnstableCurrentSearchParams } from 'utils/getUnstableCurrentSearchParams';
import { QueryParams } from 'constants/query';
const EXPANDED_ROW_LIMIT = 10;

View File

@@ -10,7 +10,7 @@ import DateTimeSelection from '../index';
import {
__resetSearchParamsGetter,
__setSearchParamsGetterForTest,
} from '../utils/getUnstableCurrentSearchParams';
} from 'utils/getUnstableCurrentSearchParams';
import { queryClient, TestWrapper } from './testUtils';
const mockSafeNavigate = jest.fn();

View File

@@ -10,7 +10,7 @@ import DateTimeSelection from '../index';
import {
__resetSearchParamsGetter,
__setSearchParamsGetterForTest,
} from '../utils/getUnstableCurrentSearchParams';
} from 'utils/getUnstableCurrentSearchParams';
import { queryClient, TestWrapper } from './testUtils';
const mockSafeNavigate = jest.fn();

View File

@@ -24,7 +24,7 @@ import DateTimeSelection from '../index';
import {
__resetSearchParamsGetter,
__setSearchParamsGetterForTest,
} from '../utils/getUnstableCurrentSearchParams';
} from 'utils/getUnstableCurrentSearchParams';
const queryClient = new QueryClient({
defaultOptions: {

View File

@@ -5,7 +5,7 @@ import DateTimeSelection from '../index';
import {
__resetSearchParamsGetter,
__setSearchParamsGetterForTest,
} from '../utils/getUnstableCurrentSearchParams';
} from 'utils/getUnstableCurrentSearchParams';
import { queryClient, TestWrapper } from './testUtils';
const mockSafeNavigate = jest.fn();

View File

@@ -10,7 +10,7 @@ import DateTimeSelection from '../index';
import {
__resetSearchParamsGetter,
__setSearchParamsGetterForTest,
} from '../utils/getUnstableCurrentSearchParams';
} from 'utils/getUnstableCurrentSearchParams';
import { queryClient, TestWrapper, createMockMoment } from './testUtils';
const mockSafeNavigate = jest.fn();

View File

@@ -54,7 +54,7 @@ import {
Time,
TimeRange,
} from './types';
import { getUnstableCurrentSearchParams } from './utils/getUnstableCurrentSearchParams';
import { getUnstableCurrentSearchParams } from 'utils/getUnstableCurrentSearchParams';
import './DateTimeSelectionV2.styles.scss';

View File

@@ -46,23 +46,11 @@ beforeAll(() => {
});
// jest.config maps the real hook to a no-op mock; this suite needs real navigation.
jest.mock('hooks/useSafeNavigate', () => {
const { useHistory } = jest.requireActual('react-router-dom');
return {
useSafeNavigate: (): unknown => {
const history = useHistory();
return {
safeNavigate: (to: string, opts?: { replace?: boolean }): void => {
if (opts?.replace) {
history.replace(to);
} else {
history.push(to);
}
},
};
},
};
});
jest.mock('hooks/useSafeNavigate', () =>
jest
.requireActual('tests/browser-history-safe-navigate')
.createBrowserHistorySafeNavigateMock(),
);
jest.mock('api/querySuggestions/getKeySuggestions', () => ({
getKeySuggestions: jest
@@ -204,9 +192,12 @@ function Harness(): JSX.Element {
);
}
const INITIAL_ROUTE = '/dashboard/dash-1';
const renderHarness = (): void => {
window.history.replaceState(null, '', INITIAL_ROUTE);
render(
<MemoryRouter initialEntries={['/dashboard/dash-1']}>
<MemoryRouter initialEntries={[INITIAL_ROUTE]}>
<CompatRouter>
<QueryClientProvider client={new QueryClient()}>
<ReduxProvider store={configureStore([])(appStore.getState())}>

View File

@@ -16,23 +16,11 @@ import ViewPanelModal from '../ViewPanelModal/ViewPanelModal';
import { useViewPanel } from '../hooks/useViewPanel';
// jest.config maps the real hook to a no-op mock; this suite needs real navigation.
jest.mock('hooks/useSafeNavigate', () => {
const { useHistory } = jest.requireActual('react-router-dom');
return {
useSafeNavigate: (): unknown => {
const history = useHistory();
return {
safeNavigate: (to: string, opts?: { replace?: boolean }): void => {
if (opts?.replace) {
history.replace(to);
} else {
history.push(to);
}
},
};
},
};
});
jest.mock('hooks/useSafeNavigate', () =>
jest
.requireActual('tests/browser-history-safe-navigate')
.createBrowserHistorySafeNavigateMock(),
);
jest.mock(
'pages/DashboardPageV2/DashboardContainer/hooks/usePanelQuery',
@@ -150,9 +138,12 @@ function Harness(): JSX.Element {
);
}
const INITIAL_ROUTE = '/dashboard/dash-1';
const renderHarness = (): void => {
window.history.replaceState(null, '', INITIAL_ROUTE);
render(
<MemoryRouter initialEntries={['/dashboard/dash-1']}>
<MemoryRouter initialEntries={[INITIAL_ROUTE]}>
<CompatRouter>
<QueryClientProvider client={new QueryClient()}>
<ReduxProvider store={configureStore([])(appStore.getState())}>

View File

@@ -14,23 +14,11 @@ import { useViewPanelMode } from '../ViewPanelModal/useViewPanelMode';
import { useViewPanel } from '../hooks/useViewPanel';
// jest.config maps the real hook to a no-op mock; this suite needs real navigation.
jest.mock('hooks/useSafeNavigate', () => {
const { useHistory } = jest.requireActual('react-router-dom');
return {
useSafeNavigate: (): unknown => {
const history = useHistory();
return {
safeNavigate: (to: string, opts?: { replace?: boolean }): void => {
if (opts?.replace) {
history.replace(to);
} else {
history.push(to);
}
},
};
},
};
});
jest.mock('hooks/useSafeNavigate', () =>
jest
.requireActual('tests/browser-history-safe-navigate')
.createBrowserHistorySafeNavigateMock(),
);
jest.mock(
'pages/DashboardPageV2/DashboardContainer/hooks/usePanelQuery',
@@ -184,9 +172,12 @@ function Harness(): JSX.Element {
);
}
const INITIAL_ROUTE = '/dashboard/dash-1';
const renderHarness = (): void => {
window.history.replaceState(null, '', INITIAL_ROUTE);
render(
<MemoryRouter initialEntries={['/dashboard/dash-1']}>
<MemoryRouter initialEntries={[INITIAL_ROUTE]}>
<CompatRouter>
<QueryBuilderProvider>
<Harness />

View File

@@ -37,7 +37,6 @@ import { OptionsQuery } from 'container/OptionsMenu/types';
import { useGetCompositeQueryParam } from 'hooks/queryBuilder/useGetCompositeQueryParam';
import { updateStepInterval } from 'hooks/queryBuilder/useStepInterval';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery';
import { createIdFromObjectFields } from 'lib/createIdFromObjectFields';
import { createNewBuilderItemName } from 'lib/newQueryBuilder/createNewBuilderItemName';
import { getOperatorsBySourceAndPanelType } from 'lib/newQueryBuilder/getOperatorsBySourceAndPanelType';
@@ -66,6 +65,7 @@ import {
} from 'types/common/queryBuilder';
import { sanitizeOrderByForExplorer } from 'utils/sanitizeOrderBy';
import { v4 as uuid } from 'uuid';
import { getUnstableCurrentSearchParams } from 'utils/getUnstableCurrentSearchParams';
export const QueryBuilderContext = createContext<QueryBuilderContextType>({
currentQuery: initialQueriesMap.metrics,
@@ -105,7 +105,6 @@ export const QueryBuilderContext = createContext<QueryBuilderContextType>({
export function QueryBuilderProvider({
children,
}: PropsWithChildren): JSX.Element {
const urlQuery = useUrlQuery();
const location = useLocation();
const currentPathnameRef = useRef<string | null>(location.pathname);
@@ -122,7 +121,7 @@ export function QueryBuilderProvider({
null,
);
const panelTypeQueryParams = urlQuery.get(
const panelTypeQueryParams = getUnstableCurrentSearchParams().get(
QueryParams.panelTypes,
) as PANEL_TYPES | null;
@@ -976,6 +975,7 @@ export function QueryBuilderProvider({
unit: query.unit || initialQueryState.unit,
};
const urlQuery = getUnstableCurrentSearchParams();
const pagination = urlQuery.get(QueryParams.pagination);
if (pagination) {
@@ -1014,7 +1014,7 @@ export function QueryBuilderProvider({
safeNavigate(generatedUrl, { newTab });
},
[location.pathname, safeNavigate, urlQuery],
[location.pathname, safeNavigate],
);
const handleSetConfig = useCallback(

View File

@@ -0,0 +1,54 @@
// Mock factory for suites that need `useSafeNavigate` to navigate for real.
//
// `jest.config.ts` maps every `hooks/useSafeNavigate` import to the no-op
// `__tests__/safeNavigateMock.ts`, so a suite that drives navigation has to opt
// out with its own `jest.mock`.
//
// In production `safeNavigate` goes through `createBrowserHistory`, which writes
// `window.location` as well as notifying the router. `MemoryRouter` never touches
// `window`, so anything reading `getUnstableCurrentSearchParams()` sees an empty
// search and drops the params the test just navigated with. This mock writes both.
//
// The `jest.mock` factory is hoisted above imports, so require it inside:
//
// jest.mock('hooks/useSafeNavigate', () =>
// jest
// .requireActual('tests/browser-history-safe-navigate')
// .createBrowserHistorySafeNavigateMock(),
// );
import type { History } from 'history';
interface SafeNavigateOptions {
replace?: boolean;
}
interface UseSafeNavigateModule {
useSafeNavigate: () => {
safeNavigate: (to: string, options?: SafeNavigateOptions) => void;
};
}
export function createBrowserHistorySafeNavigateMock(): UseSafeNavigateModule {
const { useHistory } = jest.requireActual<{ useHistory: () => History }>(
'react-router-dom',
);
return {
useSafeNavigate: () => {
const history = useHistory();
return {
safeNavigate: (to: string, options?: SafeNavigateOptions): void => {
if (options?.replace) {
window.history.replaceState(null, '', to);
history.replace(to);
} else {
window.history.pushState(null, '', to);
history.push(to);
}
},
};
},
};
}