From c8227a26941a76044a89d27662dae029644b3ea7 Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Mon, 11 Nov 2024 09:31:15 +0100 Subject: [PATCH] [React@18] Upgrade `@testing-library/react` (#198918) --- package.json | 4 +- .../src/jest/mocks/react_dom_client_mock.ts | 10 +++ packages/kbn-test/src/jest/resolver.js | 7 ++ .../src/jest/setup/react_testing_library.js | 31 +++++++++ ..._timeline_items_from_conversation.test.tsx | 2 +- .../summary_actions/check_all/index.test.tsx | 3 +- .../components/add_comment/index.test.tsx | 65 ++++++++++++------- .../public/components/create/index.test.tsx | 4 +- .../kubernetes_security/public/test/index.tsx | 4 +- .../transaction_action_menu.test.tsx.snap | 2 +- .../mock/endpoint/app_context_render.tsx | 2 +- .../related_integrations.test.tsx | 6 ++ .../session_view/public/test/index.tsx | 2 +- .../public/connector_types/lib/test_utils.tsx | 2 +- .../components/health_check.test.tsx | 2 +- .../rules_settings_modal.test.tsx | 2 + yarn.lock | 38 +++++------ 17 files changed, 128 insertions(+), 58 deletions(-) create mode 100644 packages/kbn-test/src/jest/mocks/react_dom_client_mock.ts diff --git a/package.json b/package.json index 024cedb6e9556..afda7cd4c9125 100644 --- a/package.json +++ b/package.json @@ -1518,9 +1518,9 @@ "@storybook/react": "^6.5.16", "@storybook/testing-react": "^1.3.0", "@storybook/theming": "^6.5.16", - "@testing-library/dom": "^8.19.0", + "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.5.0", - "@testing-library/react": "^12.1.5", + "@testing-library/react": "^16.0.1", "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.5.2", "@types/adm-zip": "^0.5.0", diff --git a/packages/kbn-test/src/jest/mocks/react_dom_client_mock.ts b/packages/kbn-test/src/jest/mocks/react_dom_client_mock.ts new file mode 100644 index 0000000000000..4e24481458767 --- /dev/null +++ b/packages/kbn-test/src/jest/mocks/react_dom_client_mock.ts @@ -0,0 +1,10 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export {}; diff --git a/packages/kbn-test/src/jest/resolver.js b/packages/kbn-test/src/jest/resolver.js index aab1b0f597284..a3303ecf17e45 100644 --- a/packages/kbn-test/src/jest/resolver.js +++ b/packages/kbn-test/src/jest/resolver.js @@ -58,6 +58,13 @@ module.exports = (request, options) => { }); } + // This is a workaround to run tests with React 17 and the latest @testing-library/react + // This will be removed once we upgrade to React 18 and start transitioning to the Concurrent Mode + // Tracking issue to clean this up https://github.com/elastic/kibana/issues/199100 + if (request === 'react-dom/client') { + return Path.resolve(__dirname, 'mocks/react_dom_client_mock.ts'); + } + if (request === `elastic-apm-node`) { return APM_AGENT_MOCK; } diff --git a/packages/kbn-test/src/jest/setup/react_testing_library.js b/packages/kbn-test/src/jest/setup/react_testing_library.js index a04ee097a5ec7..1444aa41949ef 100644 --- a/packages/kbn-test/src/jest/setup/react_testing_library.js +++ b/packages/kbn-test/src/jest/setup/react_testing_library.js @@ -19,3 +19,34 @@ import { configure } from '@testing-library/react'; // instead of default 'data-testid', use kibana's 'data-test-subj' configure({ testIdAttribute: 'data-test-subj', asyncUtilTimeout: 4500 }); + +/* eslint-env jest */ + +// This is a workaround to run tests with React 17 and the latest @testing-library/react +// Tracking issue to clean this up https://github.com/elastic/kibana/issues/199100 +jest.mock('@testing-library/react', () => { + const actual = jest.requireActual('@testing-library/react'); + + return { + ...actual, + render: (ui, options) => actual.render(ui, { ...options, legacyRoot: true }), + renderHook: (render, options) => actual.renderHook(render, { ...options, legacyRoot: true }), + }; +}); + +// This is a workaround to run tests with React 17 and the latest @testing-library/react +// And prevent the act warnings that were supposed to be muted by @testing-library +// The testing library mutes the act warnings in some cases by setting IS_REACT_ACT_ENVIRONMENT which is React@18 feature https://github.com/testing-library/react-testing-library/pull/1137/ +// Using this console override we're muting the act warnings as well +// Tracking issue to clean this up https://github.com/elastic/kibana/issues/199100 +// NOTE: we're not muting all the act warnings but only those that testing-library wanted to mute +const originalConsoleError = console.error; +console.error = (...args) => { + if (global.IS_REACT_ACT_ENVIRONMENT === false) { + if (args[0].includes('Warning: An update to %s inside a test was not wrapped in act')) { + return; + } + } + + originalConsoleError(...args); +}; diff --git a/x-pack/packages/kbn-ai-assistant/src/utils/get_timeline_items_from_conversation.test.tsx b/x-pack/packages/kbn-ai-assistant/src/utils/get_timeline_items_from_conversation.test.tsx index 337c11419209e..6a304430103ab 100644 --- a/x-pack/packages/kbn-ai-assistant/src/utils/get_timeline_items_from_conversation.test.tsx +++ b/x-pack/packages/kbn-ai-assistant/src/utils/get_timeline_items_from_conversation.test.tsx @@ -18,7 +18,7 @@ const mockChatService = createMockChatService(); let items: ReturnType; -function Providers({ children }: { children: React.ReactElement }) { +function Providers({ children }: { children: React.ReactNode }) { return ( { // simulate the wall clock advancing for (let i = 0; i < totalIndexNames + 1; i++) { - act(() => { + await act(async () => { jest.advanceTimersByTime(1000 * 10); }); - await waitFor(() => {}); } }); diff --git a/x-pack/plugins/cases/public/components/add_comment/index.test.tsx b/x-pack/plugins/cases/public/components/add_comment/index.test.tsx index 68cf0c8a1e2b5..5664151aa6df0 100644 --- a/x-pack/plugins/cases/public/components/add_comment/index.test.tsx +++ b/x-pack/plugins/cases/public/components/add_comment/index.test.tsx @@ -21,12 +21,13 @@ import { CasesTimelineIntegrationProvider } from '../timeline_context'; import { timelineIntegrationMock } from '../__mock__/timeline'; import type { CaseAttachmentWithoutOwner } from '../../types'; import type { AppMockRenderer } from '../../common/mock'; +import { useCreateAttachments } from '../../containers/use_create_attachments'; -jest.mock('../../containers/api', () => ({ - createAttachments: jest.fn(), -})); +jest.mock('../../containers/use_create_attachments'); -const createAttachmentsMock = createAttachments as jest.Mock; +const useCreateAttachmentsMock = useCreateAttachments as jest.Mock; + +const createAttachmentsMock = jest.fn().mockImplementation(() => defaultResponse); const onCommentSaving = jest.fn(); const onCommentPosted = jest.fn(); @@ -58,7 +59,10 @@ describe('AddComment ', () => { beforeEach(() => { jest.clearAllMocks(); appMockRender = createAppMockRenderer(); - createAttachmentsMock.mockImplementation(() => defaultResponse); + useCreateAttachmentsMock.mockReturnValue({ + isLoading: false, + mutate: createAttachmentsMock, + }); }); afterEach(() => { @@ -72,6 +76,11 @@ describe('AddComment ', () => { }); it('should render spinner and disable submit when loading', async () => { + useCreateAttachmentsMock.mockReturnValue({ + isLoading: true, + mutateAsync: createAttachmentsMock, + }); + appMockRender.render(); fireEvent.change(screen.getByLabelText('caseComment'), { @@ -109,16 +118,19 @@ describe('AddComment ', () => { await waitFor(() => expect(onCommentSaving).toBeCalled()); await waitFor(() => - expect(createAttachmentsMock).toBeCalledWith({ - caseId: addCommentProps.caseId, - attachments: [ - { - comment: sampleData.comment, - owner: SECURITY_SOLUTION_OWNER, - type: AttachmentType.user, - }, - ], - }) + expect(createAttachmentsMock).toBeCalledWith( + { + caseId: addCommentProps.caseId, + attachments: [ + { + comment: sampleData.comment, + type: AttachmentType.user, + }, + ], + caseOwner: SECURITY_SOLUTION_OWNER, + }, + { onSuccess: expect.any(Function) } + ) ); await waitFor(() => { expect(screen.getByTestId('euiMarkdownEditorTextArea')).toHaveTextContent(''); @@ -258,16 +270,19 @@ describe('draft comment ', () => { await waitFor(() => { expect(onCommentSaving).toBeCalled(); - expect(createAttachmentsMock).toBeCalledWith({ - caseId: addCommentProps.caseId, - attachments: [ - { - comment: sampleData.comment, - owner: SECURITY_SOLUTION_OWNER, - type: AttachmentType.user, - }, - ], - }); + expect(createAttachmentsMock).toBeCalledWith( + { + caseId: addCommentProps.caseId, + attachments: [ + { + comment: sampleData.comment, + type: AttachmentType.user, + }, + ], + caseOwner: SECURITY_SOLUTION_OWNER, + }, + { onSuccess: expect.any(Function) } + ); }); await waitFor(() => { 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 bb519b1f6f778..37e817d00f331 100644 --- a/x-pack/plugins/cases/public/components/create/index.test.tsx +++ b/x-pack/plugins/cases/public/components/create/index.test.tsx @@ -172,6 +172,8 @@ describe('CreateCase case', () => { await user.click(screen.getByTestId('create-case-submit')); - expect(defaultProps.onSuccess).toHaveBeenCalled(); + await waitFor(() => { + expect(defaultProps.onSuccess).toHaveBeenCalled(); + }); }); }); diff --git a/x-pack/plugins/kubernetes_security/public/test/index.tsx b/x-pack/plugins/kubernetes_security/public/test/index.tsx index a267169e6cf18..4aeaf93f746cc 100644 --- a/x-pack/plugins/kubernetes_security/public/test/index.tsx +++ b/x-pack/plugins/kubernetes_security/public/test/index.tsx @@ -17,7 +17,7 @@ import { coreMock } from '@kbn/core/public/mocks'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; -type UiRender = (ui: React.ReactElement, options?: RenderOptions) => RenderResult; +type UiRender = (ui: React.ReactNode, options?: RenderOptions) => RenderResult; /** * Mocked app root context renderer @@ -113,7 +113,7 @@ export const createAppRootMockRenderer = (): AppContextTestRender => { }, }); - const AppWrapper: React.FC<{ children: React.ReactElement }> = ({ children }) => ( + const AppWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => ( {children} diff --git a/x-pack/plugins/observability_solution/apm/public/components/shared/transaction_action_menu/__snapshots__/transaction_action_menu.test.tsx.snap b/x-pack/plugins/observability_solution/apm/public/components/shared/transaction_action_menu/__snapshots__/transaction_action_menu.test.tsx.snap index 023caad499485..63f0a9ff2f3ce 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/shared/transaction_action_menu/__snapshots__/transaction_action_menu.test.tsx.snap +++ b/x-pack/plugins/observability_solution/apm/public/components/shared/transaction_action_menu/__snapshots__/transaction_action_menu.test.tsx.snap @@ -3,7 +3,7 @@ exports[`TransactionActionMenu matches the snapshot 1`] = `