From e62581f8bf6098f2813768af2f31647c592645a2 Mon Sep 17 00:00:00 2001 From: Julian Gernun <17549662+jcger@users.noreply.github.com> Date: Tue, 2 May 2023 11:28:56 +0200 Subject: [PATCH] [RAM] Slack Web API Connector Channels List Error Message Not Showing Up (#155996) Fixes https://github.com/elastic/kibana/issues/155722 Adds an integration test that loads the ActionForm using SlackApi connector so we can check that the right error message is shown --------- Co-authored-by: Xavier Mouligneau --- .../slack/action_form.test.tsx | 177 ++++++++++++++++++ .../action_connector_form/action_form.tsx | 4 + 2 files changed, 181 insertions(+) create mode 100644 x-pack/plugins/stack_connectors/public/connector_types/slack/action_form.test.tsx diff --git a/x-pack/plugins/stack_connectors/public/connector_types/slack/action_form.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/slack/action_form.test.tsx new file mode 100644 index 0000000000000..32eb23f9a167f --- /dev/null +++ b/x-pack/plugins/stack_connectors/public/connector_types/slack/action_form.test.tsx @@ -0,0 +1,177 @@ +/* + * 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, screen } from '@testing-library/react'; +import { ActionForm } from '@kbn/triggers-actions-ui-plugin/public/application/sections/action_connector_form/action_form'; +import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; +import { ActionTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; +import type { ApplicationStart } from '@kbn/core/public'; +import { useKibana } from '@kbn/triggers-actions-ui-plugin/public/common/lib/kibana'; +import { IToasts } from '@kbn/core/public'; +import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; +import { getConnectorType as getSlackConnectorType } from './slack'; +import { getSlackApiConnectorType } from '../slack_api'; + +jest.mock('@kbn/triggers-actions-ui-plugin/public/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('@kbn/triggers-actions-ui-plugin/public/application/lib/action_connector_api/connectors'); +jest.mock( + '@kbn/triggers-actions-ui-plugin/public/application/lib/action_connector_api/connector_types' +); +jest.mock( + '@kbn/triggers-actions-ui-plugin/public/application/lib/action_connector_api/execute', + () => ({ + executeAction: async () => ({ + status: 'ok', + data: { + ok: true, + channels: [ + { + id: 'channel-id', + name: 'channel-name', + }, + ], + }, + connector_id: '.slack_api', + }), + }) +); +const { loadAllActions } = jest.requireMock( + '@kbn/triggers-actions-ui-plugin/public/application/lib/action_connector_api/connectors' +); +const { loadActionTypes } = jest.requireMock( + '@kbn/triggers-actions-ui-plugin/public/application/lib/action_connector_api/connector_types' +); +const useKibanaMock = useKibana as jest.Mocked; + +// GET api/actions/connector_types?feature_id=alerting +loadActionTypes.mockResolvedValue([ + { + enabled: true, + enabledInConfig: true, + enabledInLicense: true, + id: '.slack', + minimumLicenseRequired: 'basic', + name: 'Slack', + supportedFeatureIds: ['alerting', 'uptime', 'siem'], + }, + { + enabled: true, + enabledInConfig: true, + enabledInLicense: true, + id: '.slack_api', + minimumLicenseRequired: 'basic', + name: 'Slack API', + supportedFeatureIds: ['alerting', 'siem'], + }, +]); + +// GET api/actions/connectors +loadAllActions.mockResolvedValue([ + { + actionTypeId: '.slack_api', + config: {}, + id: 'connector-id', + isDeprecated: false, + isMissingSecrets: false, + isPreconfigured: false, + name: 'webapi', + referencedByCount: 0, + }, +]); + +const actionTypeRegistry = new TypeRegistry(); +actionTypeRegistry.register(getSlackConnectorType()); +actionTypeRegistry.register(getSlackApiConnectorType()); + +const baseProps = { + actions: [], + defaultActionGroupId: 'metrics.inventory_threshold.fired', + hasSummary: true, + featureId: 'alerting', + recoveryActionGroup: 'recovered', + actionTypeRegistry, + minimumThrottleInterval: [1, 'm'] as [number | undefined, string], + setActions: jest.fn(), + setActionIdByIndex: jest.fn(), + setActionParamsProperty: jest.fn(), + setActionFrequencyProperty: jest.fn(), + setActionAlertsFilterProperty: jest.fn(), +}; + +const mockToasts = { + danger: jest.fn(), + warning: jest.fn(), +}; + +jest.mock('@kbn/triggers-actions-ui-plugin/public', () => { + const original = jest.requireActual('@kbn/triggers-actions-ui-plugin/public'); + return { + ...original, + useKibana: () => ({ + ...original.useKibana(), + notifications: { toasts: mockToasts }, + }), + }; +}); + +describe('ActionForm - Slack API Connector', () => { + beforeAll(() => { + useKibanaMock().services.notifications.toasts = { + addSuccess: jest.fn(), + addError: jest.fn(), + addDanger: jest.fn(), + } as unknown as IToasts; + + useKibanaMock().services.application.capabilities = { + actions: { + delete: true, + save: true, + show: true, + }, + } as unknown as ApplicationStart['capabilities']; + }); + + test('show error message when no channel has been selected', async () => { + const testActions = [ + { + id: 'connector-id', + actionTypeId: '.slack_api', + group: 'metrics.inventory_threshold.fired', + params: { + subAction: 'postMessage', + subActionParams: { + text: 'text', + channels: [], // no channel selected + }, + }, + frequency: { + notifyWhen: 'onActionGroupChange' as 'onActionGroupChange', + throttle: null, + summary: false, + }, + }, + ]; + + const testProps = { + ...baseProps, + actions: testActions, + }; + + render( + + + + ); + + expect(await screen.findByText('Selected channel is required.')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx index 7557adb4979c0..f5245cd85fb53 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx @@ -562,6 +562,10 @@ export const ActionForm = ({ actionType={actionTypesIndex[activeActionItem.actionTypeId]} onClose={closeAddConnectorModal} postSaveEventHandler={(savedAction: ActionConnector) => { + // TODO: fix in https://github.com/elastic/kibana/issues/155993 + // actionTypes with subtypes need to be updated in case they switched to a + // subtype that is not the default one + actions[0].actionTypeId = savedAction.actionTypeId; connectors.push(savedAction); const indicesToUpdate = activeActionItem.indices || []; indicesToUpdate.forEach((index: number) => setActionIdByIndex(savedAction.id, index));