diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/user.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/user.tsx index a4e6fe6cf288..6c4c96a95bc4 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/user.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/user.tsx @@ -65,6 +65,7 @@ export const createUserAttachmentUserActionBuilder = ({ }), children: ( (commentRefs.current[comment.id] = element)} id={comment.id} content={comment.comment} diff --git a/x-pack/plugins/cases/public/components/user_actions/description.tsx b/x-pack/plugins/cases/public/components/user_actions/description.tsx index 01b0e105ecd9..eae2bd3d1258 100644 --- a/x-pack/plugins/cases/public/components/user_actions/description.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/description.tsx @@ -43,6 +43,7 @@ export const getDescriptionUserAction = ({ handleManageMarkdownEditId, handleManageQuote, }: GetDescriptionUserActionArgs): EuiCommentProps => { + const isEditable = manageMarkdownEditIds.includes(DESCRIPTION_ID); return { username: ( , children: ( (commentRefs.current[DESCRIPTION_ID] = element)} id={DESCRIPTION_ID} content={caseData.description} - isEditable={manageMarkdownEditIds.includes(DESCRIPTION_ID)} + isEditable={isEditable} onSaveContent={(content: string) => { onUpdateField({ key: DESCRIPTION_ID, value: content }); }} 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 19f60d7cb8c7..ae242fc64aaf 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 @@ -8,8 +8,9 @@ import React from 'react'; import { mount } from 'enzyme'; import { UserActionMarkdown } from './markdown_form'; -import { TestProviders } from '../../common/mock'; +import { AppMockRenderer, createAppMockRenderer, TestProviders } from '../../common/mock'; import { waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; const onChangeEditable = jest.fn(); const onSaveContent = jest.fn(); @@ -86,4 +87,113 @@ describe('UserActionMarkdown ', () => { expect(onChangeEditable).toHaveBeenCalledWith(defaultProps.id); }); }); + + describe('useForm stale state bug', () => { + let appMockRenderer: AppMockRenderer; + const oldContent = defaultProps.content; + const appendContent = ' appended content'; + const newContent = defaultProps.content + appendContent; + + beforeEach(() => { + appMockRenderer = createAppMockRenderer(); + }); + + it('creates a stale state if a key is not passed to the component', async () => { + const TestComponent = () => { + const [isEditable, setIsEditable] = React.useState(true); + const [saveContent, setSaveContent] = React.useState(defaultProps.content); + return ( +
+ +
+ ); + }; + + const result = appMockRenderer.render(); + + expect(result.getByTestId('user-action-markdown-form')).toBeTruthy(); + + // append some content and save + userEvent.type(result.container.querySelector('textarea')!, appendContent); + userEvent.click(result.getByTestId('user-action-save-markdown')); + + // wait for the state to update + await waitFor(() => { + expect(onChangeEditable).toHaveBeenCalledWith(defaultProps.id); + }); + + // toggle to non-edit state + userEvent.click(result.getByTestId('test-button')); + expect(result.getByTestId('user-action-markdown')).toBeTruthy(); + + // toggle to edit state again + userEvent.click(result.getByTestId('test-button')); + + // the text area holds a stale value + // this is the wrong behaviour. The textarea holds the old content + expect(result.container.querySelector('textarea')!.value).toEqual(oldContent); + expect(result.container.querySelector('textarea')!.value).not.toEqual(newContent); + }); + + it("doesn't create a stale state if a key is passed to the component", async () => { + const TestComponent = () => { + const [isEditable, setIsEditable] = React.useState(true); + const [saveContent, setSaveContent] = React.useState(defaultProps.content); + return ( +
+ +
+ ); + }; + const result = appMockRenderer.render(); + expect(result.getByTestId('user-action-markdown-form')).toBeTruthy(); + + // append content and save + userEvent.type(result.container.querySelector('textarea')!, appendContent); + userEvent.click(result.getByTestId('user-action-save-markdown')); + + // wait for the state to update + await waitFor(() => { + expect(onChangeEditable).toHaveBeenCalledWith(defaultProps.id); + }); + + // toggle to non-edit state + userEvent.click(result.getByTestId('test-button')); + expect(result.getByTestId('user-action-markdown')).toBeTruthy(); + + // toggle to edit state again + userEvent.click(result.getByTestId('test-button')); + + // this is the correct behaviour. The textarea holds the new content + expect(result.container.querySelector('textarea')!.value).toEqual(newContent); + expect(result.container.querySelector('textarea')!.value).not.toEqual(oldContent); + }); + }); });