Skip to content

Commit

Permalink
[React18] Migrated test suites to accommodate changes to testing libr…
Browse files Browse the repository at this point in the history
…ary owned by security-solution
  • Loading branch information
eokoneyo committed Dec 17, 2024
1 parent 1b52848 commit 5747fce
Show file tree
Hide file tree
Showing 93 changed files with 670 additions and 820 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { renderHook } from '@testing-library/react-hooks';
import { renderHook } from '@testing-library/react';
import { usePanelSideNavItems } from './use_panel_side_nav_items';
import { SecurityPageName } from '@kbn/security-solution-navigation';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,10 @@
* 2.0.
*/

import { renderHook } from '@testing-library/react-hooks';
import { renderHook } from '@testing-library/react';

import { mockQuery, mockAlertCountByRuleResult, parsedAlertCountByRuleResult } from './mock_data';
import type {
UseAlertCountByRuleByStatus,
UseAlertCountByRuleByStatusProps,
} from './use_alert_count_by_rule_by_status';
import type { UseAlertCountByRuleByStatusProps } from './use_alert_count_by_rule_by_status';
import { useAlertCountByRuleByStatus } from './use_alert_count_by_rule_by_status';

const dateNow = new Date('2022-04-15T12:00:00.000Z').valueOf();
Expand Down Expand Up @@ -53,7 +50,7 @@ jest.mock('../../../detections/containers/detection_engine/alerts/use_signal_ind
const renderUseAlertCountByRuleByStatus = (
overrides: Partial<UseAlertCountByRuleByStatusProps> = {}
) =>
renderHook<UseAlertCountByRuleByStatusProps, ReturnType<UseAlertCountByRuleByStatus>>(() =>
renderHook(() =>
useAlertCountByRuleByStatus({
skip: false,
field: 'test_field',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { renderHook } from '@testing-library/react-hooks';
import { renderHook } from '@testing-library/react';
import React from 'react';

import { TestProviders } from '../../../../mock';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { createSearchSourceMock } from '@kbn/data-plugin/public/mocks';
import { discoverPluginMock } from '@kbn/discover-plugin/public/mocks';
import { dataViewMock } from '@kbn/discover-utils/src/__mocks__';
import type { SavedSearch } from '@kbn/saved-search-plugin/common';
import { renderHook } from '@testing-library/react-hooks';
import { waitFor, act, renderHook } from '@testing-library/react';
import { createMockStore, mockGlobalState, TestProviders } from '../../mock';
import { useDiscoverInTimelineActions } from './use_discover_in_timeline_actions';
import type { Filter } from '@kbn/es-query';
Expand All @@ -20,9 +20,6 @@ import * as timelineActions from '../../../timelines/store/actions';
import type { ComponentType, FC, PropsWithChildren } from 'react';
import React from 'react';
import type { DataView } from '@kbn/data-views-plugin/common';
import TestRenderer from 'react-test-renderer';

const { act } = TestRenderer;

let mockDiscoverStateContainerRef = {
current: discoverPluginMock.getDiscoverStateMock({}),
Expand Down Expand Up @@ -148,7 +145,7 @@ describe('useDiscoverInTimelineActions', () => {
});
describe('getAppStateFromSavedSearch', () => {
it('should reach out to discover to convert app state from saved search', async () => {
const { result, waitFor } = renderTestHook();
const { result } = renderTestHook();
const { appState } = result.current.getAppStateFromSavedSearch(savedSearchMock);
await waitFor(() => {
expect(appState).toMatchObject(
Expand Down Expand Up @@ -178,15 +175,15 @@ describe('useDiscoverInTimelineActions', () => {

describe('resetDiscoverAppState', () => {
it('should reset Discover AppState to a default state', async () => {
const { result, waitFor } = renderTestHook();
const { result } = renderTestHook();
await result.current.resetDiscoverAppState();
await waitFor(() => {
const appState = mockDiscoverStateContainerRef.current.appState.getState();
expect(appState).toMatchObject(result.current.defaultDiscoverAppState);
});
});
it('should reset Discover time to a default state', async () => {
const { result, waitFor } = renderTestHook();
const { result } = renderTestHook();
await result.current.resetDiscoverAppState();
await waitFor(() => {
const globalState = mockDiscoverStateContainerRef.current.globalState.get();
Expand All @@ -197,6 +194,15 @@ describe('useDiscoverInTimelineActions', () => {
describe('updateSavedSearch', () => {
it('should add defaults to the savedSearch before updating saved search', async () => {
const { result } = renderTestHook();

await waitFor(() =>
expect(result.current).toEqual(
expect.objectContaining({
updateSavedSearch: expect.any(Function),
})
)
);

await act(async () => {
await result.current.updateSavedSearch(savedSearchMock, TimelineId.active);
});
Expand All @@ -216,6 +222,7 @@ describe('useDiscoverInTimelineActions', () => {
})
);
});

it('should initialize saved search when it is not set on the timeline model yet', async () => {
const localMockState: State = {
...mockGlobalState,
Expand All @@ -235,6 +242,13 @@ describe('useDiscoverInTimelineActions', () => {

const LocalTestProvider = getTestProviderWithCustomState(localMockState);
const { result } = renderTestHook(LocalTestProvider);
await waitFor(() =>
expect(result.current).toEqual(
expect.objectContaining({
updateSavedSearch: expect.any(Function),
})
)
);
await act(async () => {
await result.current.updateSavedSearch(savedSearchMock, TimelineId.active);
});
Expand Down Expand Up @@ -269,6 +283,13 @@ describe('useDiscoverInTimelineActions', () => {

const LocalTestProvider = getTestProviderWithCustomState(localMockState);
const { result } = renderTestHook(LocalTestProvider);
await waitFor(() =>
expect(result.current).toEqual(
expect.objectContaining({
updateSavedSearch: expect.any(Function),
})
)
);
await act(async () => {
await result.current.updateSavedSearch(changedSavedSearchMock, TimelineId.active);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { act, renderHook } from '@testing-library/react-hooks';
import { renderHook, act } from '@testing-library/react';

import { APP_ID } from '../../../../common/constants';
import { DEFAULT_STACK_BY_FIELD } from '../../../detections/components/alerts_kpis/common/config';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { act, renderHook } from '@testing-library/react-hooks';

import { act, waitFor, renderHook } from '@testing-library/react';
import { TestProviders } from '../../../mock';
import { useAggregatedAnomaliesByJob, AnomalyEntity } from './use_anomalies_search';

Expand Down Expand Up @@ -70,37 +71,29 @@ describe('useAggregatedAnomaliesByJob', () => {
});

it('refetch calls useSecurityJobs().refetch', async () => {
await act(async () => {
const { result, waitForNextUpdate } = renderHook(
() => useAggregatedAnomaliesByJob({ skip: false, from, to }),
{
wrapper: TestProviders,
}
);
const { result } = renderHook(() => useAggregatedAnomaliesByJob({ skip: false, from, to }), {
wrapper: TestProviders,
});

await waitForNextUpdate();
await waitFor(() => new Promise((resolve) => resolve(null)));

act(() => {
result.current.refetch();
});

expect(useSecurityJobsRefetch).toHaveBeenCalled();
});

it('returns formated data', async () => {
await act(async () => {
const jobCount = { key: jobId, doc_count: 99 };
mockAnomaliesSearch.mockResolvedValue({
aggregations: { number_of_anomalies: { buckets: [jobCount] } },
});
const { result, waitForNextUpdate } = renderHook(
() => useAggregatedAnomaliesByJob({ skip: false, from, to }),
{
wrapper: TestProviders,
}
);
await waitForNextUpdate();
await waitForNextUpdate();
const jobCount = { key: jobId, doc_count: 99 };
mockAnomaliesSearch.mockResolvedValue({
aggregations: { number_of_anomalies: { buckets: [jobCount] } },
});
const { result } = renderHook(() => useAggregatedAnomaliesByJob({ skip: false, from, to }), {
wrapper: TestProviders,
});

await waitFor(() =>
expect(result.current.data).toEqual(
expect.arrayContaining([
{
Expand All @@ -110,75 +103,62 @@ describe('useAggregatedAnomaliesByJob', () => {
entity: AnomalyEntity.Host,
},
])
);
});
)
);
});

it('returns jobs sorted by name', async () => {
await act(async () => {
const firstJobId = 'v3_windows_anomalous_script';
const secondJobId = 'auth_rare_source_ip_for_a_user';
const fistJobCount = { key: firstJobId, doc_count: 99 };
const secondJobCount = { key: secondJobId, doc_count: 99 };
const firstJobSecurityName = '0000001';
const secondJobSecurityName = '0000002';
const firstJob = {
id: firstJobId,
jobState: 'started',
datafeedState: 'started',
customSettings: {
security_app_display_name: firstJobSecurityName,
},
};
const secondJob = {
id: secondJobId,
jobState: 'started',
datafeedState: 'started',
customSettings: {
security_app_display_name: secondJobSecurityName,
},
};

mockAnomaliesSearch.mockResolvedValue({
aggregations: { number_of_anomalies: { buckets: [fistJobCount, secondJobCount] } },
});
const firstJobId = 'v3_windows_anomalous_script';
const secondJobId = 'auth_rare_source_ip_for_a_user';
const fistJobCount = { key: firstJobId, doc_count: 99 };
const secondJobCount = { key: secondJobId, doc_count: 99 };
const firstJobSecurityName = '0000001';
const secondJobSecurityName = '0000002';
const firstJob = {
id: firstJobId,
jobState: 'started',
datafeedState: 'started',
customSettings: {
security_app_display_name: firstJobSecurityName,
},
};
const secondJob = {
id: secondJobId,
jobState: 'started',
datafeedState: 'started',
customSettings: {
security_app_display_name: secondJobSecurityName,
},
};

mockAnomaliesSearch.mockResolvedValue({
aggregations: { number_of_anomalies: { buckets: [fistJobCount, secondJobCount] } },
});

mockUseSecurityJobs.mockReturnValue({
loading: false,
isMlAdmin: true,
jobs: [firstJob, secondJob],
refetch: useSecurityJobsRefetch,
});
mockUseSecurityJobs.mockReturnValue({
loading: false,
isMlAdmin: true,
jobs: [firstJob, secondJob],
refetch: useSecurityJobsRefetch,
});

const { result, waitForNextUpdate } = renderHook(
() => useAggregatedAnomaliesByJob({ skip: false, from, to }),
{
wrapper: TestProviders,
}
);
await waitForNextUpdate();
await waitForNextUpdate();
const { result } = renderHook(() => useAggregatedAnomaliesByJob({ skip: false, from, to }), {
wrapper: TestProviders,
});
await waitFor(() => new Promise((resolve) => resolve(null)));

const names = result.current.data.map(({ name }) => name);
const names = result.current.data.map(({ name }) => name);

expect(names[0]).toEqual(firstJobSecurityName);
expect(names[1]).toEqual(secondJobSecurityName);
});
expect(names[0]).toEqual(firstJobSecurityName);
expect(names[1]).toEqual(secondJobSecurityName);
});

it('does not throw error when aggregations is undefined', async () => {
await act(async () => {
mockAnomaliesSearch.mockResolvedValue({});
const { waitForNextUpdate } = renderHook(
() => useAggregatedAnomaliesByJob({ skip: false, from, to }),
{
wrapper: TestProviders,
}
);
await waitForNextUpdate();
await waitForNextUpdate();

expect(mockAddToastError).not.toBeCalled();
mockAnomaliesSearch.mockResolvedValue({});
renderHook(() => useAggregatedAnomaliesByJob({ skip: false, from, to }), {
wrapper: TestProviders,
});

await waitFor(() => expect(mockAddToastError).not.toBeCalled());
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { renderHook } from '@testing-library/react-hooks';
import { waitFor, renderHook } from '@testing-library/react';

import { hasMlUserPermissions } from '../../../../../common/machine_learning/has_ml_user_permissions';
import { hasMlLicense } from '../../../../../common/machine_learning/has_ml_license';
Expand Down Expand Up @@ -38,12 +38,12 @@ describe('useInstalledSecurityJobs', () => {
});

it('returns jobs and permissions', async () => {
const { result, waitForNextUpdate } = renderHook(() => useInstalledSecurityJobs(), {
const { result } = renderHook(() => useInstalledSecurityJobs(), {
wrapper: TestProviders,
});
await waitForNextUpdate();

expect(result.current.jobs).toHaveLength(3);
await waitFor(() => expect(result.current.jobs).toHaveLength(3));

expect(result.current.jobs).toEqual(
expect.arrayContaining([
{
Expand Down Expand Up @@ -71,25 +71,26 @@ describe('useInstalledSecurityJobs', () => {
});

it('filters out non-security jobs', async () => {
const { result, waitForNextUpdate } = renderHook(() => useInstalledSecurityJobs(), {
const { result } = renderHook(() => useInstalledSecurityJobs(), {
wrapper: TestProviders,
});
await waitForNextUpdate();
await waitFor(() => expect(result.current.jobs.length).toBeGreaterThan(0));

expect(result.current.jobs.length).toBeGreaterThan(0);
expect(result.current.jobs.every(isSecurityJob)).toEqual(true);
});

it('renders a toast error if the ML call fails', async () => {
(getJobsSummary as jest.Mock).mockRejectedValue('whoops');
const { waitForNextUpdate } = renderHook(() => useInstalledSecurityJobs(), {

renderHook(() => useInstalledSecurityJobs(), {
wrapper: TestProviders,
});
await waitForNextUpdate();

expect(appToastsMock.addError).toHaveBeenCalledWith('whoops', {
title: 'Security job fetch failure',
});
await waitFor(() =>
expect(appToastsMock.addError).toHaveBeenCalledWith('whoops', {
title: 'Security job fetch failure',
})
);
});
});

Expand Down
Loading

0 comments on commit 5747fce

Please sign in to comment.