diff --git a/src/components/MessageActions/__tests__/MessageActions.test.js b/src/components/MessageActions/__tests__/MessageActions.test.js index 9c7afa2d3..cbb350f20 100644 --- a/src/components/MessageActions/__tests__/MessageActions.test.js +++ b/src/components/MessageActions/__tests__/MessageActions.test.js @@ -1,15 +1,19 @@ import React from 'react'; import '@testing-library/jest-dom'; import testRenderer from 'react-test-renderer'; -import { cleanup, fireEvent, render } from '@testing-library/react'; +import { act, cleanup, fireEvent, render, screen } from '@testing-library/react'; import { MessageActions } from '../MessageActions'; import { MessageActionsBox as MessageActionsBoxMock } from '../MessageActionsBox'; -import { ChannelStateProvider } from '../../../context/ChannelStateContext'; -import { ChatProvider } from '../../../context/ChatContext'; -import { MessageProvider } from '../../../context/MessageContext'; -import { TranslationProvider } from '../../../context/TranslationContext'; +import { + ChannelStateProvider, + ChatProvider, + ComponentProvider, + DialogsManagerProvider, + MessageProvider, + TranslationProvider, +} from '../../../context'; import { generateMessage, getTestClient, mockTranslationContext } from '../../../mock-builders'; @@ -45,17 +49,22 @@ const chatClient = getTestClient(); function renderMessageActions(customProps, renderer = render) { return renderer( - - - - - - - + + + + + + + + + + + , ); } +const dialogOverlayTestId = 'str-chat__dialog-overlay'; const messageActionsTestId = 'message-actions'; describe(' component', () => { afterEach(cleanup); @@ -64,32 +73,44 @@ describe(' component', () => { it('should render correctly', () => { const tree = renderMessageActions({}, testRenderer.create); expect(tree.toJSON()).toMatchInlineSnapshot(` -
-
- -
+ + + + +
, +
, + ] `); }); @@ -101,77 +122,98 @@ describe(' component', () => { expect(queryByTestId(messageActionsTestId)).toBeNull(); }); - it('should open message actions box on click', () => { + it('should open message actions box on click', async () => { const { getByTestId } = renderMessageActions(); expect(MessageActionsBoxMock).toHaveBeenCalledWith( expect.objectContaining({ open: false }), {}, ); - fireEvent.click(getByTestId(messageActionsTestId)); + const dialogOverlay = screen.getByTestId(dialogOverlayTestId); + expect(dialogOverlay.children).toHaveLength(1); + await act(async () => { + await fireEvent.click(getByTestId(messageActionsTestId)); + }); expect(MessageActionsBoxMock).toHaveBeenLastCalledWith( expect.objectContaining({ open: true }), {}, ); + expect(dialogOverlay.children).toHaveLength(1); }); - it('should close message actions box on icon click if already opened', () => { + it('should close message actions box on icon click if already opened', async () => { const { getByTestId } = renderMessageActions(); expect(MessageActionsBoxMock).toHaveBeenLastCalledWith( expect.objectContaining({ open: false }), {}, ); - fireEvent.click(getByTestId(messageActionsTestId)); + await act(async () => { + await fireEvent.click(getByTestId(messageActionsTestId)); + }); expect(MessageActionsBoxMock).toHaveBeenLastCalledWith( expect.objectContaining({ open: true }), {}, ); - fireEvent.click(getByTestId(messageActionsTestId)); + await act(async () => { + await fireEvent.click(getByTestId(messageActionsTestId)); + }); expect(MessageActionsBoxMock).toHaveBeenLastCalledWith( expect.objectContaining({ open: false }), {}, ); }); - it('should close message actions box when user clicks anywhere in the document if it is already opened', () => { + it('should close message actions box when user clicks overlay if it is already opened', async () => { const { getByRole } = renderMessageActions(); - fireEvent.click(getByRole('button')); - + await act(async () => { + await fireEvent.click(getByRole('button')); + }); expect(MessageActionsBoxMock).toHaveBeenLastCalledWith( expect.objectContaining({ open: true }), {}, ); - fireEvent.click(document); + const dialogOverlay = screen.getByTestId(dialogOverlayTestId); + await act(async () => { + await fireEvent.click(dialogOverlay); + }); expect(MessageActionsBoxMock).toHaveBeenLastCalledWith( expect.objectContaining({ open: false }), {}, ); }); - it('should close message actions box when user presses Escape key', () => { + it('should close message actions box when user presses Escape key', async () => { const { getByRole } = renderMessageActions(); - fireEvent.click(getByRole('button')); + await act(async () => { + await fireEvent.click(getByRole('button')); + }); expect(MessageActionsBoxMock).toHaveBeenLastCalledWith( expect.objectContaining({ open: true }), {}, ); - fireEvent.keyUp(document, { charCode: 27, code: 'Escape', key: 'Escape' }); + await act(async () => { + await fireEvent.keyUp(document, { charCode: 27, code: 'Escape', key: 'Escape' }); + }); expect(MessageActionsBoxMock).toHaveBeenLastCalledWith( expect.objectContaining({ open: false }), {}, ); }); - it('should close actions box open on mouseleave if container ref provided', () => { + it('should close actions box open on mouseleave if container ref provided', async () => { const customProps = { messageWrapperRef: { current: wrapperMock }, }; const { getByRole } = renderMessageActions(customProps); - fireEvent.click(getByRole('button')); + await act(async () => { + await fireEvent.click(getByRole('button')); + }); expect(MessageActionsBoxMock).toHaveBeenLastCalledWith( expect.objectContaining({ open: true }), {}, ); - fireEvent.mouseLeave(customProps.messageWrapperRef.current); + await act(async () => { + await fireEvent.mouseLeave(customProps.messageWrapperRef.current); + }); expect(MessageActionsBoxMock).toHaveBeenLastCalledWith( expect.objectContaining({ open: false }), {}, @@ -196,12 +238,13 @@ describe(' component', () => { ); }); - it('should not register click and keyup event listeners to close actions box until opened', () => { + it('should not register click and keyup event listeners to close actions box until opened', async () => { const { getByRole } = renderMessageActions(); const addEventListener = jest.spyOn(document, 'addEventListener'); expect(document.addEventListener).not.toHaveBeenCalled(); - fireEvent.click(getByRole('button')); - expect(document.addEventListener).toHaveBeenCalledWith('click', expect.any(Function)); + await act(async () => { + await fireEvent.click(getByRole('button')); + }); expect(document.addEventListener).toHaveBeenCalledWith('keyup', expect.any(Function)); addEventListener.mockClear(); }); @@ -216,13 +259,14 @@ describe(' component', () => { removeEventListener.mockClear(); }); - it('should remove event listener when unmounted', () => { + it('should remove event listener when unmounted', async () => { const { getByRole, unmount } = renderMessageActions(); const removeEventListener = jest.spyOn(document, 'removeEventListener'); - fireEvent.click(getByRole('button')); + await act(async () => { + await fireEvent.click(getByRole('button')); + }); expect(document.removeEventListener).not.toHaveBeenCalled(); unmount(); - expect(document.removeEventListener).toHaveBeenCalledWith('click', expect.any(Function)); expect(document.removeEventListener).toHaveBeenCalledWith('keyup', expect.any(Function)); removeEventListener.mockClear(); }); @@ -235,32 +279,44 @@ describe(' component', () => { testRenderer.create, ); expect(tree.toJSON()).toMatchInlineSnapshot(` -
-
- -
+ + + + +
, +
, + ] `); }); @@ -272,32 +328,44 @@ describe(' component', () => { testRenderer.create, ); expect(tree.toJSON()).toMatchInlineSnapshot(` - -
- - + + + + + , +
, + ] `); }); }); diff --git a/src/components/MessageActions/__tests__/MessageActionsBox.test.js b/src/components/MessageActions/__tests__/MessageActionsBox.test.js index 2f786facf..4975bd3e4 100644 --- a/src/components/MessageActions/__tests__/MessageActionsBox.test.js +++ b/src/components/MessageActions/__tests__/MessageActionsBox.test.js @@ -18,7 +18,7 @@ import { import { Message } from '../../Message'; import { Channel } from '../../Channel'; import { Chat } from '../../Chat'; -import { ChatProvider } from '../../../context'; +import { ChatProvider, ComponentProvider, DialogsManagerProvider } from '../../../context'; expect.extend(toHaveNoViolations); @@ -34,19 +34,27 @@ async function renderComponent(boxProps, messageContext = {}) { return render( key }}> - - + - - - + + + + + + + , ); @@ -72,7 +80,9 @@ describe('MessageActionsBox', () => { getMessageActionsMock.mockImplementationOnce(() => ['flag']); const handleFlag = jest.fn(); const { container, getByText } = await renderComponent({ handleFlag }); - fireEvent.click(getByText('Flag')); + await act(async () => { + await fireEvent.click(getByText('Flag')); + }); expect(handleFlag).toHaveBeenCalledTimes(1); const results = await axe(container); expect(results).toHaveNoViolations(); @@ -85,7 +95,9 @@ describe('MessageActionsBox', () => { handleMute, isUserMuted: () => false, }); - fireEvent.click(getByText('Mute')); + await act(async () => { + await fireEvent.click(getByText('Mute')); + }); expect(handleMute).toHaveBeenCalledTimes(1); const results = await axe(container); expect(results).toHaveNoViolations(); @@ -98,7 +110,9 @@ describe('MessageActionsBox', () => { handleMute, isUserMuted: () => true, }); - fireEvent.click(getByText('Unmute')); + await act(async () => { + await fireEvent.click(getByText('Unmute')); + }); expect(handleMute).toHaveBeenCalledTimes(1); const results = await axe(container); expect(results).toHaveNoViolations(); @@ -108,7 +122,9 @@ describe('MessageActionsBox', () => { getMessageActionsMock.mockImplementationOnce(() => ['edit']); const handleEdit = jest.fn(); const { container, getByText } = await renderComponent({ handleEdit }); - fireEvent.click(getByText('Edit Message')); + await act(async () => { + await fireEvent.click(getByText('Edit Message')); + }); expect(handleEdit).toHaveBeenCalledTimes(1); const results = await axe(container); expect(results).toHaveNoViolations(); @@ -118,7 +134,9 @@ describe('MessageActionsBox', () => { getMessageActionsMock.mockImplementationOnce(() => ['delete']); const handleDelete = jest.fn(); const { container, getByText } = await renderComponent({ handleDelete }); - fireEvent.click(getByText('Delete')); + await act(async () => { + await fireEvent.click(getByText('Delete')); + }); expect(handleDelete).toHaveBeenCalledTimes(1); const results = await axe(container); expect(results).toHaveNoViolations(); @@ -129,7 +147,9 @@ describe('MessageActionsBox', () => { const handlePin = jest.fn(); const message = generateMessage({ pinned: false }); const { container, getByText } = await renderComponent({ handlePin, message }); - fireEvent.click(getByText('Pin')); + await act(async () => { + await fireEvent.click(getByText('Pin')); + }); expect(handlePin).toHaveBeenCalledTimes(1); const results = await axe(container); expect(results).toHaveNoViolations(); @@ -140,7 +160,9 @@ describe('MessageActionsBox', () => { const handlePin = jest.fn(); const message = generateMessage({ pinned: true }); const { container, getByText } = await renderComponent({ handlePin, message }); - fireEvent.click(getByText('Unpin')); + await act(async () => { + await fireEvent.click(getByText('Unpin')); + }); expect(handlePin).toHaveBeenCalledTimes(1); const results = await axe(container); expect(results).toHaveNoViolations(); @@ -195,16 +217,18 @@ describe('MessageActionsBox', () => { 'upload-file', ]; const renderMarkUnreadUI = async ({ channelProps, chatProps, messageProps }) => - await act(() => { - render( + await act(async () => { + await render( - + + + , ); @@ -230,8 +254,8 @@ describe('MessageActionsBox', () => { chatProps: { client }, messageProps: { message }, }); - await act(() => { - fireEvent.click(screen.getByTestId(TOGGLE_ACTIONS_BUTTON_TEST_ID)); + await act(async () => { + await fireEvent.click(screen.getByTestId(TOGGLE_ACTIONS_BUTTON_TEST_ID)); }); expect(screen.queryByText(ACTION_TEXT)).not.toBeInTheDocument(); }); @@ -257,8 +281,8 @@ describe('MessageActionsBox', () => { chatProps: { client }, messageProps: { message: myMessage }, }); - await act(() => { - fireEvent.click(screen.getByTestId(TOGGLE_ACTIONS_BUTTON_TEST_ID)); + await act(async () => { + await fireEvent.click(screen.getByTestId(TOGGLE_ACTIONS_BUTTON_TEST_ID)); }); expect(screen.queryByText(ACTION_TEXT)).toBeInTheDocument(); }); @@ -277,8 +301,8 @@ describe('MessageActionsBox', () => { chatProps: { client }, messageProps: { message, threadList: true }, }); - await act(() => { - fireEvent.click(screen.getByTestId(TOGGLE_ACTIONS_BUTTON_TEST_ID)); + await act(async () => { + await fireEvent.click(screen.getByTestId(TOGGLE_ACTIONS_BUTTON_TEST_ID)); }); expect(screen.queryByText(ACTION_TEXT)).not.toBeInTheDocument(); }); @@ -312,8 +336,8 @@ describe('MessageActionsBox', () => { }); }); - await act(() => { - fireEvent.click(screen.getByTestId(TOGGLE_ACTIONS_BUTTON_TEST_ID)); + await act(async () => { + await fireEvent.click(screen.getByTestId(TOGGLE_ACTIONS_BUTTON_TEST_ID)); }); expect(screen.queryByText(ACTION_TEXT)).toBeInTheDocument(); }); @@ -341,8 +365,8 @@ describe('MessageActionsBox', () => { chatProps: { client }, messageProps: { message: messageWithoutID }, }); - await act(() => { - fireEvent.click(screen.getByTestId(TOGGLE_ACTIONS_BUTTON_TEST_ID)); + await act(async () => { + await fireEvent.click(screen.getByTestId(TOGGLE_ACTIONS_BUTTON_TEST_ID)); }); expect(screen.queryByText(ACTION_TEXT)).not.toBeInTheDocument(); }); @@ -374,12 +398,14 @@ describe('MessageActionsBox', () => { customUser: me, }); - await act(() => { - render( + await act(async () => { + await render( - - + + + + , ); @@ -405,9 +431,9 @@ describe('MessageActionsBox', () => { chatProps: { client }, messageProps: { message }, }); - await act(() => { - fireEvent.click(screen.getByTestId(TOGGLE_ACTIONS_BUTTON_TEST_ID)); - fireEvent.click(screen.getByText(ACTION_TEXT)); + await act(async () => { + await fireEvent.click(screen.getByTestId(TOGGLE_ACTIONS_BUTTON_TEST_ID)); + await fireEvent.click(screen.getByText(ACTION_TEXT)); }); expect(channel.markUnread).toHaveBeenCalledWith( expect.objectContaining({ message_id: message.id }), @@ -430,9 +456,9 @@ describe('MessageActionsBox', () => { chatProps: { client }, messageProps: { getMarkMessageUnreadSuccessNotification, message }, }); - await act(() => { - fireEvent.click(screen.getByTestId(TOGGLE_ACTIONS_BUTTON_TEST_ID)); - fireEvent.click(screen.getByText(ACTION_TEXT)); + await act(async () => { + await fireEvent.click(screen.getByTestId(TOGGLE_ACTIONS_BUTTON_TEST_ID)); + await fireEvent.click(screen.getByText(ACTION_TEXT)); }); expect(getMarkMessageUnreadSuccessNotification).toHaveBeenCalledWith( expect.objectContaining(message), @@ -455,9 +481,9 @@ describe('MessageActionsBox', () => { chatProps: { client }, messageProps: { getMarkMessageUnreadErrorNotification, message }, }); - await act(() => { - fireEvent.click(screen.getByTestId(TOGGLE_ACTIONS_BUTTON_TEST_ID)); - fireEvent.click(screen.getByText(ACTION_TEXT)); + await act(async () => { + await fireEvent.click(screen.getByTestId(TOGGLE_ACTIONS_BUTTON_TEST_ID)); + await fireEvent.click(screen.getByText(ACTION_TEXT)); }); expect(getMarkMessageUnreadErrorNotification).toHaveBeenCalledWith( expect.objectContaining(message),