From 1623629460c0696160ba43796afefb81d0fa1ea9 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Mon, 4 May 2020 10:15:08 -0700 Subject: [PATCH] Fixed alert Edit flyout shows the error message when one of this actions has a preconfigured action type (#64742) (#65092) * Fixed alert Edit flyout shows the error message when one of this actions has a preconfigured action type * Added tests * fixed config * fixed tests * Fixed browser error about memory * Fixed type check * Fixed func tests * fixed more tests * fixed tests --- .../action_connector_form/action_form.tsx | 28 +++++++-- .../components/alert_instances_route.tsx | 3 +- .../sections/alert_form/alert_edit.tsx | 1 + .../apps/triggers_actions_ui/connectors.ts | 59 +++++++++--------- .../apps/triggers_actions_ui/details.ts | 60 ++++++++++++------- .../apps/triggers_actions_ui/home_page.ts | 8 ++- x-pack/test/functional_with_es_ssl/config.ts | 23 ++++++- 7 files changed, 121 insertions(+), 61 deletions(-) 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 0027837c913d16..531e9e1926ff45 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 @@ -106,10 +106,6 @@ export const ActionForm = ({ index[actionTypeItem.id] = actionTypeItem; } setActionTypesIndex(index); - const hasActionsDisabled = actions.some(action => !index[action.actionTypeId].enabled); - if (setHasActionsDisabled) { - setHasActionsDisabled(hasActionsDisabled); - } } catch (e) { toastNotifications.addDanger({ title: i18n.translate( @@ -129,7 +125,8 @@ export const ActionForm = ({ (async () => { try { setIsLoadingConnectors(true); - setConnectors(await loadConnectors({ http })); + const loadedConnectors = await loadConnectors({ http }); + setConnectors(loadedConnectors); } catch (e) { toastNotifications.addDanger({ title: i18n.translate( @@ -146,6 +143,27 @@ export const ActionForm = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + useEffect(() => { + const setActionTypesAvalilability = () => { + const preconfiguredConnectors = connectors.filter(connector => connector.isPreconfigured); + const hasActionsDisabled = actions.some( + action => + !actionTypesIndex![action.actionTypeId].enabled && + !checkActionFormActionTypeEnabled( + actionTypesIndex![action.actionTypeId], + preconfiguredConnectors + ).isEnabled + ); + if (setHasActionsDisabled) { + setHasActionsDisabled(hasActionsDisabled); + } + }; + if (connectors.length > 0 && actionTypesIndex) { + setActionTypesAvalilability(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [connectors, actionTypesIndex]); + const preconfiguredMessage = i18n.translate( 'xpack.triggersActionsUI.sections.actionForm.preconfiguredTitleMessage', { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances_route.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances_route.tsx index b9d08abae16842..a02b44523e26c1 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances_route.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances_route.tsx @@ -32,7 +32,8 @@ export const AlertInstancesRoute: React.FunctionComponent = useEffect(() => { getAlertState(alert.id, loadAlertState, setAlertState, toastNotifications); - }, [alert, loadAlertState, toastNotifications]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [alert]); return alertState ? ( diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_edit.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_edit.tsx index c9cf59d87414fe..00bc9874face19 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_edit.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_edit.tsx @@ -150,6 +150,7 @@ export const AlertEdit = ({ size="s" color="danger" iconType="alert" + data-test-subj="hasActionsDisabled" title={i18n.translate( 'xpack.triggersActionsUI.sections.alertEdit.disabledActionsWarningTitle', { defaultMessage: 'This alert has actions that are disabled' } diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts index 562f64656319e4..1facc05bc186d2 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts @@ -21,10 +21,12 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { describe('Connectors', function() { before(async () => { await alerting.actions.createAction({ - name: `server-log-${Date.now()}`, - actionTypeId: '.server-log', + name: `slack-${Date.now()}`, + actionTypeId: '.slack', config: {}, - secrets: {}, + secrets: { + webhookUrl: 'https://test', + }, }); await pageObjects.common.navigateToApp('triggersActions'); @@ -36,12 +38,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.triggersActionsUI.clickCreateConnectorButton(); - await testSubjects.click('.server-log-card'); + await testSubjects.click('.slack-card'); + + await testSubjects.setValue('nameInput', connectorName); - const nameInput = await testSubjects.find('nameInput'); - await nameInput.click(); - await nameInput.clearValue(); - await nameInput.type(connectorName); + await testSubjects.setValue('slackWebhookUrlInput', 'https://test'); await find.clickByCssSelector('[data-test-subj="saveNewActionButton"]:not(disabled)'); @@ -54,7 +55,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expect(searchResults).to.eql([ { name: connectorName, - actionType: 'Server log', + actionType: 'Slack', referencedByCount: '0', }, ]); @@ -66,12 +67,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.triggersActionsUI.clickCreateConnectorButton(); - await testSubjects.click('.server-log-card'); + await testSubjects.click('.slack-card'); + + await testSubjects.setValue('nameInput', connectorName); - const nameInput = await testSubjects.find('nameInput'); - await nameInput.click(); - await nameInput.clearValue(); - await nameInput.type(connectorName); + await testSubjects.setValue('slackWebhookUrlInput', 'https://test'); await find.clickByCssSelector('[data-test-subj="saveNewActionButton"]:not(disabled)'); @@ -84,10 +84,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await find.clickByCssSelector('[data-test-subj="connectorsTableCell-name"] button'); - const nameInputToUpdate = await testSubjects.find('nameInput'); - await nameInputToUpdate.click(); - await nameInputToUpdate.clearValue(); - await nameInputToUpdate.type(updatedConnectorName); + await testSubjects.setValue('nameInput', updatedConnectorName); + + await testSubjects.setValue('slackWebhookUrlInput', 'https://test'); await find.clickByCssSelector('[data-test-subj="saveEditedActionButton"]:not(disabled)'); @@ -100,7 +99,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expect(searchResultsAfterEdit).to.eql([ { name: updatedConnectorName, - actionType: 'Server log', + actionType: 'Slack', referencedByCount: '0', }, ]); @@ -110,12 +109,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { async function createConnector(connectorName: string) { await pageObjects.triggersActionsUI.clickCreateConnectorButton(); - await testSubjects.click('.server-log-card'); + await testSubjects.click('.slack-card'); + + await testSubjects.setValue('nameInput', connectorName); - const nameInput = await testSubjects.find('nameInput'); - await nameInput.click(); - await nameInput.clearValue(); - await nameInput.type(connectorName); + await testSubjects.setValue('slackWebhookUrlInput', 'https://test'); await find.clickByCssSelector('[data-test-subj="saveNewActionButton"]:not(disabled)'); await pageObjects.common.closeToast(); @@ -148,12 +146,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { async function createConnector(connectorName: string) { await pageObjects.triggersActionsUI.clickCreateConnectorButton(); - await testSubjects.click('.server-log-card'); + await testSubjects.click('.slack-card'); + + await testSubjects.setValue('nameInput', connectorName); - const nameInput = await testSubjects.find('nameInput'); - await nameInput.click(); - await nameInput.clearValue(); - await nameInput.type(connectorName); + await testSubjects.setValue('slackWebhookUrlInput', 'https://test'); await find.clickByCssSelector('[data-test-subj="saveNewActionButton"]:not(disabled)'); await pageObjects.common.closeToast(); @@ -186,7 +183,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('should not be able to delete a preconfigured connector', async () => { - const preconfiguredConnectorName = 'xyz'; + const preconfiguredConnectorName = 'Serverlog'; await pageObjects.triggersActionsUI.searchConnectors(preconfiguredConnectorName); const searchResults = await pageObjects.triggersActionsUI.getConnectorsList(); @@ -197,7 +194,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('should not be able to edit a preconfigured connector', async () => { - const preconfiguredConnectorName = 'xyz'; + const preconfiguredConnectorName = 'xyztest'; await pageObjects.triggersActionsUI.searchConnectors(preconfiguredConnectorName); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts index 6ff065c1f4ab24..7970c9b24427e1 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts @@ -27,16 +27,20 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const actions = await Promise.all([ alerting.actions.createAction({ - name: `server-log-${testRunUuid}-${0}`, - actionTypeId: '.server-log', + name: `slack-${testRunUuid}-${0}`, + actionTypeId: '.slack', config: {}, - secrets: {}, + secrets: { + webhookUrl: 'https://test', + }, }), alerting.actions.createAction({ - name: `server-log-${testRunUuid}-${1}`, - actionTypeId: '.server-log', + name: `slack-${testRunUuid}-${1}`, + actionTypeId: '.slack', config: {}, - secrets: {}, + secrets: { + webhookUrl: 'https://test', + }, }), ]); @@ -72,7 +76,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expect(alertType).to.be(`Always Firing`); const { actionType, actionCount } = await pageObjects.alertDetailsUI.getActionsLabels(); - expect(actionType).to.be(`Server log`); + expect(actionType).to.be(`Slack`); expect(actionCount).to.be(`+1`); }); @@ -168,7 +172,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const alert = await alerting.alerts.createAlertWithActions( testRunUuid, '.index-threshold', - params + params, + [ + { + group: 'threshold met', + id: 'my-server-log', + params: { level: 'info', message: ' {{context.message}}' }, + }, + ] ); // refresh to see alert await browser.refresh(); @@ -183,6 +194,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const editButton = await testSubjects.find('openEditAlertFlyoutButton'); await editButton.click(); + expect(await testSubjects.exists('hasActionsDisabled')).to.eql(false); const updatedAlertName = `Changed Alert Name ${uuid.v4()}`; await testSubjects.setValue('alertNameInput', updatedAlertName, { @@ -304,16 +316,20 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const actions = await Promise.all([ alerting.actions.createAction({ - name: `server-log-${testRunUuid}-${0}`, - actionTypeId: '.server-log', + name: `slack-${testRunUuid}-${0}`, + actionTypeId: '.slack', config: {}, - secrets: {}, + secrets: { + webhookUrl: 'https://test', + }, }), alerting.actions.createAction({ - name: `server-log-${testRunUuid}-${1}`, - actionTypeId: '.server-log', + name: `slack-${testRunUuid}-${1}`, + actionTypeId: '.slack', config: {}, - secrets: {}, + secrets: { + webhookUrl: 'https://test', + }, }), ]); @@ -516,16 +532,20 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const actions = await Promise.all([ alerting.actions.createAction({ - name: `server-log-${testRunUuid}-${0}`, - actionTypeId: '.server-log', + name: `slack-${testRunUuid}-${0}`, + actionTypeId: '.slack', config: {}, - secrets: {}, + secrets: { + webhookUrl: 'https://test', + }, }), alerting.actions.createAction({ - name: `server-log-${testRunUuid}-${1}`, - actionTypeId: '.server-log', + name: `slack-${testRunUuid}-${1}`, + actionTypeId: '.slack', config: {}, - secrets: {}, + secrets: { + webhookUrl: 'https://test', + }, }), ]); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts index f049406b639c79..2edab1b164a1bb 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts @@ -59,10 +59,12 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { it('navigates to an alert details page', async () => { const action = await alerting.actions.createAction({ - name: `server-log-${Date.now()}`, - actionTypeId: '.server-log', + name: `Slack-${Date.now()}`, + actionTypeId: '.slack', config: {}, - secrets: {}, + secrets: { + webhookUrl: 'https://test', + }, }); const alert = await alerting.alerts.createAlwaysFiringWithAction( diff --git a/x-pack/test/functional_with_es_ssl/config.ts b/x-pack/test/functional_with_es_ssl/config.ts index 71b22a336f6b92..ef2270fb97745d 100644 --- a/x-pack/test/functional_with_es_ssl/config.ts +++ b/x-pack/test/functional_with_es_ssl/config.ts @@ -10,6 +10,21 @@ import { FtrConfigProviderContext } from '@kbn/test/types/ftr'; import { services } from './services'; import { pageObjects } from './page_objects'; +// .server-log is specifically not enabled +const enabledActionTypes = [ + '.email', + '.index', + '.pagerduty', + '.servicenow', + '.slack', + '.webhook', + 'test.authorization', + 'test.failing', + 'test.index-record', + 'test.noop', + 'test.rate-limit', +]; + // eslint-disable-next-line import/no-default-export export default async function({ readConfigFile }: FtrConfigProviderContext) { const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js')); @@ -50,15 +65,21 @@ export default async function({ readConfigFile }: FtrConfigProviderContext) { `--elasticsearch.hosts=https://${servers.elasticsearch.hostname}:${servers.elasticsearch.port}`, `--elasticsearch.ssl.certificateAuthorities=${CA_CERT_PATH}`, `--plugin-path=${join(__dirname, 'fixtures', 'plugins', 'alerts')}`, + `--xpack.actions.enabledActionTypes=${JSON.stringify(enabledActionTypes)}`, `--xpack.actions.preconfigured=${JSON.stringify([ { id: 'my-slack1', actionTypeId: '.slack', - name: 'Slack#xyz', + name: 'Slack#xyztest', config: { webhookUrl: 'https://hooks.slack.com/services/abcd/efgh/ijklmnopqrstuvwxyz', }, }, + { + id: 'my-server-log', + actionTypeId: '.server-log', + name: 'Serverlog#xyz', + }, ])}`, ], },