From 8cd6eabb438e422c5cf0dae41f10a7e7c94d1130 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 17 Dec 2024 04:55:33 +1100 Subject: [PATCH] [8.x] [Search][A11Y] Playground -> Open AI form (#202071) (#204428) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Backport This will backport the following commits from `main` to `8.x`: - [[Search][A11Y] Playground -> Open AI form (#202071)](https://github.com/elastic/kibana/pull/202071) ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) Co-authored-by: Samiul Monir <150824886+Samiul-TheSoccerFan@users.noreply.github.com> --- .../create_connector_flyout/index.test.tsx | 68 ++++++++++++++++++- .../create_connector_flyout/index.tsx | 24 +++++++ .../edit_connector_flyout/index.test.tsx | 38 ++++++++++- .../edit_connector_flyout/index.tsx | 44 ++++++++++-- 4 files changed, 163 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/create_connector_flyout/index.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/create_connector_flyout/index.test.tsx index df52b1729bb8d..1c5008d4e1dde 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/create_connector_flyout/index.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/create_connector_flyout/index.test.tsx @@ -9,7 +9,7 @@ import React, { lazy } from 'react'; import { actionTypeRegistryMock } from '../../../action_type_registry.mock'; import userEvent from '@testing-library/user-event'; -import { waitFor, act } from '@testing-library/react'; +import { waitFor, act, screen } from '@testing-library/react'; import CreateConnectorFlyout from '.'; import { AppMockRenderer, createAppMockRenderer } from '../../test_utils'; import { TECH_PREVIEW_LABEL } from '../../translations'; @@ -426,7 +426,7 @@ describe('CreateConnectorFlyout', () => { describe('Submitting', () => { it('creates a connector correctly', async () => { - const { getByTestId } = appMockRenderer.render( + const { getByTestId, queryByTestId } = appMockRenderer.render( { name: 'My test', secrets: {}, }); + expect(queryByTestId('connector-form-header-error-label')).not.toBeInTheDocument(); + }); + + it('show error message in the form header', async () => { + appMockRenderer.render( + + ); + + await userEvent.click(await screen.findByTestId(`${actionTypeModel.id}-card`)); + expect(await screen.findByTestId('test-connector-text-field')).toBeInTheDocument(); + + await userEvent.type( + await screen.findByTestId('test-connector-text-field'), + 'My text field', + { + delay: 100, + } + ); + + await userEvent.click(await screen.findByTestId('create-connector-flyout-save-btn')); + expect(onClose).not.toHaveBeenCalled(); + expect(onConnectorCreated).not.toHaveBeenCalled(); + expect(await screen.findByTestId('connector-form-header-error-label')).toBeInTheDocument(); + }); + + it('removes error message from the form header', async () => { + appMockRenderer.render( + + ); + + await userEvent.click(await screen.findByTestId(`${actionTypeModel.id}-card`)); + expect(await screen.findByTestId('test-connector-text-field')).toBeInTheDocument(); + + await userEvent.type( + await screen.findByTestId('test-connector-text-field'), + 'My text field', + { + delay: 100, + } + ); + + await userEvent.click(await screen.findByTestId('create-connector-flyout-save-btn')); + expect(onClose).not.toHaveBeenCalled(); + expect(onConnectorCreated).not.toHaveBeenCalled(); + expect(await screen.findByTestId('connector-form-header-error-label')).toBeInTheDocument(); + + await userEvent.type(await screen.findByTestId('nameInput'), 'My test', { + delay: 100, + }); + + await userEvent.click(await screen.findByTestId('create-connector-flyout-save-btn')); + expect(onClose).toHaveBeenCalled(); + expect(onConnectorCreated).toHaveBeenCalled(); + expect(screen.queryByTestId('connector-form-header-error-label')).not.toBeInTheDocument(); }); it('runs pre submit validator correctly', async () => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/create_connector_flyout/index.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/create_connector_flyout/index.tsx index b93d2815bf197..c341f861b5ead 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/create_connector_flyout/index.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/create_connector_flyout/index.tsx @@ -9,6 +9,7 @@ import React, { memo, ReactNode, useCallback, useEffect, useRef, useState } from import { EuiButton, EuiButtonGroup, + EuiCallOut, EuiFlexGroup, EuiFlexItem, EuiFlyout, @@ -18,6 +19,7 @@ import { import { getConnectorCompatibility } from '@kbn/actions-plugin/common'; import { FormattedMessage } from '@kbn/i18n-react'; +import { i18n } from '@kbn/i18n'; import { ActionConnector, ActionType, @@ -60,6 +62,7 @@ const CreateConnectorFlyoutComponent: React.FC = ({ const [actionType, setActionType] = useState(null); const [hasActionsUpgradeableByTrial, setHasActionsUpgradeableByTrial] = useState(false); const canSave = hasSaveActionsCapability(capabilities); + const [showFormErrors, setShowFormErrors] = useState(false); const [preSubmitValidationErrorMessage, setPreSubmitValidationErrorMessage] = useState(null); @@ -106,6 +109,7 @@ const CreateConnectorFlyoutComponent: React.FC = ({ const setResetForm = (reset: ResetForm) => { resetConnectorForm.current = reset; + setShowFormErrors(false); }; const onChangeGroupAction = (id: string) => { @@ -127,6 +131,7 @@ const CreateConnectorFlyoutComponent: React.FC = ({ const validateAndCreateConnector = useCallback(async () => { setPreSubmitValidationErrorMessage(null); + setShowFormErrors(false); const { isValid, data } = await submit(); if (!isMounted.current) { @@ -159,6 +164,8 @@ const CreateConnectorFlyoutComponent: React.FC = ({ const createdConnector = await createConnector(validConnector); return createdConnector; + } else { + setShowFormErrors(true); } }, [submit, preSubmitValidator, createConnector]); @@ -228,6 +235,23 @@ const CreateConnectorFlyoutComponent: React.FC = ({ )} + {showFormErrors && ( + <> + + + + )} { describe('Submitting', () => { it('updates the connector correctly', async () => { - const { getByTestId } = appMockRenderer.render( + const { getByTestId, queryByTestId } = appMockRenderer.render( { name: 'My test', secrets: {}, }); + expect(queryByTestId('connector-form-header-error-label')).not.toBeInTheDocument(); }); it('updates connector form field with latest value', async () => { @@ -555,6 +556,39 @@ describe('EditConnectorFlyout', () => { }); }); + it('show error message in the form header', async () => { + appMockRenderer.render( + + ); + + expect(await screen.findByTestId('test-connector-text-field')).toBeInTheDocument(); + await userEvent.clear(screen.getByTestId('nameInput')); + await userEvent.click(screen.getByTestId('edit-connector-flyout-save-btn')); + expect(await screen.findByTestId('connector-form-header-error-label')).toBeInTheDocument(); + }); + + it('removes error message from the form header', async () => { + appMockRenderer.render( + + ); + + await userEvent.clear(screen.getByTestId('nameInput')); + await userEvent.type(screen.getByTestId('nameInput'), 'My new name'); + await userEvent.type(screen.getByTestId('test-connector-secret-text-field'), 'password'); + await userEvent.click(screen.getByTestId('edit-connector-flyout-save-btn')); + expect(screen.queryByTestId('connector-form-header-error-label')).not.toBeInTheDocument(); + }); + it('runs pre submit validator correctly', async () => { const errorActionTypeModel = actionTypeRegistryMock.createMockActionTypeModel({ actionConnectorFields: lazy(() => import('../connector_error_mock')), diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx index e787f3eac42bf..1188f06a87d56 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx @@ -6,7 +6,14 @@ */ import React, { memo, ReactNode, useCallback, useEffect, useRef, useState } from 'react'; -import { EuiFlyout, EuiFlyoutBody, EuiButton, EuiConfirmModal } from '@elastic/eui'; +import { + EuiFlyout, + EuiFlyoutBody, + EuiButton, + EuiConfirmModal, + EuiCallOut, + EuiSpacer, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { ActionTypeExecutorResult, isActionTypeExecutorResult } from '@kbn/actions-plugin/common'; @@ -62,6 +69,7 @@ const EditConnectorFlyoutComponent: React.FC = ({ const canSave = hasSaveActionsCapability(capabilities); const { isLoading: isUpdatingConnector, updateConnector } = useUpdateConnector(); const { isLoading: isExecutingConnector, executeConnector } = useExecuteConnector(); + const [showFormErrors, setShowFormErrors] = useState(false); const [preSubmitValidationErrorMessage, setPreSubmitValidationErrorMessage] = useState(null); @@ -90,6 +98,7 @@ const EditConnectorFlyoutComponent: React.FC = ({ if (nextPage === EditConnectorTabs.Configuration && testExecutionResult !== none) { setTestExecutionResult(none); } + setShowFormErrors(false); setTab(nextPage); }, [testExecutionResult, setTestExecutionResult] @@ -146,6 +155,7 @@ const EditConnectorFlyoutComponent: React.FC = ({ const onClickSave = useCallback(async () => { setPreSubmitValidationErrorMessage(null); + setShowFormErrors(false); const { isValid, data } = await submit(); if (!isMounted.current) { @@ -194,6 +204,8 @@ const EditConnectorFlyoutComponent: React.FC = ({ } return updatedConnector; + } else { + setShowFormErrors(true); } }, [ onConnectorUpdated, @@ -218,6 +230,23 @@ const EditConnectorFlyoutComponent: React.FC = ({ <> {isEdit && ( <> + {showFormErrors && ( + <> + + + + )} = ({ ); }, [ connector, + docLinks.links.alerting.preconfiguredConnectors, actionTypeModel, isEdit, - docLinks.links.alerting.preconfiguredConnectors, - hasErrors, - isFormModified, - isSaved, - isSaving, + showFormErrors, + onFormModifiedChange, preSubmitValidationErrorMessage, showButtons, + isSaved, + isSaving, onClickSave, - onFormModifiedChange, + isFormModified, + hasErrors, ]); const renderTestTab = useCallback(() => {