From 0c5f351a37798a3f5a2831933fdb0b6239b58a40 Mon Sep 17 00:00:00 2001 From: Ievgen Sorokopud Date: Mon, 16 Oct 2023 17:20:47 +0200 Subject: [PATCH] Tests --- .../right/components/assignees.test.tsx | 123 +++++++++++++++++ .../right/components/assignees.tsx | 25 +++- .../components/assignees_popover.test.tsx | 125 ++++++++++++++++++ .../right/components/assignees_popover.tsx | 4 +- .../right/components/test_ids.ts | 5 + 5 files changed, 275 insertions(+), 7 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.test.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees_popover.test.tsx diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.test.tsx new file mode 100644 index 0000000000000..b1c86da72b058 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.test.tsx @@ -0,0 +1,123 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; + +import { + ASSIGNEES_ADD_BUTTON_TEST_ID, + ASSIGNEES_COUNT_BADGE_TEST_ID, + ASSIGNEES_TITLE_TEST_ID, + ASSIGNEES_VALUE_TEST_ID, + ASSIGNEE_AVATAR_TEST_ID, +} from './test_ids'; +import { Assignees } from './assignees'; + +import { useGetUserProfiles } from '../../../../detections/containers/detection_engine/alerts/use_get_user_profiles'; +import { useSuggestUsers } from '../../../../detections/containers/detection_engine/alerts/use_suggest_users'; +import type { SetAlertAssigneesFunc } from '../../../../common/components/toolbar/bulk_actions/use_set_alert_assignees'; +import { useSetAlertAssignees } from '../../../../common/components/toolbar/bulk_actions/use_set_alert_assignees'; +import { TestProviders } from '../../../../common/mock'; + +jest.mock('../../../../detections/containers/detection_engine/alerts/use_get_user_profiles'); +jest.mock('../../../../detections/containers/detection_engine/alerts/use_suggest_users'); +jest.mock('../../../../common/components/toolbar/bulk_actions/use_set_alert_assignees'); + +const mockUserProfiles: UserProfileWithAvatar[] = [ + { uid: 'user-id-1', enabled: true, user: { username: 'user1', full_name: 'User 1' }, data: {} }, + { uid: 'user-id-2', enabled: true, user: { username: 'user2', full_name: 'User 2' }, data: {} }, + { uid: 'user-id-3', enabled: true, user: { username: 'user3', full_name: 'User 3' }, data: {} }, +]; + +const renderAssignees = ( + eventId = 'event-1', + alertAssignees = ['user-id-1'], + onAssigneesUpdated = jest.fn() +) => + render( + + + + ); + +describe('', () => { + let setAlertAssigneesMock: jest.Mocked; + + beforeEach(() => { + jest.clearAllMocks(); + (useGetUserProfiles as jest.Mock).mockReturnValue({ + loading: false, + userProfiles: mockUserProfiles, + }); + (useSuggestUsers as jest.Mock).mockReturnValue({ + loading: false, + userProfiles: mockUserProfiles, + }); + + setAlertAssigneesMock = jest.fn().mockReturnValue(Promise.resolve()); + (useSetAlertAssignees as jest.Mock).mockReturnValue(setAlertAssigneesMock); + }); + + it('should render component', () => { + const { getByTestId } = renderAssignees(); + + expect(getByTestId(ASSIGNEES_TITLE_TEST_ID)).toBeInTheDocument(); + expect(getByTestId(ASSIGNEES_VALUE_TEST_ID)).toBeInTheDocument(); + expect(getByTestId(ASSIGNEES_ADD_BUTTON_TEST_ID)).toBeInTheDocument(); + }); + + it('should render assignees avatars', () => { + const assignees = ['user-id-1', 'user-id-2']; + const { getByTestId, queryByTestId } = renderAssignees('test-event', assignees); + + expect(getByTestId(ASSIGNEE_AVATAR_TEST_ID('user1'))).toBeInTheDocument(); + expect(getByTestId(ASSIGNEE_AVATAR_TEST_ID('user2'))).toBeInTheDocument(); + + expect(queryByTestId(ASSIGNEES_COUNT_BADGE_TEST_ID)).not.toBeInTheDocument(); + }); + + it('should render badge with assignees count in case there are more than two users assigned to an alert', () => { + const assignees = ['user-id-1', 'user-id-2', 'user-id-3']; + const { getByTestId, queryByTestId } = renderAssignees('test-event', assignees); + + const assigneesCountBadge = getByTestId(ASSIGNEES_COUNT_BADGE_TEST_ID); + expect(assigneesCountBadge).toBeInTheDocument(); + expect(assigneesCountBadge).toHaveTextContent(`${assignees.length}`); + + expect(queryByTestId(ASSIGNEE_AVATAR_TEST_ID('user1'))).not.toBeInTheDocument(); + expect(queryByTestId(ASSIGNEE_AVATAR_TEST_ID('user2'))).not.toBeInTheDocument(); + expect(queryByTestId(ASSIGNEE_AVATAR_TEST_ID('user3'))).not.toBeInTheDocument(); + }); + + it('should call assignees update functionality with the right arguments', () => { + const assignees = ['user-id-1', 'user-id-2']; + const { getByTestId, getByText } = renderAssignees('test-event', assignees); + + // Update assignees + getByTestId(ASSIGNEES_ADD_BUTTON_TEST_ID).click(); + getByText('User 1').click(); + getByText('User 3').click(); + + // Close assignees popover + getByTestId(ASSIGNEES_ADD_BUTTON_TEST_ID).click(); + + expect(setAlertAssigneesMock).toHaveBeenCalledWith( + { + assignees_to_add: ['user-id-3'], + assignees_to_remove: ['user-id-1'], + }, + ['test-event'], + expect.anything(), + expect.anything() + ); + }); +}); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.tsx index 83f6aeb307530..3f22d13f82531 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.tsx @@ -16,9 +16,15 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { UserAvatar } from '@kbn/user-profile-components'; +import { noop } from 'lodash'; import { useGetUserProfiles } from '../../../../detections/containers/detection_engine/alerts/use_get_user_profiles'; import { useSetAlertAssignees } from '../../../../common/components/toolbar/bulk_actions/use_set_alert_assignees'; -import { ASSIGNEES_TITLE_TEST_ID, ASSIGNEES_VALUE_TEST_ID } from './test_ids'; +import { + ASSIGNEE_AVATAR_TEST_ID, + ASSIGNEES_TITLE_TEST_ID, + ASSIGNEES_VALUE_TEST_ID, + ASSIGNEES_COUNT_BADGE_TEST_ID, +} from './test_ids'; import { AssigneesPopover } from './assignees_popover'; export interface AssigneesProps { @@ -44,7 +50,6 @@ export const Assignees: FC = memo( const onSuccess = useCallback(() => { if (onAssigneesUpdated) onAssigneesUpdated(); }, [onAssigneesUpdated]); - const setIsLoading = useCallback(() => {}, []); const handleOnAlertAssigneesSubmit = useCallback(async () => { if (setAlertAssignees && selectedAssignees) { @@ -59,9 +64,9 @@ export const Assignees: FC = memo( assignees_to_remove: assigneesToRemoveArray, }; - await setAlertAssignees(assigneesToUpdate, [eventId], onSuccess, setIsLoading); + await setAlertAssignees(assigneesToUpdate, [eventId], onSuccess, noop); } - }, [alertAssignees, eventId, onSuccess, selectedAssignees, setAlertAssignees, setIsLoading]); + }, [alertAssignees, eventId, onSuccess, selectedAssignees, setAlertAssignees]); const togglePopover = useCallback(() => { setIsPopoverOpen((value) => !value); @@ -111,11 +116,19 @@ export const Assignees: FC = memo( ))} repositionOnScroll={true} > - {assignees.length} + + {assignees.length} + ) : ( assignees.map((user) => ( - + )) )} diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees_popover.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees_popover.test.tsx new file mode 100644 index 0000000000000..b9a5604657090 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees_popover.test.tsx @@ -0,0 +1,125 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; + +import { ASSIGNEES_ADD_BUTTON_TEST_ID } from './test_ids'; +import { AssigneesPopover } from './assignees_popover'; + +import { useSuggestUsers } from '../../../../detections/containers/detection_engine/alerts/use_suggest_users'; +import { TestProviders } from '../../../../common/mock'; + +jest.mock('../../../../detections/containers/detection_engine/alerts/use_suggest_users'); + +const mockUserProfiles: UserProfileWithAvatar[] = [ + { + uid: 'user-id-1', + enabled: true, + user: { username: 'user1', full_name: 'User 1', email: 'user1@test.com' }, + data: {}, + }, + { + uid: 'user-id-2', + enabled: true, + user: { username: 'user2', full_name: 'User 2', email: 'user2@test.com' }, + data: {}, + }, + { + uid: 'user-id-3', + enabled: true, + user: { username: 'user3', full_name: 'User 3', email: 'user3@test.com' }, + data: {}, + }, +]; + +const renderAssigneesPopover = ( + alertAssignees: string[], + isPopoverOpen: boolean, + onUsersChange = jest.fn(), + togglePopover = jest.fn(), + onClosePopover = jest.fn() +) => + render( + + + + ); + +describe('', () => { + beforeEach(() => { + jest.clearAllMocks(); + (useSuggestUsers as jest.Mock).mockReturnValue({ + loading: false, + userProfiles: mockUserProfiles, + }); + }); + + it('should render closed popover component', () => { + const { getByTestId, queryByTestId } = renderAssigneesPopover([], false); + + expect(getByTestId(ASSIGNEES_ADD_BUTTON_TEST_ID)).toBeInTheDocument(); + expect(queryByTestId('euiSelectableList')).not.toBeInTheDocument(); + }); + + it('should render opened popover component', () => { + const { getByTestId } = renderAssigneesPopover([], true); + + expect(getByTestId(ASSIGNEES_ADD_BUTTON_TEST_ID)).toBeInTheDocument(); + expect(getByTestId('euiSelectableList')).toBeInTheDocument(); + }); + + it('should render assignees', () => { + const { getByTestId } = renderAssigneesPopover([], true); + + const assigneesList = getByTestId('euiSelectableList'); + expect(assigneesList).toHaveTextContent('User 1'); + expect(assigneesList).toHaveTextContent('user1@test.com'); + expect(assigneesList).toHaveTextContent('User 2'); + expect(assigneesList).toHaveTextContent('user2@test.com'); + expect(assigneesList).toHaveTextContent('User 3'); + expect(assigneesList).toHaveTextContent('user3@test.com'); + }); + + it('should call onUsersChange on clsing the popover', () => { + const onUsersChangeMock = jest.fn(); + const { getByText } = renderAssigneesPopover([], true, onUsersChangeMock); + + getByText('User 1').click(); + getByText('User 2').click(); + getByText('User 3').click(); + getByText('User 3').click(); + getByText('User 2').click(); + getByText('User 1').click(); + + expect(onUsersChangeMock).toHaveBeenCalledTimes(6); + expect(onUsersChangeMock.mock.calls).toEqual([ + [['user-id-1']], + [['user-id-2', 'user-id-1']], + [['user-id-3', 'user-id-2', 'user-id-1']], + [['user-id-2', 'user-id-1']], + [['user-id-1']], + [[]], + ]); + }); + + it('should call togglePopover on add button click', () => { + const togglePopoverMock = jest.fn(); + const { getByTestId } = renderAssigneesPopover([], false, jest.fn(), togglePopoverMock); + + getByTestId(ASSIGNEES_ADD_BUTTON_TEST_ID).click(); + + expect(togglePopoverMock).toHaveBeenCalledTimes(1); + }); +}); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees_popover.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees_popover.tsx index 5dc05e6864e6e..d973001213c6b 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees_popover.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees_popover.tsx @@ -13,6 +13,7 @@ import { UserProfilesPopover } from '@kbn/user-profile-components'; import { EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import { useSuggestUsers } from '../../../../detections/containers/detection_engine/alerts/use_suggest_users'; +import { ASSIGNEES_ADD_BUTTON_TEST_ID } from './test_ids'; const PopoverButton: React.FC<{ togglePopover: () => void; isDisabled: boolean }> = ({ togglePopover, @@ -28,7 +29,8 @@ const PopoverButton: React.FC<{ togglePopover: () => void; isDisabled: boolean } )} > `${PREFIX}AssigneeAvatar-${userName}`; +export const ASSIGNEES_COUNT_BADGE_TEST_ID = `${PREFIX}AssigneesCountBadge`;