From 1b2af3c3050e81d4e15bbf12381065ec3d952e41 Mon Sep 17 00:00:00 2001 From: "Eyo O. Eyo" <7893459+eokoneyo@users.noreply.github.com> Date: Mon, 9 Dec 2024 14:15:29 +0100 Subject: [PATCH] [React18] Migrate test suites to account for testing library upgrades obs-ux-management-team (#201164) This PR migrates test suites that use `renderHook` from the library `@testing-library/react-hooks` to adopt the equivalent and replacement of `renderHook` from the export that is now available from `@testing-library/react`. This work is required for the planned migration to react18. ## Context In this PR, usages of `waitForNextUpdate` that previously could have been destructured from `renderHook` are now been replaced with `waitFor` exported from `@testing-library/react`, furthermore `waitFor` that would also have been destructured from the same renderHook result is now been replaced with `waitFor` from the export of `@testing-library/react`. ***Why is `waitFor` a sufficient enough replacement for `waitForNextUpdate`, and better for testing values subject to async computations?*** WaitFor will retry the provided callback if an error is returned, till the configured timeout elapses. By default the retry interval is `50ms` with a timeout value of `1000ms` that effectively translates to at least 20 retries for assertions placed within waitFor. See https://testing-library.com/docs/dom-testing-library/api-async/#waitfor for more information. This however means that for person's writing tests, said person has to be explicit about expectations that describe the internal state of the hook being tested. This implies checking for instance when a react query hook is being rendered, there's an assertion that said hook isn't loading anymore. In this PR you'd notice that this pattern has been adopted, with most existing assertions following an invocation of `waitForNextUpdate` being placed within a `waitFor` invocation. In some cases the replacement is simply a `waitFor(() => new Promise((resolve) => resolve(null)))` (many thanks to @kapral18, for point out exactly why this works), where this suffices the assertions that follow aren't placed within a waitFor so this PR doesn't get larger than it needs to be. It's also worth pointing out this PR might also contain changes to test and application code to improve said existing test. ### What to do next? 1. Review the changes in this PR. 2. If you think the changes are correct, approve the PR. ## Any questions? If you have any questions or need help with this PR, please leave comments in this PR. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Elastic Machine (cherry picked from commit 7f1d43668106e662dc06bda67d33266a0e35da62) --- .../src/hooks/use_alerts_history.test.tsx | 44 +- .../hooks/use_lens_attributes.test.tsx | 16 +- .../hooks/use_series_storage.test.tsx | 19 +- .../hooks/use_time_range.test.tsx | 11 +- .../has_data_context.test.tsx | 414 +++++++++--------- .../public/hooks/use_fetch_alert_data.test.ts | 51 +-- .../hooks/use_fetch_alert_detail.test.ts | 49 +-- .../public/hooks/use_fetch_bulk_cases.test.ts | 8 +- .../alerts/components/alert_actions.test.tsx | 3 +- .../slo_edit/hooks/use_show_sections.test.tsx | 2 +- .../use_recently_viewed_monitors.test.tsx | 21 +- .../use_monitor_status_data.test.ts | 14 +- .../monitor_filters/use_filters.test.tsx | 16 +- .../hooks/use_monitor_list.test.tsx | 14 +- .../use_get_data_stream_statuses.test.ts | 2 +- .../hooks/use_get_ilm_policies.test.ts | 6 +- .../hooks/use_location_monitors.test.tsx | 9 +- .../hooks/use_locations_api.test.tsx | 67 +-- .../use_step_waterfall_metrics.test.tsx | 2 +- .../waterfall/use_bar_charts.test.tsx | 2 +- .../waterfall_flyout/use_flyout.test.tsx | 2 +- .../hooks/use_absolute_date.test.ts | 2 +- .../hooks/use_composite_image.test.tsx | 25 +- .../hooks/use_location_name.test.tsx | 10 +- .../hooks/use_monitor_name.test.tsx | 18 +- .../use_monitors_sorted_by_status.test.tsx | 19 +- .../hooks/use_synthetics_priviliges.test.tsx | 4 +- .../synthetics/utils/testing/rtl_helpers.tsx | 2 +- .../public/hooks/use_date_format.test.tsx | 2 +- .../use_step_waterfall_metrics.test.tsx | 2 +- .../components/use_bar_charts.test.tsx | 2 +- .../waterfall/components/use_flyout.test.tsx | 2 +- .../overview/query_bar/use_query_bar.test.tsx | 3 +- .../check_steps/use_expanded_row.test.tsx | 7 +- .../hooks/use_composite_image.test.tsx | 23 +- .../hooks/use_filter_update.test.ts | 3 +- .../hooks/use_overview_filter_check.test.tsx | 2 +- 37 files changed, 437 insertions(+), 461 deletions(-) diff --git a/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.test.tsx b/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.test.tsx index 2707a0cecd185..d46d109dd21fb 100644 --- a/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.test.tsx +++ b/x-pack/packages/observability/alert_details/src/hooks/use_alerts_history.test.tsx @@ -6,13 +6,9 @@ */ import React from 'react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { waitFor, renderHook } from '@testing-library/react'; import { httpServiceMock } from '@kbn/core-http-browser-mocks'; -import { - type UseAlertsHistory, - useAlertsHistory, - type Props as useAlertsHistoryProps, -} from './use_alerts_history'; +import { useAlertsHistory } from './use_alerts_history'; const queryClient = new QueryClient({ logger: { @@ -44,7 +40,7 @@ describe('useAlertsHistory', () => { it('returns no data with error when http client is not provided', async () => { const http = undefined; - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useAlertsHistory({ http, @@ -56,18 +52,14 @@ describe('useAlertsHistory', () => { wrapper, } ); - await act(async () => { - await waitFor(() => result.current.isError); - }); - expect(result.current.isError).toBeTruthy(); + await waitFor(() => expect(result.current.isError).toBeTruthy()); expect(result.current.isSuccess).toBeFalsy(); expect(result.current.isLoading).toBeFalsy(); }); it('returns no data when API error', async () => { mockServices.http.post.mockRejectedValueOnce(new Error('ES error')); - - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useAlertsHistory({ ...mockServices, @@ -79,10 +71,7 @@ describe('useAlertsHistory', () => { wrapper, } ); - await act(async () => { - await waitFor(() => result.current.isError); - }); - expect(result.current.isError).toBeTruthy(); + await waitFor(() => expect(result.current.isError).toBeTruthy()); expect(result.current.isSuccess).toBeFalsy(); expect(result.current.isLoading).toBeFalsy(); }); @@ -130,7 +119,7 @@ describe('useAlertsHistory', () => { }, }); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useAlertsHistory({ ...mockServices, @@ -142,9 +131,7 @@ describe('useAlertsHistory', () => { wrapper, } ); - await act(async () => { - await waitFor(() => result.current.isSuccess); - }); + await waitFor(() => expect(result.current.isSuccess).toBe(true)); expect(result.current.isLoading).toBeFalsy(); expect(result.current.isError).toBeFalsy(); expect(result.current.data.avgTimeToRecoverUS).toEqual(134959464.2857143); @@ -167,7 +154,7 @@ describe('useAlertsHistory', () => { }, }); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useAlertsHistory({ ...mockServices, @@ -181,11 +168,7 @@ describe('useAlertsHistory', () => { wrapper, } ); - - await act(async () => { - await waitFor(() => result.current.isSuccess); - }); - + await waitFor(() => expect(result.current.isSuccess).toBe(true)); expect(mockServices.http.post).toBeCalledWith('/internal/rac/alerts/find', { body: '{"size":0,"rule_type_ids":["apm"],"consumers":["foo"],"query":{"bool":{"must":[' + @@ -215,7 +198,7 @@ describe('useAlertsHistory', () => { }, }); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useAlertsHistory({ ...mockServices, @@ -229,10 +212,7 @@ describe('useAlertsHistory', () => { } ); - await act(async () => { - await waitFor(() => result.current.isSuccess); - }); - + await waitFor(() => expect(result.current.isSuccess).toBe(true)); expect(mockServices.http.post).toBeCalledWith('/internal/rac/alerts/find', { body: '{"size":0,"rule_type_ids":["apm"],"query":{"bool":{"must":[' + diff --git a/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/hooks/use_lens_attributes.test.tsx b/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/hooks/use_lens_attributes.test.tsx index 1581ffd446713..e04e3d90d4b26 100644 --- a/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/hooks/use_lens_attributes.test.tsx +++ b/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/hooks/use_lens_attributes.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { allSeriesKey, reportTypeKey, UrlStorageContextProvider } from './use_series_storage'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useLensAttributes } from './use_lens_attributes'; import { ReportTypes } from '../configurations/constants'; import { mockDataView } from '../rtl_helpers'; @@ -66,9 +66,15 @@ describe('useExpViewTimeRange', function () { jest.spyOn(lensHook, 'useLensFormulaHelper').mockReturnValue(formulaHelper); }); - const lensAttributesSpy = jest.spyOn(lensAttributes, 'LensAttributes'); + const lensAttributesSpy = jest + .spyOn(lensAttributes, 'LensAttributes') + .mockImplementation(function (...args) { + return { + getJSON: () => {}, + } as lensAttributes.LensAttributes; + }); - function Wrapper({ children }: { children: JSX.Element }) { + function Wrapper({ children }: React.PropsWithChildren) { return ( - {children} + + {React.createElement(React.Fragment, {}, children)} + ); } diff --git a/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/hooks/use_series_storage.test.tsx b/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/hooks/use_series_storage.test.tsx index d43a36246c069..3ad5bdb66ed93 100644 --- a/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/hooks/use_series_storage.test.tsx +++ b/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/hooks/use_series_storage.test.tsx @@ -6,9 +6,8 @@ */ import React, { useEffect } from 'react'; -import { act, renderHook } from '@testing-library/react-hooks'; import { Router, Route } from '@kbn/shared-ux-router'; -import { render } from '@testing-library/react'; +import { render, renderHook, act } from '@testing-library/react'; import { UrlStorageContextProvider, useSeriesStorage, reportTypeKey } from './use_series_storage'; import { getHistoryFromUrl } from '../rtl_helpers'; import type { AppDataType } from '../types'; @@ -135,7 +134,7 @@ describe('userSeriesStorage', function () { }); it('ensures that only one series has a breakdown', () => { - function wrapper({ children }: { children: React.ReactElement }) { + function wrapper({ children }: React.PropsWithChildren) { return ( - {children} + {React.createElement(React.Fragment, {}, children)} ); } @@ -166,7 +165,7 @@ describe('userSeriesStorage', function () { it('sets reportType when calling applyChanges', () => { const setStorage = jest.fn(); - function wrapper({ children }: { children: React.ReactElement }) { + function wrapper({ children }: React.PropsWithChildren) { return ( - {children} + {React.createElement(React.Fragment, {}, children)} ); } @@ -197,7 +196,7 @@ describe('userSeriesStorage', function () { it('returns reportType in state, not url storage, from hook', () => { const setStorage = jest.fn(); - function wrapper({ children }: { children: React.ReactElement }) { + function wrapper({ children }: React.PropsWithChildren) { return ( - {children} + {React.createElement(React.Fragment, {}, children)} ); } @@ -225,7 +224,7 @@ describe('userSeriesStorage', function () { it('ensures that telemetry is called', () => { const trackEvent = jest.fn(); jest.spyOn(useTrackMetric, 'useUiTracker').mockReturnValue(trackEvent); - function wrapper({ children }: { children: React.ReactElement }) { + function wrapper({ children }: React.PropsWithChildren) { return ( - {children} + {React.createElement(React.Fragment, {}, children)} ); } diff --git a/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/hooks/use_time_range.test.tsx b/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/hooks/use_time_range.test.tsx index b97e3cc3c6923..ce6d344b86687 100644 --- a/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/hooks/use_time_range.test.tsx +++ b/x-pack/plugins/observability_solution/exploratory_view/public/components/shared/exploratory_view/hooks/use_time_range.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { allSeriesKey, reportTypeKey, UrlStorageContextProvider } from './use_series_storage'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useExpViewTimeRange } from './use_time_range'; import { ReportTypes } from '../configurations/constants'; import { createKbnUrlStateStorage } from '@kbn/kibana-utils-plugin/public'; @@ -43,9 +43,14 @@ const mockMultipleSeries = [ describe('useExpViewTimeRange', function () { const storage = createKbnUrlStateStorage({ useHash: false }); - function Wrapper({ children }: { children: JSX.Element }) { - return {children}; + function Wrapper({ children }: React.PropsWithChildren) { + return ( + + {React.createElement(React.Fragment, {}, children)} + + ); } + it('should return expected result when there is one series', async function () { await storage.set(allSeriesKey, mockSingleSeries); await storage.set(reportTypeKey, ReportTypes.KPI); diff --git a/x-pack/plugins/observability_solution/observability/public/context/has_data_context/has_data_context.test.tsx b/x-pack/plugins/observability_solution/observability/public/context/has_data_context/has_data_context.test.tsx index 3acc868a30c02..9fc5d77a7f881 100644 --- a/x-pack/plugins/observability_solution/observability/public/context/has_data_context/has_data_context.test.tsx +++ b/x-pack/plugins/observability_solution/observability/public/context/has_data_context/has_data_context.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { waitFor, renderHook } from '@testing-library/react'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { coreMock } from '@kbn/core/public/mocks'; import { registerDataHandler, unregisterDataHandler } from './data_handler'; @@ -16,13 +16,12 @@ import { HasDataContextProvider } from './has_data_context'; import { Router } from '@kbn/shared-ux-router'; import { createMemoryHistory } from 'history'; import { ApmIndicesConfig } from '../../../common/typings'; -import { act } from '@testing-library/react'; const sampleAPMIndices = { transaction: 'apm-*' } as ApmIndicesConfig; const core = coreMock.createStart(); -function wrapper({ children }: { children: React.ReactElement }) { +function wrapper({ children }: React.PropsWithChildren) { const history = createMemoryHistory(); return ( @@ -58,7 +57,7 @@ describe('HasDataContextProvider', () => { describe('when no plugin has registered', () => { it('hasAnyData returns undefined and all apps return undefined', async () => { - const { result, waitForNextUpdate } = renderHook(() => useHasData(), { wrapper }); + const { result } = renderHook(() => useHasData(), { wrapper }); expect(result.current).toMatchObject({ hasDataMap: {}, hasAnyData: false, @@ -66,25 +65,24 @@ describe('HasDataContextProvider', () => { forceUpdate: expect.any(String), onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); - expect(result.current).toEqual({ - hasDataMap: { - apm: { hasData: undefined, status: 'success' }, - uptime: { hasData: undefined, status: 'success' }, - infra_logs: { hasData: undefined, status: 'success' }, - infra_metrics: { hasData: undefined, status: 'success' }, - ux: { hasData: undefined, status: 'success' }, - alert: { hasData: false, status: 'success' }, - universal_profiling: { hasData: false, status: 'success' }, - }, - hasAnyData: false, - isAllRequestsComplete: true, - forceUpdate: expect.any(String), - onRefreshTimeRange: expect.any(Function), - }); + await waitFor(() => + expect(result.current).toEqual({ + hasDataMap: { + apm: { hasData: undefined, status: 'success' }, + uptime: { hasData: undefined, status: 'success' }, + infra_logs: { hasData: undefined, status: 'success' }, + infra_metrics: { hasData: undefined, status: 'success' }, + ux: { hasData: undefined, status: 'success' }, + alert: { hasData: false, status: 'success' }, + universal_profiling: { hasData: false, status: 'success' }, + }, + hasAnyData: false, + isAllRequestsComplete: true, + forceUpdate: expect.any(String), + onRefreshTimeRange: expect.any(Function), + }) + ); }); }); @@ -112,7 +110,7 @@ describe('HasDataContextProvider', () => { afterAll(unregisterAll); it('hasAnyData returns false and all apps return false', async () => { - const { result, waitForNextUpdate } = renderHook(() => useHasData(), { wrapper }); + const { result } = renderHook(() => useHasData(), { wrapper }); expect(result.current).toEqual({ hasDataMap: { @@ -124,31 +122,29 @@ describe('HasDataContextProvider', () => { onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); - - expect(result.current).toEqual({ - hasDataMap: { - apm: { hasData: false, status: 'success' }, - uptime: { - hasData: false, - status: 'success', - }, - infra_logs: { hasData: false, indices: 'test-index', status: 'success' }, - infra_metrics: { hasData: false, status: 'success' }, - ux: { - hasData: false, - status: 'success', + await waitFor(() => + expect(result.current).toEqual({ + hasDataMap: { + apm: { hasData: false, status: 'success' }, + uptime: { + hasData: false, + status: 'success', + }, + infra_logs: { hasData: false, indices: 'test-index', status: 'success' }, + infra_metrics: { hasData: false, status: 'success' }, + ux: { + hasData: false, + status: 'success', + }, + alert: { hasData: false, status: 'success' }, + universal_profiling: { hasData: false, status: 'success' }, }, - alert: { hasData: false, status: 'success' }, - universal_profiling: { hasData: false, status: 'success' }, - }, - hasAnyData: false, - isAllRequestsComplete: true, - forceUpdate: expect.any(String), - onRefreshTimeRange: expect.any(Function), - }); + hasAnyData: false, + isAllRequestsComplete: true, + forceUpdate: expect.any(String), + onRefreshTimeRange: expect.any(Function), + }) + ); }); }); @@ -178,7 +174,7 @@ describe('HasDataContextProvider', () => { afterAll(unregisterAll); it('hasAnyData returns true apm returns true and all other apps return false', async () => { - const { result, waitForNextUpdate } = renderHook(() => useHasData(), { wrapper }); + const { result } = renderHook(() => useHasData(), { wrapper }); expect(result.current).toEqual({ hasDataMap: { universal_profiling: { hasData: false, status: 'success' } }, hasAnyData: false, @@ -187,33 +183,31 @@ describe('HasDataContextProvider', () => { onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); - - expect(result.current).toEqual({ - hasDataMap: { - apm: { hasData: true, status: 'success' }, - uptime: { - hasData: false, - indices: 'heartbeat-*, synthetics-*', - status: 'success', - }, - infra_logs: { hasData: false, indices: 'test-index', status: 'success' }, - infra_metrics: { hasData: false, indices: 'metric-*', status: 'success' }, - ux: { - hasData: false, - indices: 'apm-*', - status: 'success', + await waitFor(() => + expect(result.current).toEqual({ + hasDataMap: { + apm: { hasData: true, status: 'success' }, + uptime: { + hasData: false, + indices: 'heartbeat-*, synthetics-*', + status: 'success', + }, + infra_logs: { hasData: false, indices: 'test-index', status: 'success' }, + infra_metrics: { hasData: false, indices: 'metric-*', status: 'success' }, + ux: { + hasData: false, + indices: 'apm-*', + status: 'success', + }, + alert: { hasData: false, status: 'success' }, + universal_profiling: { hasData: false, status: 'success' }, }, - alert: { hasData: false, status: 'success' }, - universal_profiling: { hasData: false, status: 'success' }, - }, - hasAnyData: true, - isAllRequestsComplete: true, - forceUpdate: expect.any(String), - onRefreshTimeRange: expect.any(Function), - }); + hasAnyData: true, + isAllRequestsComplete: true, + forceUpdate: expect.any(String), + onRefreshTimeRange: expect.any(Function), + }) + ); }); }); @@ -243,7 +237,7 @@ describe('HasDataContextProvider', () => { afterAll(unregisterAll); it('hasAnyData returns true and all apps return true', async () => { - const { result, waitForNextUpdate } = renderHook(() => useHasData(), { wrapper }); + const { result } = renderHook(() => useHasData(), { wrapper }); expect(result.current).toEqual({ hasDataMap: { universal_profiling: { hasData: false, status: 'success' } }, hasAnyData: false, @@ -252,37 +246,35 @@ describe('HasDataContextProvider', () => { onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); - - expect(result.current).toEqual({ - hasDataMap: { - apm: { - hasData: true, - status: 'success', - }, - uptime: { - hasData: true, - indices: 'heartbeat-*, synthetics-*', - status: 'success', - }, - infra_logs: { hasData: true, indices: 'test-index', status: 'success' }, - infra_metrics: { hasData: true, indices: 'metric-*', status: 'success' }, - ux: { - hasData: true, - serviceName: 'ux', - indices: 'apm-*', - status: 'success', + await waitFor(() => + expect(result.current).toEqual({ + hasDataMap: { + apm: { + hasData: true, + status: 'success', + }, + uptime: { + hasData: true, + indices: 'heartbeat-*, synthetics-*', + status: 'success', + }, + infra_logs: { hasData: true, indices: 'test-index', status: 'success' }, + infra_metrics: { hasData: true, indices: 'metric-*', status: 'success' }, + ux: { + hasData: true, + serviceName: 'ux', + indices: 'apm-*', + status: 'success', + }, + alert: { hasData: false, status: 'success' }, + universal_profiling: { hasData: false, status: 'success' }, }, - alert: { hasData: false, status: 'success' }, - universal_profiling: { hasData: false, status: 'success' }, - }, - hasAnyData: true, - isAllRequestsComplete: true, - forceUpdate: expect.any(String), - onRefreshTimeRange: expect.any(Function), - }); + hasAnyData: true, + isAllRequestsComplete: true, + forceUpdate: expect.any(String), + onRefreshTimeRange: expect.any(Function), + }) + ); }); }); @@ -297,7 +289,7 @@ describe('HasDataContextProvider', () => { afterAll(unregisterAll); it('hasAnyData returns true, apm returns true and all other apps return undefined', async () => { - const { result, waitForNextUpdate } = renderHook(() => useHasData(), { + const { result } = renderHook(() => useHasData(), { wrapper, }); expect(result.current).toEqual({ @@ -308,25 +300,23 @@ describe('HasDataContextProvider', () => { onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); - - expect(result.current).toEqual({ - hasDataMap: { - apm: { hasData: true, indices: sampleAPMIndices, status: 'success' }, - uptime: { hasData: undefined, status: 'success' }, - infra_logs: { hasData: undefined, status: 'success' }, - infra_metrics: { hasData: undefined, status: 'success' }, - ux: { hasData: undefined, status: 'success' }, - alert: { hasData: false, status: 'success' }, - universal_profiling: { hasData: false, status: 'success' }, - }, - hasAnyData: true, - isAllRequestsComplete: true, - forceUpdate: expect.any(String), - onRefreshTimeRange: expect.any(Function), - }); + await waitFor(() => + expect(result.current).toEqual({ + hasDataMap: { + apm: { hasData: true, indices: sampleAPMIndices, status: 'success' }, + uptime: { hasData: undefined, status: 'success' }, + infra_logs: { hasData: undefined, status: 'success' }, + infra_metrics: { hasData: undefined, status: 'success' }, + ux: { hasData: undefined, status: 'success' }, + alert: { hasData: false, status: 'success' }, + universal_profiling: { hasData: false, status: 'success' }, + }, + hasAnyData: true, + isAllRequestsComplete: true, + forceUpdate: expect.any(String), + onRefreshTimeRange: expect.any(Function), + }) + ); }); }); @@ -343,7 +333,7 @@ describe('HasDataContextProvider', () => { afterAll(unregisterAll); it('hasAnyData returns false, apm returns false and all other apps return undefined', async () => { - const { result, waitForNextUpdate } = renderHook(() => useHasData(), { + const { result } = renderHook(() => useHasData(), { wrapper, }); expect(result.current).toEqual({ @@ -354,29 +344,27 @@ describe('HasDataContextProvider', () => { onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); - - expect(result.current).toEqual({ - hasDataMap: { - apm: { - hasData: false, - indices: sampleAPMIndices, - status: 'success', + await waitFor(() => + expect(result.current).toEqual({ + hasDataMap: { + apm: { + hasData: false, + indices: sampleAPMIndices, + status: 'success', + }, + uptime: { hasData: undefined, status: 'success' }, + infra_logs: { hasData: undefined, status: 'success' }, + infra_metrics: { hasData: undefined, status: 'success' }, + ux: { hasData: undefined, status: 'success' }, + alert: { hasData: false, status: 'success' }, + universal_profiling: { hasData: false, status: 'success' }, }, - uptime: { hasData: undefined, status: 'success' }, - infra_logs: { hasData: undefined, status: 'success' }, - infra_metrics: { hasData: undefined, status: 'success' }, - ux: { hasData: undefined, status: 'success' }, - alert: { hasData: false, status: 'success' }, - universal_profiling: { hasData: false, status: 'success' }, - }, - hasAnyData: false, - isAllRequestsComplete: true, - forceUpdate: expect.any(String), - onRefreshTimeRange: expect.any(Function), - }); + hasAnyData: false, + isAllRequestsComplete: true, + forceUpdate: expect.any(String), + onRefreshTimeRange: expect.any(Function), + }) + ); }); }); }); @@ -412,7 +400,7 @@ describe('HasDataContextProvider', () => { afterAll(unregisterAll); it('hasAnyData returns true, apm is undefined and all other apps return true', async () => { - const { result, waitForNextUpdate } = renderHook(() => useHasData(), { wrapper }); + const { result } = renderHook(() => useHasData(), { wrapper }); expect(result.current).toEqual({ hasDataMap: { universal_profiling: { hasData: false, status: 'success' } }, hasAnyData: false, @@ -421,34 +409,32 @@ describe('HasDataContextProvider', () => { onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); - - expect(result.current).toEqual({ - hasDataMap: { - apm: { hasData: undefined, status: 'failure' }, - uptime: { - hasData: true, - indices: 'heartbeat-*, synthetics-*', - status: 'success', - }, - infra_logs: { hasData: true, indices: 'test-index', status: 'success' }, - infra_metrics: { hasData: true, indices: 'metric-*', status: 'success' }, - ux: { - hasData: true, - serviceName: 'ux', - indices: 'apm-*', - status: 'success', + await waitFor(() => + expect(result.current).toEqual({ + hasDataMap: { + apm: { hasData: undefined, status: 'failure' }, + uptime: { + hasData: true, + indices: 'heartbeat-*, synthetics-*', + status: 'success', + }, + infra_logs: { hasData: true, indices: 'test-index', status: 'success' }, + infra_metrics: { hasData: true, indices: 'metric-*', status: 'success' }, + ux: { + hasData: true, + serviceName: 'ux', + indices: 'apm-*', + status: 'success', + }, + alert: { hasData: false, status: 'success' }, + universal_profiling: { hasData: false, status: 'success' }, }, - alert: { hasData: false, status: 'success' }, - universal_profiling: { hasData: false, status: 'success' }, - }, - hasAnyData: true, - isAllRequestsComplete: true, - forceUpdate: expect.any(String), - onRefreshTimeRange: expect.any(Function), - }); + hasAnyData: true, + isAllRequestsComplete: true, + forceUpdate: expect.any(String), + onRefreshTimeRange: expect.any(Function), + }) + ); }); }); @@ -491,7 +477,7 @@ describe('HasDataContextProvider', () => { afterAll(unregisterAll); it('hasAnyData returns false and all apps return undefined', async () => { - const { result, waitForNextUpdate } = renderHook(() => useHasData(), { wrapper }); + const { result } = renderHook(() => useHasData(), { wrapper }); expect(result.current).toEqual({ hasDataMap: { universal_profiling: { hasData: false, status: 'success' } }, hasAnyData: false, @@ -500,25 +486,23 @@ describe('HasDataContextProvider', () => { onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); - - expect(result.current).toEqual({ - hasDataMap: { - apm: { hasData: undefined, status: 'failure' }, - uptime: { hasData: undefined, status: 'failure' }, - infra_logs: { hasData: undefined, status: 'failure' }, - infra_metrics: { hasData: undefined, status: 'failure' }, - ux: { hasData: undefined, status: 'failure' }, - alert: { hasData: false, status: 'success' }, - universal_profiling: { hasData: false, status: 'success' }, - }, - hasAnyData: false, - isAllRequestsComplete: true, - forceUpdate: expect.any(String), - onRefreshTimeRange: expect.any(Function), - }); + await waitFor(() => + expect(result.current).toEqual({ + hasDataMap: { + apm: { hasData: undefined, status: 'failure' }, + uptime: { hasData: undefined, status: 'failure' }, + infra_logs: { hasData: undefined, status: 'failure' }, + infra_metrics: { hasData: undefined, status: 'failure' }, + ux: { hasData: undefined, status: 'failure' }, + alert: { hasData: false, status: 'success' }, + universal_profiling: { hasData: false, status: 'success' }, + }, + hasAnyData: false, + isAllRequestsComplete: true, + forceUpdate: expect.any(String), + onRefreshTimeRange: expect.any(Function), + }) + ); }); }); }); @@ -538,7 +522,7 @@ describe('HasDataContextProvider', () => { }); it('returns if alerts are available', async () => { - const { result, waitForNextUpdate } = renderHook(() => useHasData(), { wrapper }); + const { result } = renderHook(() => useHasData(), { wrapper }); expect(result.current).toEqual({ hasDataMap: { universal_profiling: { hasData: false, status: 'success' } }, hasAnyData: false, @@ -547,25 +531,23 @@ describe('HasDataContextProvider', () => { onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); - - expect(result.current).toEqual({ - hasDataMap: { - apm: { hasData: undefined, status: 'success' }, - uptime: { hasData: undefined, status: 'success' }, - infra_logs: { hasData: undefined, status: 'success' }, - infra_metrics: { hasData: undefined, status: 'success' }, - ux: { hasData: undefined, status: 'success' }, - alert: { hasData: true, status: 'success' }, - universal_profiling: { hasData: false, status: 'success' }, - }, - hasAnyData: true, - isAllRequestsComplete: true, - forceUpdate: expect.any(String), - onRefreshTimeRange: expect.any(Function), - }); + await waitFor(() => + expect(result.current).toEqual({ + hasDataMap: { + apm: { hasData: undefined, status: 'success' }, + uptime: { hasData: undefined, status: 'success' }, + infra_logs: { hasData: undefined, status: 'success' }, + infra_metrics: { hasData: undefined, status: 'success' }, + ux: { hasData: undefined, status: 'success' }, + alert: { hasData: true, status: 'success' }, + universal_profiling: { hasData: false, status: 'success' }, + }, + hasAnyData: true, + isAllRequestsComplete: true, + forceUpdate: expect.any(String), + onRefreshTimeRange: expect.any(Function), + }) + ); }); }); }); diff --git a/x-pack/plugins/observability_solution/observability/public/hooks/use_fetch_alert_data.test.ts b/x-pack/plugins/observability_solution/observability/public/hooks/use_fetch_alert_data.test.ts index 3d148cf2283d1..f3b8dfaef848c 100644 --- a/x-pack/plugins/observability_solution/observability/public/hooks/use_fetch_alert_data.test.ts +++ b/x-pack/plugins/observability_solution/observability/public/hooks/use_fetch_alert_data.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, waitFor, renderHook } from '@testing-library/react'; import { kibanaStartMock } from '../utils/kibana_react.mock'; import { useFetchAlertData } from './use_fetch_alert_data'; @@ -39,16 +39,10 @@ describe('useFetchAlertData', () => { jest.clearAllMocks(); }); - it('initially is not loading and does not have data', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook]>( - () => useFetchAlertData(testIds) - ); + it('initially is loading and does not have data', async () => { + const { result } = renderHook(() => useFetchAlertData(testIds)); - await waitForNextUpdate(); - - expect(result.current).toEqual([false, {}]); - }); + expect(result.current).toEqual([true, {}]); }); it('returns no data when an error occurs', async () => { @@ -56,44 +50,31 @@ describe('useFetchAlertData', () => { throw new Error('an http error'); }); - await act(async () => { - const { result, waitForNextUpdate } = renderHook]>( - () => useFetchAlertData(testIds) - ); + const { result } = renderHook(() => useFetchAlertData(testIds)); - await waitForNextUpdate(); - - expect(result.current).toEqual([false, {}]); - }); + await waitFor(() => expect(result.current).toEqual([false, {}])); }); it('retrieves the alert data', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook]>( - () => useFetchAlertData(testIds) - ); - - await waitForNextUpdate(); - await waitForNextUpdate(); + const { result } = renderHook(() => useFetchAlertData(testIds)); + await waitFor(() => expect(result.current).toEqual([ false, { '123': { _id: '123', _index: 'index', testField: 'test' } }, - ]); - }); + ]) + ); }); it('does not populate the results when the request is canceled', async () => { - await act(async () => { - const { result, waitForNextUpdate, unmount } = renderHook< - string, - [boolean, Record] - >(() => useFetchAlertData(testIds)); + const { result, unmount } = renderHook(() => useFetchAlertData(testIds)); - await waitForNextUpdate(); + act(() => { unmount(); - - expect(result.current).toEqual([false, {}]); }); + + // unmounting the component should cancels the request in flight, + // and as such the loading value would actually be true since not the request is not resolved + expect(result.current).toEqual([true, {}]); }); }); diff --git a/x-pack/plugins/observability_solution/observability/public/hooks/use_fetch_alert_detail.test.ts b/x-pack/plugins/observability_solution/observability/public/hooks/use_fetch_alert_detail.test.ts index a35299bfb1033..8cc1a9db1505e 100644 --- a/x-pack/plugins/observability_solution/observability/public/hooks/use_fetch_alert_detail.test.ts +++ b/x-pack/plugins/observability_solution/observability/public/hooks/use_fetch_alert_detail.test.ts @@ -5,12 +5,12 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, waitFor, renderHook } from '@testing-library/react'; import { kibanaStartMock } from '../utils/kibana_react.mock'; import * as pluginContext from './use_plugin_context'; import { createObservabilityRuleTypeRegistryMock } from '..'; import { PluginContextValue } from '../context/plugin_context/plugin_context'; -import { AlertData, useFetchAlertDetail } from './use_fetch_alert_detail'; +import { useFetchAlertDetail } from './use_fetch_alert_detail'; const mockUseKibanaReturnValue = kibanaStartMock.startContract(); @@ -63,16 +63,10 @@ describe('useFetchAlertDetail', () => { jest.clearAllMocks(); }); - it('initially is not loading and does not have data', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useFetchAlertDetail(id) - ); + it('initially is loading and does not have data', () => { + const { result } = renderHook(() => useFetchAlertDetail(id)); - await waitForNextUpdate(); - - expect(result.current).toEqual([false, null]); - }); + expect(result.current).toEqual([true, null]); }); it('returns no data when an error occurs', async () => { @@ -80,26 +74,16 @@ describe('useFetchAlertDetail', () => { throw new Error('an http error'); }); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useFetchAlertDetail('123') - ); + const { result } = renderHook(() => useFetchAlertDetail('123')); - await waitForNextUpdate(); - - expect(result.current).toEqual([false, null]); - }); + await waitFor(() => expect(result.current).toEqual([false, null])); }); it('retrieves the alert data', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useFetchAlertDetail(id) - ); - - await waitForNextUpdate(); - await waitForNextUpdate(); + const { result } = renderHook(() => useFetchAlertDetail(id)); + await waitFor(() => { + expect(result.current[0]).toEqual(false); expect(result.current).toMatchInlineSnapshot(` Array [ false, @@ -180,16 +164,13 @@ describe('useFetchAlertDetail', () => { }); it('does not populate the results when the request is canceled', async () => { - await act(async () => { - const { result, waitForNextUpdate, unmount } = renderHook< - string, - [boolean, AlertData | null] - >(() => useFetchAlertDetail('123')); + const { result, unmount } = renderHook(() => useFetchAlertDetail('123')); - await waitForNextUpdate(); + act(() => { unmount(); - - expect(result.current).toEqual([false, null]); }); + + // since we unmount whilst the request is in flight the loading be true + await waitFor(() => expect(result.current).toEqual([true, null])); }); }); diff --git a/x-pack/plugins/observability_solution/observability/public/hooks/use_fetch_bulk_cases.test.ts b/x-pack/plugins/observability_solution/observability/public/hooks/use_fetch_bulk_cases.test.ts index 8e908abe5fcdd..ff5a8402cdd0e 100644 --- a/x-pack/plugins/observability_solution/observability/public/hooks/use_fetch_bulk_cases.test.ts +++ b/x-pack/plugins/observability_solution/observability/public/hooks/use_fetch_bulk_cases.test.ts @@ -6,7 +6,7 @@ */ import { useFetchBulkCases } from './use_fetch_bulk_cases'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { waitFor, renderHook } from '@testing-library/react'; import { kibanaStartMock } from '../utils/kibana_react.mock'; const mockUseKibanaReturnValue = kibanaStartMock.startContract(); @@ -18,11 +18,9 @@ jest.mock('../utils/kibana_react', () => ({ describe('Bulk Get Cases API hook', () => { it('initially is not loading and does not have data', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useFetchBulkCases({ ids: [] })); - - await waitForNextUpdate(); + const { result } = renderHook(() => useFetchBulkCases({ ids: [] })); + await waitFor(() => { expect(result.current.cases).toEqual([]); expect(result.current.error).toEqual(undefined); expect(result.current.isLoading).toEqual(false); diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alerts/components/alert_actions.test.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alerts/components/alert_actions.test.tsx index 32a9a70e76ab1..a4f3f93212846 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alerts/components/alert_actions.test.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alerts/components/alert_actions.test.tsx @@ -6,7 +6,6 @@ */ import React from 'react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { act } from '@testing-library/react-hooks'; import { mountWithIntl, nextTick } from '@kbn/test-jest-helpers'; import { kibanaStartMock } from '../../../utils/kibana_react.mock'; import { observabilityAIAssistantPluginMock } from '@kbn/observability-ai-assistant-plugin/public/mock'; @@ -20,7 +19,7 @@ import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; import { allCasesPermissions, noCasesPermissions } from '@kbn/observability-shared-plugin/public'; import { noop } from 'lodash'; import { EuiDataGridCellValueElementProps } from '@elastic/eui/src/components/datagrid/data_grid_types'; -import { waitFor } from '@testing-library/react'; +import { waitFor, act } from '@testing-library/react'; import { Router } from '@kbn/shared-ux-router'; import { createMemoryHistory } from 'history'; import { ObservabilityRuleTypeRegistry } from '../../../rules/create_observability_rule_type_registry'; diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/hooks/use_show_sections.test.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/hooks/use_show_sections.test.tsx index d7b485e56b34d..51de320b0d9dd 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/hooks/use_show_sections.test.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/hooks/use_show_sections.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useShowSections } from './use_show_sections'; describe('useShowSections', () => { diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.test.tsx index 185814b5ff0de..77979ae101ccd 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.test.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { waitFor, renderHook } from '@testing-library/react'; import type { FETCH_STATUS } from '@kbn/observability-shared-plugin/public'; import { useFetcher } from '@kbn/observability-shared-plugin/public'; @@ -38,10 +38,10 @@ describe('useRecentlyViewedMonitors', () => { }); it('returns expected result', () => { - const WrapperWithState = ({ children }: { children: React.ReactElement }) => { + const WrapperWithState = ({ children }: React.PropsWithChildren) => { return ( - {children} + {React.createElement(React.Fragment, null, children)} ); }; @@ -87,20 +87,17 @@ describe('useRecentlyViewedMonitors', () => { monitors: [fetchedMonitor], }); - const WrapperWithState = ({ children }: { children: React.ReactElement }) => { + const WrapperWithState = ({ children }: React.PropsWithChildren) => { return ( - {children} + {React.createElement(React.Fragment, null, children)} ); }; - const { result, waitForValueToChange, rerender } = renderHook( - () => useRecentlyViewedMonitors(), - { - wrapper: WrapperWithState, - } - ); - await waitForValueToChange(() => persistedIds); + const { result, rerender } = renderHook(() => useRecentlyViewedMonitors(), { + wrapper: WrapperWithState, + }); + await waitFor(() => persistedIds); // Sets the current monitor as well as updated information expect(setPersistedIdsMock).toHaveBeenCalledWith([currentMonitorQueryId, monitorQueryId3]); diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_details/monitor_status/use_monitor_status_data.test.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_details/monitor_status/use_monitor_status_data.test.ts index 44dd45991471f..50d49b906ea66 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_details/monitor_status/use_monitor_status_data.test.ts +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_details/monitor_status/use_monitor_status_data.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import React from 'react'; +import { renderHook, act } from '@testing-library/react'; import * as reactRedux from 'react-redux'; import { useBins, useMonitorStatusData } from './use_monitor_status_data'; import { WrappedHelper } from '../../../utils/testing'; @@ -13,6 +14,9 @@ import * as selectedMonitorHook from '../hooks/use_selected_monitor'; import * as selectedLocationHook from '../hooks/use_selected_location'; import { omit } from 'lodash'; +const Wrapper = ({ children }: React.PropsWithChildren) => + React.createElement(WrappedHelper, null, children); + describe('useMonitorStatusData', () => { let dispatchMock: jest.Mock; beforeEach(() => { @@ -65,7 +69,7 @@ describe('useMonitorStatusData', () => { initialSizeRef: { current: { clientWidth: 0 } as any }, }; const { result } = renderHook(() => useMonitorStatusData(props), { - wrapper: WrappedHelper, + wrapper: Wrapper, }); expect(result.current).toBeDefined(); expect(result.current.minsPerBin).toBeNull(); @@ -81,7 +85,7 @@ describe('useMonitorStatusData', () => { initialSizeRef: { current: { clientWidth: 0 } as any }, }; const { result } = renderHook(() => useMonitorStatusData(props), { - wrapper: WrappedHelper, + wrapper: Wrapper, }); await act(async () => { result.current.handleResize({ width: 250, height: 800 }); @@ -162,7 +166,7 @@ describe('useBins', () => { }, ], }), - { wrapper: WrappedHelper } + { wrapper: Wrapper } ); expect(result.current).toMatchInlineSnapshot(` Object { @@ -340,7 +344,7 @@ describe('useBins', () => { fromMillis: 1728310613654, toMillis: 1728313563654, }), - { wrapper: WrappedHelper } + { wrapper: Wrapper } ); expect(result.current).toMatchInlineSnapshot(` Object { diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/use_filters.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/use_filters.test.tsx index 3b949220342fb..3fd2b1093b711 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/use_filters.test.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/use_filters.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ import React from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useFilters } from './use_filters'; import { useDispatch } from 'react-redux'; import { WrappedHelper } from '../../../../utils/testing'; @@ -20,7 +20,11 @@ describe('useMonitorListFilters', () => { jest.useFakeTimers(); it('returns expected results', () => { - const { result } = renderHook(() => useFilters(), { wrapper: WrappedHelper }); + const { result } = renderHook(() => useFilters(), { + wrapper: ({ children }: React.PropsWithChildren) => ( + {React.createElement(React.Fragment, {}, children)} + ), + }); expect(result.current).toStrictEqual({ locations: [], @@ -32,7 +36,7 @@ describe('useMonitorListFilters', () => { }); it('dispatches action when filters are null', () => { - const Wrapper = ({ children }: { children: React.ReactElement }) => { + const Wrapper = ({ children }: React.PropsWithChildren) => { return ( { }, }} > - {children} + {React.createElement(React.Fragment, null, children)} ); }; @@ -67,7 +71,7 @@ describe('useMonitorListFilters', () => { projects: [], schedules: [], }; - const Wrapper = ({ children }: { children: React.ReactElement }) => { + const Wrapper = ({ children }: React.PropsWithChildren) => { return ( { }, }} > - {children} + {React.createElement(React.Fragment, null, children)} ); }; diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_monitor_list.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_monitor_list.test.tsx index 05741f7aa0cac..a8c829376762c 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_monitor_list.test.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_monitor_list.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import * as redux from 'react-redux'; import { MONITOR_ROUTE } from '../../../../../../common/constants'; import { mockState } from '../../../utils/testing/__mocks__/synthetics_store.mock'; @@ -54,7 +54,9 @@ describe('useMonitorList', () => { it('returns expected initial state', () => { const { result: { current: hookResult }, - } = renderHook(() => useMonitorList(), { wrapper: WrappedHelper }); + } = renderHook(() => useMonitorList(), { + wrapper: ({ children }) => React.createElement(WrappedHelper, null, children), + }); expect(hookResult).toMatchObject({ ...initialState, handleFilterChange: expect.any(Function) }); }); @@ -64,10 +66,10 @@ describe('useMonitorList', () => { const url = `/monitor/1?query=${query}`; jest.useFakeTimers().setSystemTime(Date.now()); - const WrapperWithState = ({ children }: { children: React.ReactElement }) => { + const WrapperWithState = ({ children }: React.PropsWithChildren) => { return ( - {children} + {React.createElement(React.Fragment, {}, children)} ); }; @@ -97,10 +99,10 @@ describe('useMonitorList', () => { )}&projects=${JSON.stringify(exp.projects)}`; jest.useFakeTimers().setSystemTime(Date.now()); - const WrapperWithState = ({ children }: { children: React.ReactElement }) => { + const WrapperWithState = ({ children }: React.PropsWithChildren) => { return ( - {children} + {React.createElement(React.Fragment, {}, children)} ); }; diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/hooks/use_get_data_stream_statuses.test.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/hooks/use_get_data_stream_statuses.test.ts index 67cf9589fb818..7abd273c89e9d 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/hooks/use_get_data_stream_statuses.test.ts +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/hooks/use_get_data_stream_statuses.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { FETCH_STATUS, useFetcher } from '@kbn/observability-shared-plugin/public'; import { useGetDataStreamStatuses } from './use_get_data_stream_statuses'; diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/hooks/use_get_ilm_policies.test.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/hooks/use_get_ilm_policies.test.ts index 3f5dba93db975..6ee6dfe568254 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/hooks/use_get_ilm_policies.test.ts +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/hooks/use_get_ilm_policies.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { renderHook } from '@testing-library/react-hooks'; +import { waitFor, renderHook } from '@testing-library/react'; import { useGetIlmPolicies } from './use_get_ilm_policies'; import * as hookPolicyAPI from './api'; @@ -23,8 +23,8 @@ describe('useGetIlmPolicies', () => { }); it('returns the correct data', async () => { - const { result, waitForNextUpdate } = renderHook(() => useGetIlmPolicies()); - await waitForNextUpdate(); + const { result } = renderHook(() => useGetIlmPolicies()); + await waitFor(() => new Promise((resolve) => resolve(null))); expect(result.current.data).toEqual([ { currentSize: '434 MB', diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_location_monitors.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_location_monitors.test.tsx index a2f20894ed80d..c2065e6851f5a 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_location_monitors.test.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_location_monitors.test.tsx @@ -5,8 +5,9 @@ * 2.0. */ +import { createElement } from 'react'; import * as reactRedux from 'react-redux'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { WrappedHelper } from '../../../../utils/testing'; import { useLocationMonitors } from './use_location_monitors'; @@ -27,7 +28,9 @@ describe('useLocationMonitors', () => { it('returns expected results', () => { useSelectorSpy.mockReturnValue({ locationMonitors: [], loading: false }); - const { result } = renderHook(() => useLocationMonitors(), { wrapper: WrappedHelper }); + const { result } = renderHook(() => useLocationMonitors(), { + wrapper: ({ children }) => createElement(WrappedHelper, null, children), + }); expect(result.current).toStrictEqual({ locationMonitors: [], loading: false }); }); @@ -46,7 +49,7 @@ describe('useLocationMonitors', () => { it('returns expected results after data', async () => { const { result } = renderHook(() => useLocationMonitors(), { - wrapper: WrappedHelper, + wrapper: ({ children }) => createElement(WrappedHelper, null, children), }); expect(result.current).toStrictEqual({ diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.test.tsx index ea8430cba5569..279a0b2a57af6 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.test.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { createElement } from 'react'; +import { act, waitFor, renderHook } from '@testing-library/react'; import { WrappedHelper } from '../../../../utils/testing'; import { getServiceLocations } from '../../../../state/service_locations'; import { setAddingNewPrivateLocation } from '../../../../state/private_locations'; @@ -24,7 +25,7 @@ describe('usePrivateLocationsAPI', () => { it('returns expected results', () => { const { result } = renderHook(() => usePrivateLocationsAPI(), { - wrapper: WrappedHelper, + wrapper: ({ children }) => createElement(WrappedHelper, null, children), }); expect(result.current).toEqual( @@ -42,8 +43,8 @@ describe('usePrivateLocationsAPI', () => { } as any, ]); it('returns expected results after data', async () => { - const { result, waitForNextUpdate } = renderHook(() => usePrivateLocationsAPI(), { - wrapper: WrappedHelper, + const { result } = renderHook(() => usePrivateLocationsAPI(), { + wrapper: ({ children }) => createElement(WrappedHelper, null, children), }); expect(result.current).toEqual( @@ -53,22 +54,22 @@ describe('usePrivateLocationsAPI', () => { }) ); - await waitForNextUpdate(); - - expect(result.current).toEqual( - expect.objectContaining({ - loading: false, - privateLocations: [], - }) + await waitFor(() => + expect(result.current).toEqual( + expect.objectContaining({ + loading: false, + privateLocations: [], + }) + ) ); }); it('adds location on submit', async () => { - const { result, waitForNextUpdate } = renderHook(() => usePrivateLocationsAPI(), { - wrapper: WrappedHelper, + const { result } = renderHook(() => usePrivateLocationsAPI(), { + wrapper: ({ children }) => createElement(WrappedHelper, null, children), }); - await waitForNextUpdate(); + await waitFor(() => new Promise((resolve) => resolve(null))); act(() => { result.current.onSubmit({ @@ -81,35 +82,35 @@ describe('usePrivateLocationsAPI', () => { }); }); - await waitForNextUpdate(); - - expect(addAPI).toHaveBeenCalledWith({ - geo: { - lat: 0, - lon: 0, - }, - label: 'new', - agentPolicyId: 'newPolicy', + await waitFor(() => { + expect(addAPI).toHaveBeenCalledWith({ + geo: { + lat: 0, + lon: 0, + }, + label: 'new', + agentPolicyId: 'newPolicy', + }); + expect(dispatch).toBeCalledWith(setAddingNewPrivateLocation(false)); + expect(dispatch).toBeCalledWith(getServiceLocations()); }); - expect(dispatch).toBeCalledWith(setAddingNewPrivateLocation(false)); - expect(dispatch).toBeCalledWith(getServiceLocations()); }); it('deletes location on delete', async () => { - const { result, waitForNextUpdate } = renderHook(() => usePrivateLocationsAPI(), { - wrapper: WrappedHelper, + const { result } = renderHook(() => usePrivateLocationsAPI(), { + wrapper: ({ children }) => createElement(WrappedHelper, null, children), }); - await waitForNextUpdate(); + await waitFor(() => new Promise((resolve) => resolve(null))); act(() => { result.current.onDelete('Test'); }); - await waitForNextUpdate(); - - expect(deletedAPI).toHaveBeenLastCalledWith('Test'); - expect(dispatch).toBeCalledWith(setAddingNewPrivateLocation(false)); - expect(dispatch).toBeCalledWith(getServiceLocations()); + await waitFor(() => { + expect(deletedAPI).toHaveBeenLastCalledWith('Test'); + expect(dispatch).toBeCalledWith(setAddingNewPrivateLocation(false)); + expect(dispatch).toBeCalledWith(getServiceLocations()); + }); }); }); diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/use_step_waterfall_metrics.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/use_step_waterfall_metrics.test.tsx index 17034c2153c52..743dfa9ff046f 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/use_step_waterfall_metrics.test.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/use_step_waterfall_metrics.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { BROWSER_TRACE_NAME, BROWSER_TRACE_START, diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/use_bar_charts.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/use_bar_charts.test.tsx index 24c1c074bd86a..9ace447221d8d 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/use_bar_charts.test.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/use_bar_charts.test.tsx @@ -6,7 +6,7 @@ */ import { useBarCharts } from './use_bar_charts'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { IWaterfallContext } from './context/waterfall_context'; import { CANVAS_MAX_ITEMS } from './constants'; diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/use_flyout.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/use_flyout.test.tsx index 0476f46e11f2a..2cdb150948c6e 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/use_flyout.test.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/use_flyout.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; import { useFlyout } from './use_flyout'; import { IWaterfallContext } from '../context/waterfall_context'; diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_absolute_date.test.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_absolute_date.test.ts index 94e9178a7299e..2561ede50abb3 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_absolute_date.test.ts +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_absolute_date.test.ts @@ -6,7 +6,7 @@ */ import datemath from '@elastic/datemath'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import moment, { Moment } from 'moment'; import { useAbsoluteDate } from './use_absolute_date'; diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_composite_image.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_composite_image.test.tsx index 9660490515549..ae0f1342d8c03 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_composite_image.test.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_composite_image.test.tsx @@ -6,7 +6,7 @@ */ import * as redux from 'react-redux'; -import { renderHook } from '@testing-library/react-hooks'; +import { waitFor, renderHook } from '@testing-library/react'; import { ScreenshotRefImageData, ScreenshotBlockCache } from '../../../../common/runtime_types'; import { fetchBlocksAction } from '../state'; import { shouldCompose, useComposeImageFromRef } from './use_composite_image'; @@ -148,6 +148,17 @@ describe('use composite image', () => { let removeChildSpy: jest.Mock; let selectorSpy: jest.SpyInstance; let composeSpy: jest.SpyInstance; + let documentCreateElementSpy: jest.SpyInstance< + ReturnType, + Parameters + >; + + // store reference to original document.createElement + const superCreateElement = document.createElement; + + beforeAll(() => { + documentCreateElementSpy = jest.spyOn(document, 'createElement'); + }); beforeEach(() => { useDispatchMock = jest.fn(); @@ -158,8 +169,16 @@ describe('use composite image', () => { }, toDataURL: jest.fn().mockReturnValue('compose success'), }; + // @ts-expect-error mocking canvas element for testing - jest.spyOn(document, 'createElement').mockReturnValue(canvasMock); + documentCreateElementSpy.mockImplementation(function (tagName, options) { + if (tagName === 'canvas') { + return canvasMock; + } + + return superCreateElement.call(document, tagName, options); + }); + jest.spyOn(redux, 'useDispatch').mockReturnValue(useDispatchMock); selectorSpy = jest.spyOn(redux, 'useSelector').mockReturnValue({ blocks }); composeSpy = jest @@ -179,7 +198,7 @@ describe('use composite image', () => { }); it('composes when all required blocks are loaded 2', async () => { - const { waitFor, result } = renderHook(() => useComposeImageFromRef(imgRef)); + const { result } = renderHook(() => useComposeImageFromRef(imgRef)); expect(selectorSpy).toHaveBeenCalled(); expect(result.current.isComposing).toBeTruthy(); diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_location_name.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_location_name.test.tsx index 0a92712d282a5..598112c972c32 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_location_name.test.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_location_name.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ import React from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useLocationName } from './use_location_name'; import { WrappedHelper } from '../utils/testing'; import { OverviewStatusMetaData } from '../../../../common/runtime_types'; @@ -16,7 +16,7 @@ describe('useLocationName', () => { }); it('returns expected label', () => { - const WrapperWithState = ({ children }: { children: React.ReactElement }) => { + const WrapperWithState = ({ children }: React.PropsWithChildren) => { return ( { }, }} > - {children} + {React.createElement(React.Fragment, null, children)} ); }; @@ -56,7 +56,7 @@ describe('useLocationName', () => { }); it('returns the location id if matching location cannot be found', () => { - const WrapperWithState = ({ children }: { children: React.ReactElement }) => { + const WrapperWithState = ({ children }: React.PropsWithChildren) => { return ( { }, }} > - {children} + {React.createElement(React.Fragment, null, children)} ); }; diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_monitor_name.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_monitor_name.test.tsx index af7700f549d88..f4a2294e4f4c6 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_monitor_name.test.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_monitor_name.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { renderHook } from '@testing-library/react-hooks'; +import { waitFor, renderHook } from '@testing-library/react'; import { fetchMonitorManagementList } from '../state'; import { useMonitorName } from './use_monitor_name'; @@ -54,7 +54,7 @@ describe('useMonitorName', () => { }); it('returns expected initial and after load state', async () => { - const { result, waitForValueToChange } = renderHook(() => useMonitorName({})); + const { result } = renderHook(() => useMonitorName({})); expect(result.current).toStrictEqual({ loading: true, @@ -62,7 +62,7 @@ describe('useMonitorName', () => { nameAlreadyExists: false, }); - await waitForValueToChange(() => result.current.values); + await waitFor(() => result.current.values); expect(result.current).toStrictEqual({ loading: false, @@ -78,11 +78,9 @@ describe('useMonitorName', () => { }); it('returns correct "nameAlreadyExists" when name matches', async () => { - const { result, waitForValueToChange } = renderHook(() => - useMonitorName({ search: 'Test monitor name 2' }) - ); + const { result } = renderHook(() => useMonitorName({ search: 'Test monitor name 2' })); - await waitForValueToChange(() => result.current.values); // Wait until data has been loaded + await waitFor(() => result.current.values); // Wait until data has been loaded expect(result.current).toStrictEqual({ loading: false, nameAlreadyExists: true, @@ -97,11 +95,9 @@ describe('useMonitorName', () => { }); it('returns expected results after data while editing monitor', async () => { - const { result, waitForValueToChange } = renderHook(() => - useMonitorName({ search: 'Test monitor name' }) - ); + const { result } = renderHook(() => useMonitorName({ search: 'Test monitor name' })); - await waitForValueToChange(() => result.current.values); // Wait until data has been loaded + await waitFor(() => result.current.values); // Wait until data has been loaded expect(result.current).toStrictEqual({ loading: false, nameAlreadyExists: false, // Should be `false` for the currently editing monitor, diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_monitors_sorted_by_status.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_monitors_sorted_by_status.test.tsx index a8f3dee54f07d..9e2c2c30cabe9 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_monitors_sorted_by_status.test.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_monitors_sorted_by_status.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ import React from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { SyntheticsUrlParams } from '../utils/url_params/get_supported_url_params'; import { useMonitorsSortedByStatus } from './use_monitors_sorted_by_status'; import { WrappedHelper } from '../utils/testing'; @@ -37,10 +37,9 @@ describe('useMonitorsSortedByStatus', () => { const WrapperWithState = ({ children, sortOrder = 'asc', - }: { - children: React.ReactElement; + }: React.PropsWithChildren<{ sortOrder: 'asc' | 'desc'; - }) => { + }>) => { return ( { }, }} > - {children} + {React.createElement(React.Fragment, null, children)} ); }; it('returns monitors down first when sort order is asc', () => { const { result } = renderHook(() => useMonitorsSortedByStatus(), { - wrapper: WrapperWithState, + wrapper: ({ children }) => React.createElement(WrapperWithState, null, children), }); expect(result.current).toMatchInlineSnapshot(` Array [ @@ -167,7 +166,7 @@ describe('useMonitorsSortedByStatus', () => { it('returns monitors up first when sort order is desc', () => { const { result } = renderHook(() => useMonitorsSortedByStatus(), { - wrapper: ({ children }: { children: React.ReactElement }) => ( + wrapper: ({ children }: React.PropsWithChildren) => ( {children} ), }); @@ -223,7 +222,7 @@ describe('useMonitorsSortedByStatus', () => { } as SyntheticsUrlParams); const { result } = renderHook(() => useMonitorsSortedByStatus(), { - wrapper: ({ children }: { children: React.ReactElement }) => ( + wrapper: ({ children }: React.PropsWithChildren) => ( {children} ), }); @@ -254,7 +253,7 @@ describe('useMonitorsSortedByStatus', () => { } as SyntheticsUrlParams); const { result } = renderHook(() => useMonitorsSortedByStatus(), { - wrapper: ({ children }: { children: React.ReactElement }) => ( + wrapper: ({ children }: React.PropsWithChildren) => ( {children} ), }); @@ -285,7 +284,7 @@ describe('useMonitorsSortedByStatus', () => { } as SyntheticsUrlParams); const { result } = renderHook(() => useMonitorsSortedByStatus(), { - wrapper: ({ children }: { children: React.ReactElement }) => ( + wrapper: ({ children }: React.PropsWithChildren) => ( {children} ), }); diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_synthetics_priviliges.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_synthetics_priviliges.test.tsx index 7d496b3940da8..53b3287c60105 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_synthetics_priviliges.test.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_synthetics_priviliges.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import React from 'react'; import { render, WrappedHelper } from '../utils/testing'; import { useSyntheticsPrivileges } from './use_synthetics_priviliges'; @@ -22,7 +22,7 @@ jest.mock('react-redux', () => { }; }); -function wrapper({ children }: { children: React.ReactElement }) { +function wrapper({ children }: React.PropsWithChildren) { return {children}; } diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx index 1b359a319b332..8a92c23eec27a 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx @@ -249,7 +249,7 @@ export function WrappedHelper({ useRealStore, path, history = createMemoryHistory(), -}: RenderRouterOptions & { children: ReactElement; useRealStore?: boolean }) { +}: React.PropsWithChildren & { useRealStore?: boolean }>) { const testState: AppState = mergeWith({}, mockState, state, (objValue, srcValue) => { if (Array.isArray(objValue)) { return srcValue; diff --git a/x-pack/plugins/observability_solution/synthetics/public/hooks/use_date_format.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/hooks/use_date_format.test.tsx index fac97ba610377..2757835c50e93 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/hooks/use_date_format.test.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/hooks/use_date_format.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { i18n } from '@kbn/i18n'; jest.mock('@kbn/i18n', () => ({ diff --git a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/step_detail/use_step_waterfall_metrics.test.tsx b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/step_detail/use_step_waterfall_metrics.test.tsx index f5c79e10f1626..a8b19dea83839 100644 --- a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/step_detail/use_step_waterfall_metrics.test.tsx +++ b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/step_detail/use_step_waterfall_metrics.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { BROWSER_TRACE_NAME, BROWSER_TRACE_START, diff --git a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/waterfall/components/use_bar_charts.test.tsx b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/waterfall/components/use_bar_charts.test.tsx index a963fb1e2939c..eec6aadc07597 100644 --- a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/waterfall/components/use_bar_charts.test.tsx +++ b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/waterfall/components/use_bar_charts.test.tsx @@ -6,7 +6,7 @@ */ import { useBarCharts } from './use_bar_charts'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { IWaterfallContext } from '../context/waterfall_chart'; import { CANVAS_MAX_ITEMS } from './constants'; diff --git a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/waterfall/components/use_flyout.test.tsx b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/waterfall/components/use_flyout.test.tsx index 5b388874d508e..0fe4d8dda69b3 100644 --- a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/waterfall/components/use_flyout.test.tsx +++ b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/monitor/synthetics/waterfall/components/use_flyout.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; import { useFlyout } from './use_flyout'; import { IWaterfallContext } from '../context/waterfall_chart'; diff --git a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/overview/query_bar/use_query_bar.test.tsx b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/overview/query_bar/use_query_bar.test.tsx index 4a9c459dd36ea..90799ded861e8 100644 --- a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/overview/query_bar/use_query_bar.test.tsx +++ b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/overview/query_bar/use_query_bar.test.tsx @@ -6,8 +6,7 @@ */ import React from 'react'; -import { waitFor } from '@testing-library/react'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { waitFor, renderHook, act } from '@testing-library/react'; import { MockRouter, MockKibanaProvider } from '../../../lib/helper/rtl_helpers'; import { SyntaxType, useQueryBar, DEBOUNCE_INTERVAL } from './use_query_bar'; import { MountWithReduxProvider } from '../../../lib'; diff --git a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/synthetics/check_steps/use_expanded_row.test.tsx b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/synthetics/check_steps/use_expanded_row.test.tsx index a139abe5d86a0..1445ec8e3332a 100644 --- a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/synthetics/check_steps/use_expanded_row.test.tsx +++ b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/components/synthetics/check_steps/use_expanded_row.test.tsx @@ -8,8 +8,7 @@ import React from 'react'; import ReactRouterDom from 'react-router-dom'; import { Route } from '@kbn/shared-ux-router'; -import { fireEvent, screen } from '@testing-library/react'; -import { renderHook, act as hooksAct } from '@testing-library/react-hooks'; +import { fireEvent, screen, renderHook, act as hooksAct } from '@testing-library/react'; import { createMemoryHistory } from 'history'; import { EuiButtonIcon } from '@elastic/eui'; import { getExpandedStepCallback, useExpandedRow } from './use_expanded_row'; @@ -217,7 +216,9 @@ describe('useExpandedROw', () => { }) ); - result.current.toggleExpand({ journeyStep: defaultSteps[0] }); + act(() => { + result.current.toggleExpand({ journeyStep: defaultSteps[0] }); + }); expect(result.current.expandedRows[0].props.browserConsoles).toEqual([ browserConsoleStep.synthetics.payload.text, diff --git a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/hooks/use_composite_image.test.tsx b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/hooks/use_composite_image.test.tsx index d26342aca54c5..2797a8de19740 100644 --- a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/hooks/use_composite_image.test.tsx +++ b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/hooks/use_composite_image.test.tsx @@ -6,7 +6,7 @@ */ import * as redux from 'react-redux'; -import { renderHook } from '@testing-library/react-hooks'; +import { waitFor, renderHook } from '@testing-library/react'; import { ScreenshotRefImageData, ScreenshotBlockCache } from '../../../common/runtime_types'; import { shouldCompose, useCompositeImage } from './use_composite_image'; import * as compose from '../lib/helper/compose_screenshot_images'; @@ -147,6 +147,17 @@ describe('use composite image', () => { let removeChildSpy: jest.Mock; let selectorSpy: jest.SpyInstance; let composeSpy: jest.SpyInstance; + let documentCreateElementSpy: jest.SpyInstance< + ReturnType, + Parameters + >; + + // store reference to original document.createElement + const superCreateElement = document.createElement; + + beforeAll(() => { + documentCreateElementSpy = jest.spyOn(document, 'createElement'); + }); beforeEach(() => { useDispatchMock = jest.fn(); @@ -158,7 +169,13 @@ describe('use composite image', () => { toDataURL: jest.fn().mockReturnValue('compose success'), }; // @ts-expect-error mocking canvas element for testing - jest.spyOn(document, 'createElement').mockReturnValue(canvasMock); + documentCreateElementSpy.mockImplementation(function (tagName, options) { + if (tagName === 'canvas') { + return canvasMock; + } + + return superCreateElement.call(document, tagName, options); + }); jest.spyOn(redux, 'useDispatch').mockReturnValue(useDispatchMock); selectorSpy = jest.spyOn(redux, 'useSelector').mockReturnValue({ blocks }); composeSpy = jest @@ -182,7 +199,7 @@ describe('use composite image', () => { it('composes when all required blocks are loaded', async () => { const onComposeImageSuccess = jest.fn(); - const { waitFor } = renderHook(() => useCompositeImage(imgRef, onComposeImageSuccess)); + renderHook(() => useCompositeImage(imgRef, onComposeImageSuccess)); expect(selectorSpy).toHaveBeenCalled(); expect(composeSpy).toHaveBeenCalledTimes(1); diff --git a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/hooks/use_filter_update.test.ts b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/hooks/use_filter_update.test.ts index 734b018a6b624..05f507b7da839 100644 --- a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/hooks/use_filter_update.test.ts +++ b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/hooks/use_filter_update.test.ts @@ -4,7 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { renderHook } from '@testing-library/react-hooks'; + +import { renderHook } from '@testing-library/react'; import { addUpdatedField, useFilterUpdate } from './use_filter_update'; import * as params from './use_url_params'; diff --git a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/hooks/use_overview_filter_check.test.tsx b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/hooks/use_overview_filter_check.test.tsx index 9fd0a07033120..d203e01dbd577 100644 --- a/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/hooks/use_overview_filter_check.test.tsx +++ b/x-pack/plugins/observability_solution/uptime/public/legacy_uptime/hooks/use_overview_filter_check.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { createMemoryHistory } from 'history'; import React, { FC, PropsWithChildren } from 'react'; import * as reactRedux from 'react-redux';