diff --git a/x-pack/plugins/cases/public/common/translations.ts b/x-pack/plugins/cases/public/common/translations.ts index 08f7c0aa4e8d0..d46734524cb25 100644 --- a/x-pack/plugins/cases/public/common/translations.ts +++ b/x-pack/plugins/cases/public/common/translations.ts @@ -70,9 +70,12 @@ export const ARIA_KEYPAD_LEGEND = i18n.translate( } ); -export const COMMENT_REQUIRED = i18n.translate('xpack.cases.caseView.commentFieldRequiredError', { - defaultMessage: 'A comment is required.', -}); +export const EMPTY_COMMENTS_NOT_ALLOWED = i18n.translate( + 'xpack.cases.caseView.commentFieldRequiredError', + { + defaultMessage: 'Empty comments are not allowed.', + } +); export const REQUIRED_FIELD = i18n.translate('xpack.cases.caseView.fieldRequiredError', { defaultMessage: 'Required field', diff --git a/x-pack/plugins/cases/public/components/add_comment/index.tsx b/x-pack/plugins/cases/public/components/add_comment/index.tsx index dc5c1c48cfd9b..57dccbbfebe4e 100644 --- a/x-pack/plugins/cases/public/components/add_comment/index.tsx +++ b/x-pack/plugins/cases/public/components/add_comment/index.tsx @@ -177,7 +177,7 @@ export const AddComment = React.memo( data-test-subj="submit-comment" fill iconType="plusInCircle" - isDisabled={isLoading} + isDisabled={!comment || isLoading} isLoading={isLoading} onClick={onSubmit} > diff --git a/x-pack/plugins/cases/public/components/add_comment/schema.tsx b/x-pack/plugins/cases/public/components/add_comment/schema.tsx index 5df5769ef62ab..980a03e76b772 100644 --- a/x-pack/plugins/cases/public/components/add_comment/schema.tsx +++ b/x-pack/plugins/cases/public/components/add_comment/schema.tsx @@ -9,6 +9,7 @@ import type { FormSchema } from '@kbn/es-ui-shared-plugin/static/forms/hook_form import { FIELD_TYPES } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers'; import type { CommentRequestUserType } from '../../../common/api'; + import * as i18n from './translations'; const { emptyField } = fieldValidators; @@ -22,7 +23,7 @@ export const schema: FormSchema = { type: FIELD_TYPES.TEXTAREA, validations: [ { - validator: emptyField(i18n.COMMENT_REQUIRED), + validator: emptyField(i18n.EMPTY_COMMENTS_NOT_ALLOWED), }, ], }, diff --git a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx index cb08bf4b6e526..df261b613b0b2 100644 --- a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx @@ -65,8 +65,11 @@ const LineClampedEuiBadgeGroup = euiStyled(EuiBadgeGroup)` word-break: normal; `; +// margin-right is required here because -webkit-box-orient: vertical; +// in the EuiBadgeGroup prevents us from defining gutterSize. const StyledEuiBadge = euiStyled(EuiBadge)` - max-width: 100px + max-width: 100px; + margin-right: 5px; `; // to allow for ellipsis const renderStringField = (field: string, dataTestSubj: string) => diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx index 1fa5e94e6df98..dc1db2651f5bf 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx @@ -189,7 +189,7 @@ export const CaseViewActivity = ({ )} - + {caseAssignmentAuthorized ? ( <> { + let appMock: AppMockRenderer; + const props = { + title: 'My title', + confirmButtonText: 'My confirm button text', + cancelButtonText: 'My cancel button text', + onCancel: jest.fn(), + onConfirm: jest.fn(), + }; + + beforeEach(() => { + appMock = createAppMockRenderer(); + jest.clearAllMocks(); + }); + + it('renders correctly', async () => { + const result = appMock.render(); + + expect(result.getByTestId('cancel-creation-confirmation-modal')).toBeInTheDocument(); + expect(result.getByText(props.title)).toBeInTheDocument(); + expect(result.getByText(props.confirmButtonText)).toBeInTheDocument(); + expect(result.getByText(props.cancelButtonText)).toBeInTheDocument(); + }); + + it('calls onConfirm', async () => { + const result = appMock.render(); + + expect(result.getByText(props.confirmButtonText)).toBeInTheDocument(); + userEvent.click(result.getByText(props.confirmButtonText)); + + expect(props.onConfirm).toHaveBeenCalled(); + }); + + it('calls onCancel', async () => { + const result = appMock.render(); + + expect(result.getByText(props.cancelButtonText)).toBeInTheDocument(); + userEvent.click(result.getByText(props.cancelButtonText)); + + expect(props.onCancel).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/cases/public/components/create/cancel_creation_confirmation_modal.tsx b/x-pack/plugins/cases/public/components/create/cancel_creation_confirmation_modal.tsx new file mode 100644 index 0000000000000..0f73d90a60986 --- /dev/null +++ b/x-pack/plugins/cases/public/components/create/cancel_creation_confirmation_modal.tsx @@ -0,0 +1,41 @@ +/* + * 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 type { EuiConfirmModalProps } from '@elastic/eui'; +import { EuiConfirmModal } from '@elastic/eui'; +import * as i18n from './translations'; + +type Props = Pick< + EuiConfirmModalProps, + 'title' | 'confirmButtonText' | 'cancelButtonText' | 'onConfirm' | 'onCancel' +>; + +const CancelCreationConfirmationModalComponent: React.FC = ({ + title, + confirmButtonText = i18n.CONFIRM_MODAL_BUTTON, + cancelButtonText = i18n.CANCEL_MODAL_BUTTON, + onConfirm, + onCancel, +}) => { + return ( + + ); +}; + +CancelCreationConfirmationModalComponent.displayName = 'CancelCreationConfirmationModal'; + +export const CancelCreationConfirmationModal = React.memo(CancelCreationConfirmationModalComponent); diff --git a/x-pack/plugins/cases/public/components/create/form.tsx b/x-pack/plugins/cases/public/components/create/form.tsx index 4ec587667e18d..68ec55bbc956b 100644 --- a/x-pack/plugins/cases/public/components/create/form.tsx +++ b/x-pack/plugins/cases/public/components/create/form.tsx @@ -38,6 +38,8 @@ import { useAvailableCasesOwners } from '../app/use_available_owners'; import type { CaseAttachmentsWithoutOwner } from '../../types'; import { Severity } from './severity'; import { Assignees } from './assignees'; +import { useCancelCreationAction } from './use_cancel_creation_action'; +import { CancelCreationConfirmationModal } from './cancel_creation_confirmation_modal'; interface ContainerProps { big?: boolean; @@ -184,45 +186,59 @@ export const CreateCaseForm: React.FC = React.memo( timelineIntegration, attachments, initialValue, - }) => ( - - - - - - - - {i18n.CANCEL} - - - - - - - - - - - ) + }) => { + const { showConfirmationModal, onOpenModal, onConfirmModal, onCancelModal } = + useCancelCreationAction({ + onConfirmationCallback: onCancel, + }); + + return ( + + + + + + + + {i18n.CANCEL} + + {showConfirmationModal && ( + + )} + + + + + + + + + + ); + } ); CreateCaseForm.displayName = 'CreateCaseForm'; diff --git a/x-pack/plugins/cases/public/components/create/index.test.tsx b/x-pack/plugins/cases/public/components/create/index.test.tsx index bd2ef3ca1068f..24798c114fede 100644 --- a/x-pack/plugins/cases/public/components/create/index.test.tsx +++ b/x-pack/plugins/cases/public/components/create/index.test.tsx @@ -8,7 +8,8 @@ import React from 'react'; import type { ReactWrapper } from 'enzyme'; import { mount } from 'enzyme'; -import { act } from '@testing-library/react'; +import { act, waitFor } from '@testing-library/react'; + import type { EuiComboBoxOptionOption } from '@elastic/eui'; import { EuiComboBox } from '@elastic/eui'; @@ -105,16 +106,66 @@ describe('CreateCase case', () => { }); }); - it('should call cancel on cancel click', async () => { + it('should open modal on cancel click', async () => { const wrapper = mount( ); - await act(async () => { - wrapper.find(`[data-test-subj="create-case-cancel"]`).first().simulate('click'); + + wrapper.find(`[data-test-subj="create-case-cancel"]`).first().simulate('click'); + + await waitFor(() => { + expect( + wrapper.find(`[data-test-subj="cancel-creation-confirmation-modal"]`).exists() + ).toBeTruthy(); + }); + }); + + it('should confirm cancelation on modal confirm click', async () => { + const wrapper = mount( + + + + ); + + wrapper.find(`[data-test-subj="create-case-cancel"]`).first().simulate('click'); + + await waitFor(() => { + expect( + wrapper.find(`[data-test-subj="cancel-creation-confirmation-modal"]`).exists() + ).toBeTruthy(); + }); + + wrapper.find(`button[data-test-subj="confirmModalConfirmButton"]`).simulate('click'); + + await waitFor(() => { + expect(defaultProps.onCancel).toHaveBeenCalled(); + }); + }); + + it('should close modal on modal cancel click', async () => { + const wrapper = mount( + + + + ); + + wrapper.find(`[data-test-subj="create-case-cancel"]`).first().simulate('click'); + + await waitFor(() => { + expect( + wrapper.find(`[data-test-subj="cancel-creation-confirmation-modal"]`).exists() + ).toBeTruthy(); + }); + + wrapper.find(`button[data-test-subj="confirmModalCancelButton"]`).simulate('click'); + + await waitFor(() => { + expect( + wrapper.find(`[data-test-subj="cancel-creation-confirmation-modal"]`).exists() + ).toBeFalsy(); }); - expect(defaultProps.onCancel).toHaveBeenCalled(); }); it('should redirect to new case when posting the case', async () => { @@ -128,6 +179,7 @@ describe('CreateCase case', () => { fillForm(wrapper); wrapper.find(`button[data-test-subj="create-case-submit"]`).first().simulate('click'); }); + expect(defaultProps.onSuccess).toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/cases/public/components/create/index.tsx b/x-pack/plugins/cases/public/components/create/index.tsx index 386b64f04bd1c..a765bb0f7b801 100644 --- a/x-pack/plugins/cases/public/components/create/index.tsx +++ b/x-pack/plugins/cases/public/components/create/index.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { Field } from '@kbn/es-ui-shared-plugin/static/forms/components'; import { getUseField } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { EuiPageSection } from '@elastic/eui'; import * as i18n from './translations'; import type { CreateCaseFormProps } from './form'; import { CreateCaseForm } from './form'; @@ -23,7 +24,7 @@ export const CreateCase = React.memo( useCasesBreadcrumbs(CasesDeepLinkId.casesCreate); return ( - <> + ( timelineIntegration={timelineIntegration} withSteps={withSteps} /> - + ); } ); diff --git a/x-pack/plugins/cases/public/components/create/translations.ts b/x-pack/plugins/cases/public/components/create/translations.ts index 780a1bbd1d02f..4bb7471e1c648 100644 --- a/x-pack/plugins/cases/public/components/create/translations.ts +++ b/x-pack/plugins/cases/public/components/create/translations.ts @@ -29,3 +29,15 @@ export const SYNC_ALERTS_LABEL = i18n.translate('xpack.cases.create.syncAlertsLa export const ASSIGN_YOURSELF = i18n.translate('xpack.cases.create.assignYourself', { defaultMessage: 'Assign yourself', }); + +export const MODAL_TITLE = i18n.translate('xpack.cases.create.modalTitle', { + defaultMessage: 'Discard case?', +}); + +export const CANCEL_MODAL_BUTTON = i18n.translate('xpack.cases.create.cancelModalButton', { + defaultMessage: 'Cancel', +}); + +export const CONFIRM_MODAL_BUTTON = i18n.translate('xpack.cases.create.confirmModalButton', { + defaultMessage: 'Exit without saving', +}); diff --git a/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.test.tsx b/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.test.tsx new file mode 100644 index 0000000000000..4174d33c44d2f --- /dev/null +++ b/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.test.tsx @@ -0,0 +1,78 @@ +/* + * 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 { renderHook, act } from '@testing-library/react-hooks'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; +import { useCancelCreationAction } from './use_cancel_creation_action'; + +describe('UseConfirmationModal', () => { + let appMockRender: AppMockRenderer; + const onConfirmationCallback = jest.fn(); + + beforeEach(() => { + appMockRender = createAppMockRenderer(); + jest.clearAllMocks(); + }); + + it('init', async () => { + const { result } = renderHook(() => useCancelCreationAction({ onConfirmationCallback }), { + wrapper: appMockRender.AppWrapper, + }); + + expect(result.current.showConfirmationModal).toBe(false); + }); + + it('opens the modal', async () => { + const { result } = renderHook(() => useCancelCreationAction({ onConfirmationCallback }), { + wrapper: appMockRender.AppWrapper, + }); + + act(() => { + result.current.onOpenModal(); + }); + + expect(result.current.showConfirmationModal).toBe(true); + }); + + it('closes the modal', async () => { + const { result } = renderHook(() => useCancelCreationAction({ onConfirmationCallback }), { + wrapper: appMockRender.AppWrapper, + }); + + act(() => { + result.current.onOpenModal(); + }); + + expect(result.current.showConfirmationModal).toBe(true); + + act(() => { + result.current.onCancelModal(); + }); + + expect(result.current.showConfirmationModal).toBe(false); + }); + + it('calls onConfirmationCallback on confirm', async () => { + const { result } = renderHook(() => useCancelCreationAction({ onConfirmationCallback }), { + wrapper: appMockRender.AppWrapper, + }); + + act(() => { + result.current.onOpenModal(); + }); + + expect(result.current.showConfirmationModal).toBe(true); + + act(() => { + result.current.onConfirmModal(); + }); + + expect(result.current.showConfirmationModal).toBe(false); + expect(onConfirmationCallback).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.tsx b/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.tsx new file mode 100644 index 0000000000000..461125b739ee7 --- /dev/null +++ b/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.tsx @@ -0,0 +1,31 @@ +/* + * 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 { useCallback, useState } from 'react'; + +interface Props { + onConfirmationCallback: () => void; +} + +export const useCancelCreationAction = ({ onConfirmationCallback }: Props) => { + const [showConfirmationModal, setShowConfirmationModal] = useState(false); + + const onOpenModal = useCallback(() => { + setShowConfirmationModal(true); + }, []); + + const onConfirmModal = useCallback(() => { + setShowConfirmationModal(false); + onConfirmationCallback(); + }, [onConfirmationCallback]); + + const onCancelModal = useCallback(() => { + setShowConfirmationModal(false); + }, []); + + return { showConfirmationModal, onOpenModal, onConfirmModal, onCancelModal }; +}; diff --git a/x-pack/plugins/cases/public/components/user_actions/markdown_form.test.tsx b/x-pack/plugins/cases/public/components/user_actions/markdown_form.test.tsx index f9fb8594ea51e..c6b6c0e59f004 100644 --- a/x-pack/plugins/cases/public/components/user_actions/markdown_form.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/markdown_form.test.tsx @@ -16,6 +16,7 @@ const onChangeEditable = jest.fn(); const onSaveContent = jest.fn(); const newValue = 'Hello from Tehas'; +const emptyValue = ''; const hyperlink = `[hyperlink](http://elastic.co)`; const defaultProps = { content: `A link to a timeline ${hyperlink}`, @@ -61,6 +62,7 @@ describe('UserActionMarkdown ', () => { expect(onChangeEditable).toHaveBeenCalledWith(defaultProps.id); }); }); + it('Does not call onSaveContent if no change from current text', async () => { const wrapper = mount( @@ -75,6 +77,28 @@ describe('UserActionMarkdown ', () => { }); expect(onSaveContent).not.toHaveBeenCalled(); }); + + it('Save button disabled if current text is empty', async () => { + const wrapper = mount( + + + + ); + + wrapper + .find(`.euiMarkdownEditorTextArea`) + .first() + .simulate('change', { + target: { value: emptyValue }, + }); + + await waitFor(() => { + expect( + wrapper.find(`button[data-test-subj="user-action-save-markdown"]`).first().prop('disabled') + ).toBeTruthy(); + }); + }); + it('Cancel button click calls only onChangeEditable', async () => { const wrapper = mount( diff --git a/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx b/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx index b2b7443e001e8..42abc55f336c9 100644 --- a/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx @@ -5,15 +5,14 @@ * 2.0. */ -import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty, EuiButton } from '@elastic/eui'; -import React, { forwardRef, useCallback, useImperativeHandle, useMemo, useRef } from 'react'; +import React, { forwardRef, useCallback, useImperativeHandle, useRef } from 'react'; import styled from 'styled-components'; import { Form, useForm, UseField } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; -import * as i18n from '../case_view/translations'; import type { Content } from './schema'; import { schema } from './schema'; import { MarkdownRenderer, MarkdownEditorForm } from '../markdown_editor'; +import { UserActionMarkdownFooter } from './markdown_form_footer'; export const ContentWrapper = styled.div` padding: ${({ theme }) => `${theme.eui.euiSizeM} ${theme.eui.euiSizeL}`}; @@ -66,36 +65,6 @@ const UserActionMarkdownComponent = forwardRef< [setFieldValue] ); - const EditorButtons = useMemo( - () => ( - - - - {i18n.CANCEL} - - - - - {i18n.SAVE} - - - - ), - [handleCancelAction, handleSaveAction] - ); - useImperativeHandle(ref, () => ({ setComment, editor: editorRef.current, @@ -111,7 +80,12 @@ const UserActionMarkdownComponent = forwardRef< 'aria-label': 'Cases markdown editor', value: content, id, - bottomRightContent: EditorButtons, + bottomRightContent: ( + + ), }} /> diff --git a/x-pack/plugins/cases/public/components/user_actions/markdown_form_footer.tsx b/x-pack/plugins/cases/public/components/user_actions/markdown_form_footer.tsx new file mode 100644 index 0000000000000..ad047c68313f1 --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_actions/markdown_form_footer.tsx @@ -0,0 +1,57 @@ +/* + * 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 { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty, EuiButton } from '@elastic/eui'; +import React from 'react'; + +import { useFormData } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; + +import * as i18n from '../case_view/translations'; + +interface UserActionMarkdownFooterProps { + handleSaveAction: () => Promise; + handleCancelAction: () => void; +} + +const UserActionMarkdownFooterComponent: React.FC = ({ + handleSaveAction, + handleCancelAction, +}) => { + const [{ content }] = useFormData<{ content: string }>({ watch: ['content'] }); + + return ( + + + + {i18n.CANCEL} + + + + + {i18n.SAVE} + + + + ); +}; + +UserActionMarkdownFooterComponent.displayName = 'UserActionMarkdownFooterComponent'; + +export const UserActionMarkdownFooter = React.memo(UserActionMarkdownFooterComponent); diff --git a/x-pack/plugins/cases/public/components/user_actions/tags.tsx b/x-pack/plugins/cases/public/components/user_actions/tags.tsx index bbcad0e8486f5..ad944f1cf49b1 100644 --- a/x-pack/plugins/cases/public/components/user_actions/tags.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/tags.tsx @@ -25,7 +25,7 @@ const getLabelTitle = (userAction: UserActionResponse) => { {userAction.action === Actions.delete && i18n.REMOVED_FIELD} {i18n.TAGS.toLowerCase()} - + ); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index f5fac7b6b4459..b2746c0c2fd82 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -9278,7 +9278,6 @@ "xpack.cases.caseView.comment": "commentaire", "xpack.cases.caseView.comment.addComment": "Ajouter un commentaire", "xpack.cases.caseView.comment.addCommentHelpText": "Ajouter un nouveau commentaire...", - "xpack.cases.caseView.commentFieldRequiredError": "Un commentaire est requis.", "xpack.cases.caseView.connectors": "Système de gestion des incidents externes", "xpack.cases.caseView.copyCommentLinkAria": "Copier le lien de référence", "xpack.cases.caseView.create": "Créer un cas", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 26cb9a3bc6f06..245b2a33195fe 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9265,7 +9265,6 @@ "xpack.cases.caseView.comment": "コメント", "xpack.cases.caseView.comment.addComment": "コメントを追加", "xpack.cases.caseView.comment.addCommentHelpText": "新しいコメントを追加...", - "xpack.cases.caseView.commentFieldRequiredError": "コメントが必要です。", "xpack.cases.caseView.connectors": "外部インシデント管理システム", "xpack.cases.caseView.copyCommentLinkAria": "参照リンクをコピー", "xpack.cases.caseView.create": "ケースを作成", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index b184a4daf8113..87b560ac76f5c 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9283,7 +9283,6 @@ "xpack.cases.caseView.comment": "注释", "xpack.cases.caseView.comment.addComment": "添加注释", "xpack.cases.caseView.comment.addCommentHelpText": "添加新注释......", - "xpack.cases.caseView.commentFieldRequiredError": "注释必填。", "xpack.cases.caseView.connectors": "外部事件管理系统", "xpack.cases.caseView.copyCommentLinkAria": "复制引用链接", "xpack.cases.caseView.create": "创建案例", diff --git a/x-pack/test/functional/page_objects/observability_page.ts b/x-pack/test/functional/page_objects/observability_page.ts index 0177939ec3d15..bfbd1741d9f11 100644 --- a/x-pack/test/functional/page_objects/observability_page.ts +++ b/x-pack/test/functional/page_objects/observability_page.ts @@ -11,6 +11,7 @@ import { FtrProviderContext } from '../ftr_provider_context'; export function ObservabilityPageProvider({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); + const textValue = 'Foobar'; return { async clickSolutionNavigationEntry(appId: string, navId: string) { @@ -44,6 +45,7 @@ export function ObservabilityPageProvider({ getService, getPageObjects }: FtrPro }, async expectAddCommentButton() { + await testSubjects.setValue('add-comment', textValue); const button = await testSubjects.find('submit-comment', 20000); const disabledAttr = await button.getAttribute('disabled'); expect(disabledAttr).to.be(null);