[Case Observables] Dont fetch similar cases count without proper license (#207220)

## Summary

There is a bug where we do fetch similar cases count even if the tab
itself is hidden;
this PR solves it. 

Original issue:
https://github.com/elastic/kibana/issues/206976
This commit is contained in:
Luke Gmys 2025-01-22 08:46:27 +01:00 committed by GitHub
parent 52be832724
commit 7a1e6944e8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 51 additions and 7 deletions

View file

@ -22,6 +22,7 @@ import { CaseViewTabs } from './case_view_tabs';
import { caseData, defaultGetCase } from './mocks';
import { useGetCaseFileStats } from '../../containers/use_get_case_file_stats';
import { useCaseObservables } from './use_case_observables';
import * as similarCasesHook from '../../containers/use_get_similar_cases';
jest.mock('../../containers/use_get_case');
jest.mock('../../common/navigation/hooks');
@ -241,6 +242,8 @@ describe('CaseViewTabs', () => {
});
it('should not show observable tabs in non-platinum tiers', async () => {
const spyOnUseGetSimilarCases = jest.spyOn(similarCasesHook, 'useGetSimilarCases');
appMockRenderer = createAppMockRenderer();
appMockRenderer.render(
@ -249,6 +252,11 @@ describe('CaseViewTabs', () => {
expect(screen.queryByTestId('case-view-tab-title-observables')).not.toBeInTheDocument();
expect(screen.queryByTestId('case-view-tab-title-similar_cases')).not.toBeInTheDocument();
// NOTE: we are still calling the hook but the fetching is disabled (based on the license)
expect(spyOnUseGetSimilarCases).toHaveBeenLastCalledWith(
expect.objectContaining({ enabled: false })
);
});
describe('show observable tabs in platinum tier or higher', () => {
@ -259,6 +267,19 @@ describe('CaseViewTabs', () => {
appMockRenderer = createAppMockRenderer({ license });
});
it('should show observable tabs in platinum+ tiers', async () => {
const spyOnUseGetSimilarCases = jest.spyOn(similarCasesHook, 'useGetSimilarCases');
appMockRenderer.render(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.OBSERVABLES} />
);
// NOTE: ensure we are calling the hook but the fetching is enabled (based on the license)
expect(spyOnUseGetSimilarCases).toHaveBeenLastCalledWith(
expect.objectContaining({ enabled: true })
);
});
it('should show the observables tab', async () => {
appMockRenderer.render(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.OBSERVABLES} />

View file

@ -166,12 +166,14 @@ export const CaseViewTabs = React.memo<CaseViewTabsProps>(({ caseData, activeTab
});
const { observables, isLoading: isLoadingObservables } = useCaseObservables(caseData);
const { observablesAuthorized: canShowObservableTabs } = useCasesFeatures();
const { data: similarCasesData } = useGetSimilarCases({
caseId: caseData.id,
perPage: 0,
page: 0,
enabled: canShowObservableTabs,
});
const { observablesAuthorized: canShowObservableTabs } = useCasesFeatures();
const tabs = useMemo(
() => [

View file

@ -28,6 +28,7 @@ export const CaseViewSimilarCases = ({ caseData }: CaseViewSimilarCasesProps) =>
caseId: caseData.id,
page: pageIndex + 1,
perPage: pageSize,
enabled: true,
});
const tableOnChangeCallback = useCallback(({ page, sort }: EuiBasicTableOnChange) => {

View file

@ -30,9 +30,12 @@ describe('useGetSimilarCases', () => {
it('calls getSimilarCases with correct arguments', async () => {
const spyOnGetCases = jest.spyOn(api, 'getSimilarCases');
renderHook(() => useGetSimilarCases({ caseId: mockCase.id, perPage: 10, page: 0 }), {
wrapper: appMockRender.AppWrapper,
});
renderHook(
() => useGetSimilarCases({ caseId: mockCase.id, perPage: 10, page: 0, enabled: true }),
{
wrapper: appMockRender.AppWrapper,
}
);
await waitFor(() => {
expect(spyOnGetCases).toBeCalled();
@ -46,6 +49,18 @@ describe('useGetSimilarCases', () => {
});
});
it('calls does not call getSimilarCases when enabled=false', async () => {
const spyOnGetCases = jest.spyOn(api, 'getSimilarCases');
renderHook(
() => useGetSimilarCases({ caseId: mockCase.id, perPage: 10, page: 0, enabled: false }),
{
wrapper: appMockRender.AppWrapper,
}
);
expect(spyOnGetCases).not.toBeCalled();
});
it('shows a toast error message when an error occurs in the response', async () => {
const spyOnGetCases = jest.spyOn(api, 'getSimilarCases');
spyOnGetCases.mockImplementation(() => {
@ -55,9 +70,12 @@ describe('useGetSimilarCases', () => {
const addError = jest.fn();
(useToasts as jest.Mock).mockReturnValue({ addSuccess, addError });
renderHook(() => useGetSimilarCases({ caseId: mockCase.id, perPage: 10, page: 0 }), {
wrapper: appMockRender.AppWrapper,
});
renderHook(
() => useGetSimilarCases({ caseId: mockCase.id, perPage: 10, page: 0, enabled: true }),
{
wrapper: appMockRender.AppWrapper,
}
);
await waitFor(() => {
expect(addError).toHaveBeenCalled();

View file

@ -25,6 +25,7 @@ export const useGetSimilarCases = (params: {
caseId: string;
perPage: number;
page: number;
enabled: boolean;
}): UseQueryResult<CasesSimilarResponseUI> => {
const toasts = useToasts();
@ -39,6 +40,7 @@ export const useGetSimilarCases = (params: {
});
},
{
enabled: params.enabled,
keepPreviousData: true,
onError: (error: ServerError) => {
if (error.name !== 'AbortError') {