From 0750c6e8d3a494702776521d0bd5fd887e2d59d3 Mon Sep 17 00:00:00 2001 From: Julia Guskova Date: Thu, 24 Nov 2022 15:08:43 +0100 Subject: [PATCH] add missing test --- .../application/lib/rule_api/bulk_disable.ts | 2 +- .../application/lib/rule_api/bulk_enable.ts | 2 +- .../rules_list/components/rules_list.tsx | 4 +- .../rules_list_bulk_disable.test.tsx | 253 ++++++++++++++++++ .../rules_list_bulk_enable.test.tsx | 253 ++++++++++++++++++ 5 files changed, 510 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_disable.test.tsx create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_enable.test.tsx diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/bulk_disable.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/bulk_disable.ts index 1abeb407c0927..800a7267163da 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/bulk_disable.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/bulk_disable.ts @@ -15,7 +15,7 @@ export const bulkDisableRules = async ({ http, }: { filter?: KueryNode | null; - ids: string[]; + ids?: string[]; http: HttpSetup; }): Promise => { try { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/bulk_enable.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/bulk_enable.ts index 8c0b23d8e9a6c..d7644d9b598e7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/bulk_enable.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/bulk_enable.ts @@ -15,7 +15,7 @@ export const bulkEnableRules = async ({ http, }: { filter?: KueryNode | null; - ids: string[]; + ids?: string[]; http: HttpSetup; }): Promise => { try { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx index cf51dfa22ee6d..bff43bec81168 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx @@ -772,7 +772,7 @@ export const RulesList = ({ const { errors, total } = await bulkEnableRules({ ...(isAllSelected ? { filter: getFilter() } : {}), - ids: selectedIds, + ...(isAllSelected ? {} : { ids: selectedIds }), http, }); @@ -786,7 +786,7 @@ export const RulesList = ({ const { errors, total } = await bulkDisableRules({ ...(isAllSelected ? { filter: getFilter() } : {}), - ids: selectedIds, + ...(isAllSelected ? {} : { ids: selectedIds }), http, }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_disable.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_disable.test.tsx new file mode 100644 index 0000000000000..81f62c9a3d28b --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_disable.test.tsx @@ -0,0 +1,253 @@ +/* + * 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 * as React from 'react'; +import { ReactWrapper } from 'enzyme'; +import { act } from '@testing-library/react'; +import { mountWithIntl, nextTick } from '@kbn/test-jest-helpers'; +import { actionTypeRegistryMock } from '../../../action_type_registry.mock'; +import { ruleTypeRegistryMock } from '../../../rule_type_registry.mock'; +import { RulesList } from './rules_list'; +import { getIsExperimentalFeatureEnabled } from '../../../../common/get_experimental_features'; +import { useKibana } from '../../../../common/lib/kibana'; +import { + mockedRulesData, + ruleTypeFromApi, + getDisabledByLicenseRuleTypeFromApi, + ruleType, +} from './test_helpers'; +import { IToasts } from '@kbn/core/public'; + +jest.mock('../../../../common/lib/kibana'); +jest.mock('@kbn/kibana-react-plugin/public/ui_settings/use_ui_setting', () => ({ + useUiSetting: jest.fn(() => false), + useUiSetting$: jest.fn((value: string) => ['0,0']), +})); +jest.mock('../../../lib/action_connector_api', () => ({ + loadActionTypes: jest.fn(), + loadAllActions: jest.fn(), +})); + +jest.mock('../../../lib/rule_api', () => ({ + loadRulesWithKueryFilter: jest.fn(), + loadRuleTypes: jest.fn(), + loadRuleAggregationsWithKueryFilter: jest.fn(), + updateAPIKey: jest.fn(), + loadRuleTags: jest.fn(), + bulkDisableRules: jest.fn().mockResolvedValue({ errors: [], total: 10 }), + alertingFrameworkHealth: jest.fn(() => ({ + isSufficientlySecure: true, + hasPermanentEncryptionKey: true, + })), +})); + +jest.mock('../../../lib/rule_api/aggregate_kuery_filter'); +jest.mock('../../../lib/rule_api/rules_kuery_filter'); + +jest.mock('../../../../common/lib/health_api', () => ({ + triggersActionsUiHealth: jest.fn(() => ({ isRulesAvailable: true })), +})); +jest.mock('../../../../common/lib/config_api', () => ({ + triggersActionsUiConfig: jest + .fn() + .mockResolvedValue({ minimumScheduleInterval: { value: '1m', enforce: false } }), +})); +jest.mock('react-router-dom', () => ({ + useHistory: () => ({ + push: jest.fn(), + }), + useLocation: () => ({ + pathname: '/triggersActions/rules/', + }), +})); + +jest.mock('../../../lib/capabilities', () => ({ + hasAllPrivilege: jest.fn(() => true), + hasSaveRulesCapability: jest.fn(() => true), + hasShowActionsCapability: jest.fn(() => true), + hasExecuteActionsCapability: jest.fn(() => true), +})); +jest.mock('../../../../common/get_experimental_features', () => ({ + getIsExperimentalFeatureEnabled: jest.fn(), +})); + +const { loadRuleTypes, bulkDisableRules } = jest.requireMock('../../../lib/rule_api'); + +const { loadRulesWithKueryFilter } = jest.requireMock('../../../lib/rule_api/rules_kuery_filter'); +const { loadActionTypes, loadAllActions } = jest.requireMock('../../../lib/action_connector_api'); + +const actionTypeRegistry = actionTypeRegistryMock.create(); +const ruleTypeRegistry = ruleTypeRegistryMock.create(); + +ruleTypeRegistry.list.mockReturnValue([ruleType]); +actionTypeRegistry.list.mockReturnValue([]); + +const useKibanaMock = useKibana as jest.Mocked; + +beforeEach(() => { + (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => false); +}); + +// Test are too slow. It's breaking the build. So we skipp it now and waiting for improvment according this ticket: +// https://github.com/elastic/kibana/issues/145122 +describe.skip('Rules list bulk disable', () => { + let wrapper: ReactWrapper; + + const setup = async (authorized: boolean = true) => { + loadRulesWithKueryFilter.mockResolvedValue({ + page: 1, + perPage: 10000, + total: 6, + data: mockedRulesData, + }); + + loadActionTypes.mockResolvedValue([ + { + id: 'test', + name: 'Test', + }, + { + id: 'test2', + name: 'Test2', + }, + ]); + loadRuleTypes.mockResolvedValue([ + ruleTypeFromApi, + getDisabledByLicenseRuleTypeFromApi(authorized), + ]); + loadAllActions.mockResolvedValue([]); + // eslint-disable-next-line react-hooks/rules-of-hooks + useKibanaMock().services.ruleTypeRegistry = ruleTypeRegistry; + + // eslint-disable-next-line react-hooks/rules-of-hooks + useKibanaMock().services.actionTypeRegistry = actionTypeRegistry; + wrapper = mountWithIntl(); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + }; + + afterEach(() => { + jest.clearAllMocks(); + }); + + beforeAll(async () => { + await setup(); + useKibanaMock().services.notifications.toasts = { + addSuccess: jest.fn(), + addError: jest.fn(), + addDanger: jest.fn(), + addWarning: jest.fn(), + } as unknown as IToasts; + }); + + beforeEach(() => { + wrapper.find('[data-test-subj="checkboxSelectRow-1"]').at(1).simulate('change'); + wrapper.find('[data-test-subj="selectAllRulesButton"]').at(1).simulate('click'); + // Unselect something to test filtering + wrapper.find('[data-test-subj="checkboxSelectRow-2"]').at(1).simulate('change'); + wrapper.find('[data-test-subj="showBulkActionButton"]').first().simulate('click'); + }); + + it('can bulk disable', async () => { + wrapper.find('button[data-test-subj="bulkDisable"]').first().simulate('click'); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + const filter = bulkDisableRules.mock.calls[0][0].filter; + + expect(filter.function).toEqual('and'); + expect(filter.arguments[0].function).toEqual('or'); + expect(filter.arguments[1].function).toEqual('not'); + expect(filter.arguments[1].arguments[0].arguments[0].value).toEqual('alert.id'); + expect(filter.arguments[1].arguments[0].arguments[1].value).toEqual('alert:2'); + + expect(bulkDisableRules).toHaveBeenCalledWith( + expect.not.objectContaining({ + ids: [], + }) + ); + }); + + describe('Toast', () => { + it('should have success toast message', async () => { + wrapper.find('button[data-test-subj="bulkDisable"]').first().simulate('click'); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(useKibanaMock().services.notifications.toasts.addSuccess).toHaveBeenCalledTimes(1); + expect(useKibanaMock().services.notifications.toasts.addSuccess).toHaveBeenCalledWith( + 'Disabled 10 rules' + ); + }); + + it('should have warning toast message', async () => { + bulkDisableRules.mockResolvedValue({ + errors: [ + { + message: 'string', + rule: { + id: 'string', + name: 'string', + }, + }, + ], + total: 10, + }); + + wrapper.find('button[data-test-subj="bulkDisable"]').first().simulate('click'); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(useKibanaMock().services.notifications.toasts.addWarning).toHaveBeenCalledTimes(1); + expect(useKibanaMock().services.notifications.toasts.addWarning).toHaveBeenCalledWith( + expect.objectContaining({ + title: 'Disabled 9 rules, 1 rule encountered errors', + }) + ); + }); + + it('should have danger toast message', async () => { + bulkDisableRules.mockResolvedValue({ + errors: [ + { + message: 'string', + rule: { + id: 'string', + name: 'string', + }, + }, + ], + total: 1, + }); + + wrapper.find('button[data-test-subj="bulkDisable"]').first().simulate('click'); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(useKibanaMock().services.notifications.toasts.addDanger).toHaveBeenCalledTimes(1); + expect(useKibanaMock().services.notifications.toasts.addDanger).toHaveBeenCalledWith( + expect.objectContaining({ + title: 'Failed to disable 1 rule', + }) + ); + }); + }); +}); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_enable.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_enable.test.tsx new file mode 100644 index 0000000000000..5645b65fdbedc --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_enable.test.tsx @@ -0,0 +1,253 @@ +/* + * 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 * as React from 'react'; +import { ReactWrapper } from 'enzyme'; +import { act } from '@testing-library/react'; +import { mountWithIntl, nextTick } from '@kbn/test-jest-helpers'; +import { actionTypeRegistryMock } from '../../../action_type_registry.mock'; +import { ruleTypeRegistryMock } from '../../../rule_type_registry.mock'; +import { RulesList } from './rules_list'; +import { getIsExperimentalFeatureEnabled } from '../../../../common/get_experimental_features'; +import { useKibana } from '../../../../common/lib/kibana'; +import { + mockedRulesData, + ruleTypeFromApi, + getDisabledByLicenseRuleTypeFromApi, + ruleType, +} from './test_helpers'; +import { IToasts } from '@kbn/core/public'; + +jest.mock('../../../../common/lib/kibana'); +jest.mock('@kbn/kibana-react-plugin/public/ui_settings/use_ui_setting', () => ({ + useUiSetting: jest.fn(() => false), + useUiSetting$: jest.fn((value: string) => ['0,0']), +})); +jest.mock('../../../lib/action_connector_api', () => ({ + loadActionTypes: jest.fn(), + loadAllActions: jest.fn(), +})); + +jest.mock('../../../lib/rule_api', () => ({ + loadRulesWithKueryFilter: jest.fn(), + loadRuleTypes: jest.fn(), + loadRuleAggregationsWithKueryFilter: jest.fn(), + updateAPIKey: jest.fn(), + loadRuleTags: jest.fn(), + bulkEnableRules: jest.fn().mockResolvedValue({ errors: [], total: 10 }), + alertingFrameworkHealth: jest.fn(() => ({ + isSufficientlySecure: true, + hasPermanentEncryptionKey: true, + })), +})); + +jest.mock('../../../lib/rule_api/aggregate_kuery_filter'); +jest.mock('../../../lib/rule_api/rules_kuery_filter'); + +jest.mock('../../../../common/lib/health_api', () => ({ + triggersActionsUiHealth: jest.fn(() => ({ isRulesAvailable: true })), +})); +jest.mock('../../../../common/lib/config_api', () => ({ + triggersActionsUiConfig: jest + .fn() + .mockResolvedValue({ minimumScheduleInterval: { value: '1m', enforce: false } }), +})); +jest.mock('react-router-dom', () => ({ + useHistory: () => ({ + push: jest.fn(), + }), + useLocation: () => ({ + pathname: '/triggersActions/rules/', + }), +})); + +jest.mock('../../../lib/capabilities', () => ({ + hasAllPrivilege: jest.fn(() => true), + hasSaveRulesCapability: jest.fn(() => true), + hasShowActionsCapability: jest.fn(() => true), + hasExecuteActionsCapability: jest.fn(() => true), +})); +jest.mock('../../../../common/get_experimental_features', () => ({ + getIsExperimentalFeatureEnabled: jest.fn(), +})); + +const { loadRuleTypes, bulkEnableRules } = jest.requireMock('../../../lib/rule_api'); + +const { loadRulesWithKueryFilter } = jest.requireMock('../../../lib/rule_api/rules_kuery_filter'); +const { loadActionTypes, loadAllActions } = jest.requireMock('../../../lib/action_connector_api'); + +const actionTypeRegistry = actionTypeRegistryMock.create(); +const ruleTypeRegistry = ruleTypeRegistryMock.create(); + +ruleTypeRegistry.list.mockReturnValue([ruleType]); +actionTypeRegistry.list.mockReturnValue([]); + +const useKibanaMock = useKibana as jest.Mocked; + +beforeEach(() => { + (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => false); +}); + +// Test are too slow. It's breaking the build. So we skipp it now and waiting for improvment according this ticket: +// https://github.com/elastic/kibana/issues/145122 +describe.skip('Rules list bulk enable', () => { + let wrapper: ReactWrapper; + + const setup = async (authorized: boolean = true) => { + loadRulesWithKueryFilter.mockResolvedValue({ + page: 1, + perPage: 10000, + total: 6, + data: mockedRulesData.map((rule) => ({ ...rule, enabled: false })), + }); + + loadActionTypes.mockResolvedValue([ + { + id: 'test', + name: 'Test', + }, + { + id: 'test2', + name: 'Test2', + }, + ]); + loadRuleTypes.mockResolvedValue([ + ruleTypeFromApi, + getDisabledByLicenseRuleTypeFromApi(authorized), + ]); + loadAllActions.mockResolvedValue([]); + // eslint-disable-next-line react-hooks/rules-of-hooks + useKibanaMock().services.ruleTypeRegistry = ruleTypeRegistry; + + // eslint-disable-next-line react-hooks/rules-of-hooks + useKibanaMock().services.actionTypeRegistry = actionTypeRegistry; + wrapper = mountWithIntl(); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + }; + + afterEach(() => { + jest.clearAllMocks(); + }); + + beforeAll(async () => { + await setup(); + useKibanaMock().services.notifications.toasts = { + addSuccess: jest.fn(), + addError: jest.fn(), + addDanger: jest.fn(), + addWarning: jest.fn(), + } as unknown as IToasts; + }); + + beforeEach(() => { + wrapper.find('[data-test-subj="checkboxSelectRow-1"]').at(1).simulate('change'); + wrapper.find('[data-test-subj="selectAllRulesButton"]').at(1).simulate('click'); + // Unselect something to test filtering + wrapper.find('[data-test-subj="checkboxSelectRow-2"]').at(1).simulate('change'); + wrapper.find('[data-test-subj="showBulkActionButton"]').first().simulate('click'); + }); + + it('can bulk enable', async () => { + wrapper.find('button[data-test-subj="bulkEnable"]').first().simulate('click'); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + const filter = bulkEnableRules.mock.calls[0][0].filter; + + expect(filter.function).toEqual('and'); + expect(filter.arguments[0].function).toEqual('or'); + expect(filter.arguments[1].function).toEqual('not'); + expect(filter.arguments[1].arguments[0].arguments[0].value).toEqual('alert.id'); + expect(filter.arguments[1].arguments[0].arguments[1].value).toEqual('alert:2'); + + expect(bulkEnableRules).toHaveBeenCalledWith( + expect.not.objectContaining({ + ids: [], + }) + ); + }); + + describe('Toast', () => { + it('should have success toast message', async () => { + wrapper.find('button[data-test-subj="bulkEnable"]').first().simulate('click'); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(useKibanaMock().services.notifications.toasts.addSuccess).toHaveBeenCalledTimes(1); + expect(useKibanaMock().services.notifications.toasts.addSuccess).toHaveBeenCalledWith( + 'Enabled 10 rules' + ); + }); + + it('should have warning toast message', async () => { + bulkEnableRules.mockResolvedValue({ + errors: [ + { + message: 'string', + rule: { + id: 'string', + name: 'string', + }, + }, + ], + total: 10, + }); + + wrapper.find('button[data-test-subj="bulkEnable"]').first().simulate('click'); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(useKibanaMock().services.notifications.toasts.addWarning).toHaveBeenCalledTimes(1); + expect(useKibanaMock().services.notifications.toasts.addWarning).toHaveBeenCalledWith( + expect.objectContaining({ + title: 'Enabled 9 rules, 1 rule encountered errors', + }) + ); + }); + + it('should have danger toast message', async () => { + bulkEnableRules.mockResolvedValue({ + errors: [ + { + message: 'string', + rule: { + id: 'string', + name: 'string', + }, + }, + ], + total: 1, + }); + + wrapper.find('button[data-test-subj="bulkEnable"]').first().simulate('click'); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(useKibanaMock().services.notifications.toasts.addDanger).toHaveBeenCalledTimes(1); + expect(useKibanaMock().services.notifications.toasts.addDanger).toHaveBeenCalledWith( + expect.objectContaining({ + title: 'Failed to enable 1 rule', + }) + ); + }); + }); +});