From 6945e4769cb9606c9043ecf0b5d8e5b700c093b7 Mon Sep 17 00:00:00 2001 From: Eyo Okon Eyo Date: Thu, 12 Sep 2024 17:29:50 +0200 Subject: [PATCH 01/18] swap waitForNextUpdate for waitFor --- ...use_data_grid_column_cell_actions.test.tsx | 36 +- .../src/hooks/use_load_actions.test.ts | 49 +- .../src/hooks/use_grouping.test.tsx | 10 +- .../index.test.ts | 56 +- .../src/use_async/index.test.ts | 32 +- .../src/use_find_lists/index.test.ts | 5 +- .../src/hooks/use_existing_fields.test.tsx | 34 +- .../src/hooks/use_grouped_fields.test.tsx | 67 +-- .../hooks/use_root_profile.test.tsx | 11 +- .../public/hooks/use_data_view.test.tsx | 3 +- .../hooks/use_navigation_props.test.tsx | 3 +- .../embeddables/embeddable_renderer.test.tsx | 4 +- .../public/hooks/use_es_doc_search.test.tsx | 4 +- .../public/utils/use/use_ui_state.test.ts | 5 +- .../utils/use/use_saved_vis_instance.test.ts | 21 +- .../utils/use/use_visualize_app_state.test.ts | 11 +- .../use_fetch_anonymization_fields.test.tsx | 7 +- .../api/conversations/conversations.test.tsx | 11 +- ..._fetch_current_user_conversations.test.tsx | 9 +- .../evaluate/use_perform_evaluation.test.tsx | 19 +- .../use_delete_knowledge_base.test.tsx | 19 +- .../use_knowledge_base_status.test.tsx | 21 +- .../use_setup_knowledge_base.test.tsx | 19 +- .../api/prompts/use_fetch_prompts.test.tsx | 7 +- .../use_settings_updater.test.tsx | 24 +- .../assistant/use_conversation/index.test.tsx | 96 ++-- .../use_load_action_types/index.test.tsx | 17 +- .../use_load_connectors/index.test.tsx | 17 +- .../hooks/use_ilm_explain/index.test.tsx | 15 +- .../pattern/hooks/use_stats/index.test.tsx | 12 +- .../configure/use_action_types.test.tsx | 5 +- .../use_get_all_case_configurations.test.ts | 9 +- .../use_get_case_configuration.test.tsx | 17 +- ...t_supported_action_connectors.tsx.test.tsx | 31 +- .../containers/use_bulk_update_case.test.tsx | 19 +- .../use_create_attachments.test.tsx | 15 +- .../containers/use_delete_cases.test.tsx | 19 +- .../containers/use_delete_comment.test.tsx | 19 +- .../use_delete_file_attachment.test.tsx | 19 +- .../use_find_case_user_actions.test.tsx | 25 +- .../use_get_action_license.test.tsx | 9 +- .../public/containers/use_get_case.test.tsx | 8 +- .../use_get_case_file_stats.test.tsx | 9 +- .../containers/use_get_case_files.test.tsx | 9 +- .../containers/use_get_case_metrics.test.tsx | 9 +- .../use_get_case_user_actions_stats.test.tsx | 19 +- .../containers/use_get_case_users.test.tsx | 9 +- .../containers/use_get_cases_metrics.test.tsx | 9 +- .../containers/use_get_cases_status.test.tsx | 9 +- .../containers/use_get_categories.test.tsx | 17 +- .../containers/use_get_feature_ids.test.tsx | 8 +- .../public/containers/use_get_tags.test.tsx | 17 +- ...e_infinite_find_case_user_actions.test.tsx | 24 +- .../containers/use_messages_storage.test.tsx | 39 +- .../public/containers/use_post_case.test.tsx | 19 +- .../use_post_push_to_service.test.tsx | 19 +- .../use_replace_custom_field.test.tsx | 23 +- .../containers/use_update_case.test.tsx | 19 +- .../containers/use_update_comment.test.tsx | 15 +- .../rules/use_change_csp_rule_state.test.tsx | 19 +- .../use_fields_metadata.test.ts | 13 +- .../fleet/hooks/use_apm_service_href.test.ts | 10 +- .../hooks.test.tsx | 42 +- .../hooks/setup_technology.test.ts | 41 +- .../hooks/use_package_policy.test.tsx | 13 +- .../hooks/use_agent_soft_limit.test.tsx | 8 +- .../hooks/use_fetch_agents_data.test.tsx | 19 +- .../hooks/use_fleet_server_unhealthy.test.tsx | 12 +- .../public/hooks/use_agent_version.test.ts | 33 +- .../public/mock/create_test_renderer.tsx | 5 +- .../hooks/persist_exception_item.test.ts | 56 +- .../hooks/persist_exception_list.test.ts | 45 +- .../public/exceptions/hooks/use_api.test.ts | 353 ++++++------- .../hooks/use_exception_lists.test.ts | 404 +++++++-------- .../lists/hooks/use_create_list_index.test.ts | 24 +- .../lists/hooks/use_delete_list.test.ts | 7 +- .../lists/hooks/use_export_list.test.ts | 7 +- .../lists/hooks/use_import_list.test.ts | 15 +- .../lists/hooks/use_read_list_index.test.ts | 23 +- .../plugins/ml/common/types/storage.test.tsx | 43 +- .../hooks/use_as_observable.test.ts | 8 +- .../application/routing/use_resolver.test.ts | 5 +- ..._failed_transactions_correlations.test.tsx | 10 +- .../use_container_metrics_charts.test.ts | 17 +- .../hooks/use_host_metrics_charts.test.ts | 31 +- .../public/hooks/use_alerts_count.test.ts | 13 +- .../public/hooks/use_lens_attributes.test.ts | 9 +- .../pages/link_to/use_host_ip_to_name.test.ts | 15 +- .../hosts/hooks/use_metrics_charts.test.ts | 13 +- .../hooks/use_metrics_explorer_data.test.tsx | 37 +- .../logs/log_summary/log_summary.test.tsx | 23 +- .../has_data_context.test.tsx | 57 +- .../public/hooks/use_fetch_alert_data.test.ts | 32 +- .../hooks/use_fetch_alert_detail.test.ts | 158 +++--- .../public/hooks/use_fetch_bulk_cases.test.ts | 7 +- .../hooks/use_get_ilm_policies.test.ts | 5 +- .../hooks/use_locations_api.test.tsx | 17 +- .../public/hooks/use_load_connectors.test.ts | 37 +- .../public/hooks/use_management_link.test.ts | 5 +- .../hooks/use_source_indices_fields.test.tsx | 11 +- .../get_comments/stream/use_stream.test.tsx | 7 +- .../public/assistant/provider.test.tsx | 77 ++- .../guided_onboarding_tour/tour.test.tsx | 19 +- .../ml/anomaly/use_anomalies_search.test.ts | 163 +++--- .../hooks/use_installed_security_jobs.test.ts | 16 +- .../hooks/use_enable_data_feed.test.tsx | 13 +- .../hooks/use_security_jobs.test.ts | 13 +- .../use_bulk_get_user_profiles.test.tsx | 12 +- .../use_get_current_user_profile.test.tsx | 5 +- .../user_profiles/use_suggest_users.test.tsx | 5 +- .../events/last_event_time/index.test.ts | 84 ++- .../use_messages_storage.test.tsx | 59 +-- .../common/containers/source/index.test.tsx | 51 +- .../common/hooks/use_fetch/use_fetch.test.tsx | 73 +-- .../public/common/links/links.test.tsx | 34 +- .../utils/global_query_string/index.test.tsx | 7 +- .../utils/timeline/use_show_timeline.test.tsx | 45 +- .../use_fetch_security_dashboards.test.ts | 9 +- .../use_fetch_security_tags.test.ts | 7 +- ...se_create_security_dashboard_link.test.tsx | 14 +- .../use_security_dashboards_table.test.tsx | 11 +- ...tch_or_create_rule_exception_list.test.tsx | 236 +++------ .../use_dissasociate_exception_list.test.ts | 7 +- .../use_execution_events.test.tsx | 15 +- .../use_execution_results.test.tsx | 15 +- .../group_take_action_items.test.tsx | 225 ++++---- .../use_integrations.test.tsx | 15 +- .../components/user_info/index.test.tsx | 53 +- .../alerts/use_alerts_privileges.test.tsx | 188 +++---- .../alerts/use_cases_from_alerts.test.tsx | 7 +- .../alerts/use_query.test.tsx | 166 +++--- .../rules/use_rule_from_timeline.test.ts | 23 +- .../use_cell_actions.test.tsx | 10 +- .../cases_table/use_case_items.test.ts | 24 +- .../soc_trends/hooks/use_cases_mttr.test.tsx | 333 ++++++------ .../hooks/use_critical_alerts.test.tsx | 341 ++++++------ .../soc_trends/hooks/use_soc_trends.test.tsx | 73 ++- .../sourcerer/containers/hooks.test.tsx | 490 ++++++++---------- .../containers/use_signal_helpers.test.tsx | 77 ++- .../open_timeline/use_timeline_types.test.tsx | 200 +++---- .../use_update_timeline.test.tsx | 35 +- .../properties/use_notes_in_flyout.test.tsx | 7 +- .../timelines/containers/index.test.tsx | 384 +++++++------- .../email/use_email_config.test.ts | 59 ++- .../lib/gen_ai/use_get_dashboard.test.ts | 25 +- .../lib/servicenow/use_choices.test.tsx | 13 +- .../lib/servicenow/use_get_choices.test.tsx | 13 +- .../swimlane/use_get_application.test.tsx | 153 +++--- .../transform_list/use_actions.test.tsx | 10 +- .../transform_list/use_columns.test.tsx | 5 +- .../hooks/use_create_connector.test.tsx | 7 +- .../hooks/use_execute_connector.test.tsx | 7 +- .../hooks/use_load_alert_summary.test.ts | 13 +- .../hooks/use_load_rule_aggregations.test.tsx | 18 +- .../application/hooks/use_load_rules.test.tsx | 23 +- .../hooks/use_load_tags_query.test.tsx | 17 +- .../application/hooks/use_sub_action.test.tsx | 39 +- .../alert_mute/use_get_muted_alerts.test.tsx | 8 +- .../hooks/use_bulk_get_cases.test.tsx | 8 +- .../use_bulk_get_maintenance_windows.test.ts | 8 +- 160 files changed, 3262 insertions(+), 3626 deletions(-) diff --git a/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.test.tsx b/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.test.tsx index 2d6417cd73bd3..6459a38310fc3 100644 --- a/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.test.tsx +++ b/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.test.tsx @@ -72,24 +72,24 @@ describe('useDataGridColumnsCellActions', () => { }); it('should return array with actions for each columns', async () => { - const { result, waitForNextUpdate } = renderHook(useDataGridColumnsCellActions, { + const { result } = renderHook(useDataGridColumnsCellActions, { initialProps: useDataGridColumnsCellActionsProps, }); expect(result.current).toHaveLength(0); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toHaveLength(columns.length); expect(result.current[0]).toHaveLength(actions.length); }); it('should call getCellValue with the proper params', async () => { - const { result, waitForNextUpdate } = renderHook(useDataGridColumnsCellActions, { + const { result } = renderHook(useDataGridColumnsCellActions, { initialProps: useDataGridColumnsCellActionsProps, }); - await waitForNextUpdate(); + await waitFor(() => null); renderCellAction(result.current[0][0], { rowIndex: 0 }); renderCellAction(result.current[0][1], { rowIndex: 1 }); @@ -104,11 +104,11 @@ describe('useDataGridColumnsCellActions', () => { }); it('should render the cell actions', async () => { - const { result, waitForNextUpdate } = renderHook(useDataGridColumnsCellActions, { + const { result } = renderHook(useDataGridColumnsCellActions, { initialProps: useDataGridColumnsCellActionsProps, }); - await waitForNextUpdate(); + await waitFor(() => null); const cellAction1 = renderCellAction(result.current[0][0]); @@ -122,10 +122,10 @@ describe('useDataGridColumnsCellActions', () => { }); it('should execute the action on click', async () => { - const { result, waitForNextUpdate } = renderHook(useDataGridColumnsCellActions, { + const { result } = renderHook(useDataGridColumnsCellActions, { initialProps: useDataGridColumnsCellActionsProps, }); - await waitForNextUpdate(); + await waitFor(() => null); const cellAction = renderCellAction(result.current[0][0]); @@ -137,10 +137,10 @@ describe('useDataGridColumnsCellActions', () => { }); it('should execute the action with correct context', async () => { - const { result, waitForNextUpdate } = renderHook(useDataGridColumnsCellActions, { + const { result } = renderHook(useDataGridColumnsCellActions, { initialProps: useDataGridColumnsCellActionsProps, }); - await waitForNextUpdate(); + await waitFor(() => null); const cellAction1 = renderCellAction(result.current[0][0], { rowIndex: 1 }); @@ -194,10 +194,10 @@ describe('useDataGridColumnsCellActions', () => { }); it('should execute the action with correct page value', async () => { - const { result, waitForNextUpdate } = renderHook(useDataGridColumnsCellActions, { + const { result } = renderHook(useDataGridColumnsCellActions, { initialProps: useDataGridColumnsCellActionsProps, }); - await waitForNextUpdate(); + await waitFor(() => null); const cellAction = renderCellAction(result.current[0][0], { rowIndex: 25 }); @@ -225,10 +225,10 @@ describe('useDataGridColumnsCellActions', () => { }); it('should close popover then action executed', async () => { - const { result, waitForNextUpdate } = renderHook(useDataGridColumnsCellActions, { + const { result } = renderHook(useDataGridColumnsCellActions, { initialProps: useDataGridColumnsCellActionsProps, }); - await waitForNextUpdate(); + await waitFor(() => null); const cellAction = renderCellAction(result.current[0][0], { rowIndex: 25 }); @@ -240,28 +240,28 @@ describe('useDataGridColumnsCellActions', () => { }); it('should return empty array of actions when list of fields is empty', async () => { - const { result, waitForNextUpdate } = renderHook(useDataGridColumnsCellActions, { + const { result } = renderHook(useDataGridColumnsCellActions, { initialProps: { ...useDataGridColumnsCellActionsProps, fields: [], }, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toBeInstanceOf(Array); expect(result.current.length).toBe(0); }); it('should return empty array of actions when list of fields is undefined', async () => { - const { result, waitForNextUpdate } = renderHook(useDataGridColumnsCellActions, { + const { result } = renderHook(useDataGridColumnsCellActions, { initialProps: { ...useDataGridColumnsCellActionsProps, fields: undefined, }, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toBeInstanceOf(Array); expect(result.current.length).toBe(0); diff --git a/packages/kbn-cell-actions/src/hooks/use_load_actions.test.ts b/packages/kbn-cell-actions/src/hooks/use_load_actions.test.ts index b4aeb7795274d..1ef7d01ccf1a3 100644 --- a/packages/kbn-cell-actions/src/hooks/use_load_actions.test.ts +++ b/packages/kbn-cell-actions/src/hooks/use_load_actions.test.ts @@ -8,6 +8,7 @@ */ import { act, renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { makeAction, makeActionContext } from '../mocks/helpers'; import { useBulkLoadActions, useLoadActions, useLoadActionsFn } from './use_load_actions'; @@ -26,7 +27,7 @@ describe('loadActions hooks', () => { }); describe('useLoadActions', () => { it('should load actions when called', async () => { - const { result, waitForNextUpdate } = renderHook(useLoadActions, { + const { result } = renderHook(useLoadActions, { initialProps: actionContext, }); @@ -35,7 +36,7 @@ describe('loadActions hooks', () => { expect(mockGetActions).toHaveBeenCalledTimes(1); expect(mockGetActions).toHaveBeenCalledWith(actionContext); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.value).toEqual([action]); expect(result.current.loading).toEqual(false); @@ -45,10 +46,10 @@ describe('loadActions hooks', () => { const message = 'some division by 0'; mockGetActions.mockRejectedValueOnce(Error(message)); - const { result, waitForNextUpdate } = renderHook(useLoadActions, { + const { result } = renderHook(useLoadActions, { initialProps: actionContext, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.error?.message).toEqual(message); }); @@ -58,11 +59,11 @@ describe('loadActions hooks', () => { const actionDisabled = makeAction('action-disabled'); mockGetActions.mockResolvedValue([actionEnabled, actionDisabled]); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useLoadActions(actionContext, { disabledActionTypes: [actionDisabled.type] }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.value).toEqual([actionEnabled]); }); @@ -70,7 +71,7 @@ describe('loadActions hooks', () => { describe('useLoadActionsFn', () => { it('should load actions when returned function is called', async () => { - const { result, waitForNextUpdate } = renderHook(useLoadActionsFn); + const { result } = renderHook(useLoadActionsFn); const [{ value: valueBeforeCall, loading: loadingBeforeCall }, loadActions] = result.current; expect(valueBeforeCall).toBeUndefined(); @@ -87,7 +88,7 @@ describe('loadActions hooks', () => { expect(mockGetActions).toHaveBeenCalledTimes(1); expect(mockGetActions).toHaveBeenCalledWith(actionContext); - await waitForNextUpdate(); + await waitFor(() => null); const [{ value: valueAfterUpdate, loading: loadingAfterUpdate }] = result.current; expect(valueAfterUpdate).toEqual([action]); @@ -98,15 +99,15 @@ describe('loadActions hooks', () => { const message = 'some division by 0'; mockGetActions.mockRejectedValueOnce(Error(message)); - const { result, waitForNextUpdate } = renderHook(useLoadActionsFn); + const { result } = renderHook(useLoadActionsFn); const [_, loadActions] = result.current; - expect(result.error).toBeUndefined(); + expect(result).toBeUndefined(); act(() => { loadActions(actionContext); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.error?.message).toEqual(message); }); @@ -116,7 +117,7 @@ describe('loadActions hooks', () => { const actionDisabled = makeAction('action-disabled'); mockGetActions.mockResolvedValue([actionEnabled, actionDisabled]); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useLoadActionsFn({ disabledActionTypes: [actionDisabled.type] }) ); const [_, loadActions] = result.current; @@ -124,7 +125,7 @@ describe('loadActions hooks', () => { act(() => { loadActions(actionContext); }); - await waitForNextUpdate(); + await waitFor(() => null); const [{ value: valueAfterUpdate }] = result.current; expect(valueAfterUpdate).toEqual([actionEnabled]); @@ -136,7 +137,7 @@ describe('loadActions hooks', () => { const actionContexts = [actionContext, actionContext2]; it('should load bulk actions array when called', async () => { - const { result, waitForNextUpdate } = renderHook(useBulkLoadActions, { + const { result } = renderHook(useBulkLoadActions, { initialProps: actionContexts, }); @@ -146,7 +147,7 @@ describe('loadActions hooks', () => { expect(mockGetActions).toHaveBeenCalledWith(actionContext); expect(mockGetActions).toHaveBeenCalledWith(actionContext2); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.value).toEqual([[action], [action]]); expect(result.current.loading).toEqual(false); @@ -156,10 +157,10 @@ describe('loadActions hooks', () => { const message = 'some division by 0'; mockGetActions.mockRejectedValueOnce(Error(message)); - const { result, waitForNextUpdate } = renderHook(useBulkLoadActions, { + const { result } = renderHook(useBulkLoadActions, { initialProps: actionContexts, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.error?.message).toEqual(message); }); @@ -169,31 +170,31 @@ describe('loadActions hooks', () => { const actionDisabled = makeAction('action-disabled'); mockGetActions.mockResolvedValue([actionEnabled, actionDisabled]); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useBulkLoadActions(actionContexts, { disabledActionTypes: [actionDisabled.type] }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.value).toEqual([[actionEnabled], [actionEnabled]]); }); it('should re-render when contexts is changed', async () => { - const { result, rerender, waitForNextUpdate } = renderHook(useBulkLoadActions, { + const { result, rerender } = renderHook(useBulkLoadActions, { initialProps: [actionContext], }); - await waitForNextUpdate(); + await waitFor(() => null); expect(mockGetActions).toHaveBeenCalledWith(actionContext); rerender([actionContext2]); - await waitForNextUpdate(); + await waitFor(() => null); expect(mockGetActions).toHaveBeenCalledWith(actionContext2); mockGetActions.mockClear(); rerender([]); - await waitForNextUpdate(); + await waitFor(() => null); expect(mockGetActions).toHaveBeenCalledTimes(0); expect(result.current.value).toBeInstanceOf(Array); @@ -202,7 +203,7 @@ describe('loadActions hooks', () => { }); it('should return the same array after re-render when contexts is undefined', async () => { - const { result, rerender, waitFor } = renderHook(useBulkLoadActions, { + const { result, rerender } = renderHook(useBulkLoadActions, { initialProps: undefined, }); diff --git a/packages/kbn-grouping/src/hooks/use_grouping.test.tsx b/packages/kbn-grouping/src/hooks/use_grouping.test.tsx index 22957548de314..4dc9f1332a97c 100644 --- a/packages/kbn-grouping/src/hooks/use_grouping.test.tsx +++ b/packages/kbn-grouping/src/hooks/use_grouping.test.tsx @@ -47,9 +47,8 @@ const groupingArgs = { describe('useGrouping', () => { it('Renders child component without grouping table wrapper when no group is selected', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useGrouping(defaultArgs)); - await waitForNextUpdate(); - await waitForNextUpdate(); + const { result } = renderHook(() => useGrouping(defaultArgs)); + await waitFor(() => null); const { getByTestId, queryByTestId } = render( {result.current.getGrouping({ @@ -98,9 +97,8 @@ describe('useGrouping', () => { }) ); - const { result, waitForNextUpdate } = renderHook(() => useGrouping(defaultArgs)); - await waitForNextUpdate(); - await waitForNextUpdate(); + const { result } = renderHook(() => useGrouping(defaultArgs)); + await waitFor(() => null); const { getByTestId } = render( {result.current.getGrouping({ diff --git a/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts b/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts index aae858aa63087..5e101e4ceb51c 100644 --- a/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts +++ b/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts @@ -8,6 +8,7 @@ */ import { act, renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; import { @@ -47,7 +48,7 @@ describe('use_field_value_autocomplete', () => { test('initializes hook', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook< + const { result } = renderHook< UseFieldValueAutocompleteProps, UseFieldValueAutocompleteReturn >(() => @@ -63,7 +64,7 @@ describe('use_field_value_autocomplete', () => { selectedField: undefined, }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual([false, true, [], result.current[3]]); }); @@ -71,7 +72,7 @@ describe('use_field_value_autocomplete', () => { test('does not call autocomplete service if "operatorType" is "exists"', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook< + const { result } = renderHook< UseFieldValueAutocompleteProps, UseFieldValueAutocompleteReturn >(() => @@ -87,7 +88,7 @@ describe('use_field_value_autocomplete', () => { selectedField: getField('machine.os'), }) ); - await waitForNextUpdate(); + await waitFor(() => null); const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; @@ -98,7 +99,7 @@ describe('use_field_value_autocomplete', () => { test('does not call autocomplete service if "selectedField" is undefined', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook< + const { result } = renderHook< UseFieldValueAutocompleteProps, UseFieldValueAutocompleteReturn >(() => @@ -114,7 +115,7 @@ describe('use_field_value_autocomplete', () => { selectedField: undefined, }) ); - await waitForNextUpdate(); + await waitFor(() => null); const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; @@ -125,7 +126,7 @@ describe('use_field_value_autocomplete', () => { test('does not call autocomplete service if "indexPattern" is undefined', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook< + const { result } = renderHook< UseFieldValueAutocompleteProps, UseFieldValueAutocompleteReturn >(() => @@ -141,7 +142,7 @@ describe('use_field_value_autocomplete', () => { selectedField: getField('machine.os'), }) ); - await waitForNextUpdate(); + await waitFor(() => null); const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; @@ -160,10 +161,7 @@ describe('use_field_value_autocomplete', () => { } const { signal } = new AbortController(); - const { waitForNextUpdate } = renderHook< - UseFieldValueAutocompleteProps, - UseFieldValueAutocompleteReturn - >(() => + renderHook(() => useFieldValueAutocomplete({ autocompleteService: { ...autocompleteStartMock, @@ -176,9 +174,8 @@ describe('use_field_value_autocomplete', () => { selectedField: { ...selectedField, name: 'child' }, }) ); - // Note: initial `waitForNextUpdate` is hook initialization - await waitForNextUpdate(); - await waitForNextUpdate(); + // Note: initial `waitFor` is hook initialization + await waitFor(() => null); expect(suggestionsMock).toHaveBeenCalledWith({ field: { ...getField('nestedField.child'), name: 'nestedField.child' }, @@ -205,7 +202,7 @@ describe('use_field_value_autocomplete', () => { test('returns "isSuggestingValues" of false if field type is boolean', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook< + const { result } = renderHook< UseFieldValueAutocompleteProps, UseFieldValueAutocompleteReturn >(() => @@ -221,9 +218,8 @@ describe('use_field_value_autocomplete', () => { selectedField: getField('ssl'), }) ); - // Note: initial `waitForNextUpdate` is hook initialization - await waitForNextUpdate(); - await waitForNextUpdate(); + + await waitFor(() => null); const expectedResult: UseFieldValueAutocompleteReturn = [false, false, [], result.current[3]]; @@ -236,7 +232,7 @@ describe('use_field_value_autocomplete', () => { const suggestionsMock = jest.fn().mockResolvedValue([]); await act(async () => { - const { result, waitForNextUpdate } = renderHook< + const { result } = renderHook< UseFieldValueAutocompleteProps, UseFieldValueAutocompleteReturn >(() => @@ -252,9 +248,8 @@ describe('use_field_value_autocomplete', () => { selectedField: getField('bytes'), }) ); - // Note: initial `waitForNextUpdate` is hook initialization - await waitForNextUpdate(); - await waitForNextUpdate(); + + await waitFor(() => null); const expectedResult: UseFieldValueAutocompleteReturn = [false, false, [], result.current[3]]; @@ -266,7 +261,7 @@ describe('use_field_value_autocomplete', () => { test('returns suggestions', async () => { await act(async () => { const { signal } = new AbortController(); - const { result, waitForNextUpdate } = renderHook< + const { result } = renderHook< UseFieldValueAutocompleteProps, UseFieldValueAutocompleteReturn >(() => @@ -282,9 +277,7 @@ describe('use_field_value_autocomplete', () => { selectedField: getField('@tags'), }) ); - // Note: initial `waitForNextUpdate` is hook initialization - await waitForNextUpdate(); - await waitForNextUpdate(); + await waitFor(() => null); const expectedResult: UseFieldValueAutocompleteReturn = [ false, @@ -306,7 +299,7 @@ describe('use_field_value_autocomplete', () => { test('returns new suggestions on subsequent calls', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook< + const { result } = renderHook< UseFieldValueAutocompleteProps, UseFieldValueAutocompleteReturn >(() => @@ -322,9 +315,8 @@ describe('use_field_value_autocomplete', () => { selectedField: getField('@tags'), }) ); - // Note: initial `waitForNextUpdate` is hook initialization - await waitForNextUpdate(); - await waitForNextUpdate(); + + await waitFor(() => null); expect(result.current[3]).not.toBeNull(); @@ -339,7 +331,7 @@ describe('use_field_value_autocomplete', () => { }); } - await waitForNextUpdate(); + await waitFor(() => null); const expectedResult: UseFieldValueAutocompleteReturn = [ false, diff --git a/packages/kbn-securitysolution-hook-utils/src/use_async/index.test.ts b/packages/kbn-securitysolution-hook-utils/src/use_async/index.test.ts index a9f02622df306..35a190e938e0a 100644 --- a/packages/kbn-securitysolution-hook-utils/src/use_async/index.test.ts +++ b/packages/kbn-securitysolution-hook-utils/src/use_async/index.test.ts @@ -8,6 +8,7 @@ */ import { act, renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useAsync } from '.'; @@ -20,8 +21,8 @@ type TestReturn = Promise; describe('useAsync', () => { /** - * Timeout for both jest tests and for the waitForNextUpdate. - * jest tests default to 5 seconds and waitForNextUpdate defaults to 1 second. + * Timeout for both jest tests and for the waitFor. + * jest tests default to 5 seconds and waitFor defaults to 1 second. * 20_0000 = 20,000 milliseconds = 20 seconds */ const timeout = 20_000; @@ -42,12 +43,12 @@ describe('useAsync', () => { it( 'invokes the function when start is called', async () => { - const { result, waitForNextUpdate } = renderHook(() => useAsync(fn)); + const { result } = renderHook(() => useAsync(fn)); act(() => { result.current.start(args); }); - await waitForNextUpdate({ timeout }); + await waitFor(() => null, { timeout }); expect(fn).toHaveBeenCalled(); }, @@ -55,13 +56,13 @@ describe('useAsync', () => { ); it('invokes the function with start args', async () => { - const { result, waitForNextUpdate } = renderHook(() => useAsync(fn)); + const { result } = renderHook(() => useAsync(fn)); const expectedArgs = { ...args }; act(() => { result.current.start(args); }); - await waitForNextUpdate({ timeout }); + await waitFor(() => null, { timeout }); expect(fn).toHaveBeenCalledWith(expectedArgs); }); @@ -69,13 +70,13 @@ describe('useAsync', () => { it( 'populates result with the resolved value of the fn', async () => { - const { result, waitForNextUpdate } = renderHook(() => useAsync(fn)); + const { result } = renderHook(() => useAsync(fn)); fn.mockResolvedValue({ resolved: 'value' }); act(() => { result.current.start(args); }); - await waitForNextUpdate({ timeout }); + await waitFor(() => null, { timeout }); expect(result.current.result).toEqual({ resolved: 'value' }); expect(result.current.error).toBeUndefined(); @@ -87,12 +88,13 @@ describe('useAsync', () => { 'populates error if function rejects', async () => { fn.mockRejectedValue(new Error('whoops')); - const { result, waitForNextUpdate } = renderHook(() => useAsync(fn)); + const { result } = renderHook(() => useAsync(fn)); act(() => { result.current.start(args); }); - await waitForNextUpdate({ timeout }); + + await waitFor(() => null, { timeout }); expect(result.current.result).toBeUndefined(); expect(result.current.error).toEqual(new Error('whoops')); @@ -106,7 +108,7 @@ describe('useAsync', () => { let resolve: () => void; fn.mockImplementation(() => new Promise((_resolve) => (resolve = _resolve))); - const { result, waitForNextUpdate } = renderHook(() => useAsync(fn)); + const { result } = renderHook(() => useAsync(fn)); act(() => { result.current.start(args); @@ -115,7 +117,7 @@ describe('useAsync', () => { expect(result.current.loading).toBe(true); act(() => resolve()); - await waitForNextUpdate({ timeout }); + await waitFor(() => null, { timeout }); expect(result.current.loading).toBe(false); }, @@ -128,7 +130,7 @@ describe('useAsync', () => { let resolve: (result: string) => void; fn.mockImplementation(() => new Promise((_resolve) => (resolve = _resolve))); - const { result, waitForNextUpdate } = renderHook(() => useAsync(fn)); + const { result } = renderHook(() => useAsync(fn)); act(() => { result.current.start(args); @@ -137,7 +139,7 @@ describe('useAsync', () => { expect(result.current.loading).toBe(true); act(() => resolve('result')); - await waitForNextUpdate({ timeout }); + await waitFor(() => null, { timeout }); expect(result.current.loading).toBe(false); expect(result.current.result).toBe('result'); @@ -149,7 +151,7 @@ describe('useAsync', () => { expect(result.current.loading).toBe(true); expect(result.current.result).toBe(undefined); act(() => resolve('result')); - await waitForNextUpdate({ timeout }); + await waitFor(() => null, { timeout }); expect(result.current.loading).toBe(false); expect(result.current.result).toBe('result'); diff --git a/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.test.ts b/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.test.ts index fa68009be9d9b..95f9f2dcdfad2 100644 --- a/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.test.ts +++ b/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.test.ts @@ -8,6 +8,7 @@ */ import { act, renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useFindLists } from '.'; import { httpServiceMock } from '@kbn/core-http-browser-mocks'; @@ -26,11 +27,11 @@ describe('useFindLists', () => { }); it('invokes Api.findLists', async () => { - const { result, waitForNextUpdate } = renderHook(() => useFindLists()); + const { result } = renderHook(() => useFindLists()); act(() => { result.current.start({ http: httpMock, pageIndex: 1, pageSize: 10 }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(Api.findLists).toHaveBeenCalledWith( expect.objectContaining({ http: httpMock, pageIndex: 1, pageSize: 10 }) diff --git a/packages/kbn-unified-field-list/src/hooks/use_existing_fields.test.tsx b/packages/kbn-unified-field-list/src/hooks/use_existing_fields.test.tsx index 06b043014c2fd..d3c6b30c3ceef 100644 --- a/packages/kbn-unified-field-list/src/hooks/use_existing_fields.test.tsx +++ b/packages/kbn-unified-field-list/src/hooks/use_existing_fields.test.tsx @@ -8,6 +8,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { stubLogstashDataView as dataView } from '@kbn/data-views-plugin/common/data_view.stub'; import { createStubDataView, stubFieldSpecMap } from '@kbn/data-plugin/public/stubs'; import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; @@ -94,7 +95,7 @@ describe('UnifiedFieldList useExistingFields', () => { }; }); - const hookFetcher = renderHook(useExistingFieldsFetcher, { + renderHook(useExistingFieldsFetcher, { initialProps: { dataViews: [dataView], services: mockedServices, @@ -107,7 +108,7 @@ describe('UnifiedFieldList useExistingFields', () => { const hookReader = renderHook(useExistingFieldsReader); - await hookFetcher.waitForNextUpdate(); + await waitFor(() => null); expect(ExistingFieldsServiceApi.loadFieldExisting).toHaveBeenCalledWith( expect.objectContaining({ @@ -167,7 +168,7 @@ describe('UnifiedFieldList useExistingFields', () => { const hookReader1 = renderHook(useExistingFieldsReader); const hookReader2 = renderHook(useExistingFieldsReader); - await hookFetcher.waitForNextUpdate(); + await waitFor(() => null); expect(ExistingFieldsServiceApi.loadFieldExisting).toHaveBeenCalled(); @@ -199,7 +200,7 @@ describe('UnifiedFieldList useExistingFields', () => { throw new Error('test'); }); - const hookFetcher = renderHook(useExistingFieldsFetcher, { + renderHook(useExistingFieldsFetcher, { initialProps: { dataViews: [dataView], services: mockedServices, @@ -212,7 +213,7 @@ describe('UnifiedFieldList useExistingFields', () => { const hookReader = renderHook(useExistingFieldsReader); - await hookFetcher.waitForNextUpdate(); + await waitFor(() => null); expect(ExistingFieldsServiceApi.loadFieldExisting).toHaveBeenCalled(); @@ -232,7 +233,7 @@ describe('UnifiedFieldList useExistingFields', () => { } ); - const hookFetcher = renderHook(useExistingFieldsFetcher, { + renderHook(useExistingFieldsFetcher, { initialProps: { dataViews: [dataView, anotherDataView, dataViewWithRestrictions], services: mockedServices, @@ -244,7 +245,7 @@ describe('UnifiedFieldList useExistingFields', () => { }); const hookReader = renderHook(useExistingFieldsReader); - await hookFetcher.waitForNextUpdate(); + await waitFor(() => null); const currentResult = hookReader.result.current; @@ -310,8 +311,7 @@ describe('UnifiedFieldList useExistingFields', () => { }); const hookReader = renderHook(useExistingFieldsReader); - await hookFetcher.waitForNextUpdate(); - await hookFetcher.waitFor(() => !hookFetcher.result.current.isProcessing); + await waitFor(() => () => !hookFetcher.result.current.isProcessing); expect(dataViewWithRestrictions.getAggregationRestrictions).toHaveBeenCalled(); expect(ExistingFieldsServiceApi.loadFieldExisting).not.toHaveBeenCalled(); @@ -346,7 +346,7 @@ describe('UnifiedFieldList useExistingFields', () => { }); const hookReader = renderHook(useExistingFieldsReader); - await hookFetcher.waitForNextUpdate(); + await waitFor(() => null); expect(ExistingFieldsServiceApi.loadFieldExisting).toHaveBeenCalledWith( expect.objectContaining({ @@ -370,7 +370,7 @@ describe('UnifiedFieldList useExistingFields', () => { dataViews: [dataView, anotherDataView], }); - await hookFetcher.waitForNextUpdate(); + await waitFor(() => null); expect(ExistingFieldsServiceApi.loadFieldExisting).toHaveBeenNthCalledWith( 2, @@ -424,7 +424,7 @@ describe('UnifiedFieldList useExistingFields', () => { }); const hookReader = renderHook(useExistingFieldsReader); - await hookFetcher.waitForNextUpdate(); + await waitFor(() => null); expect(ExistingFieldsServiceApi.loadFieldExisting).toHaveBeenCalledWith( expect.objectContaining({ @@ -447,7 +447,7 @@ describe('UnifiedFieldList useExistingFields', () => { query: { query: 'test', language: 'kuery' }, }); - await hookFetcher.waitForNextUpdate(); + await waitFor(() => null); expect(ExistingFieldsServiceApi.loadFieldExisting).toHaveBeenNthCalledWith( 2, @@ -497,7 +497,7 @@ describe('UnifiedFieldList useExistingFields', () => { }); const hookReader = renderHook(useExistingFieldsReader); - await hookFetcher.waitForNextUpdate(); + await waitFor(() => null); expect(ExistingFieldsServiceApi.loadFieldExisting).toHaveBeenCalledWith( expect.objectContaining({ @@ -522,7 +522,7 @@ describe('UnifiedFieldList useExistingFields', () => { toDate: '2022-01-01', }); - await hookFetcher.waitForNextUpdate(); + await waitFor(() => null); expect(ExistingFieldsServiceApi.loadFieldExisting).toHaveBeenNthCalledWith( 2, @@ -558,12 +558,12 @@ describe('UnifiedFieldList useExistingFields', () => { query: { query: '', language: 'lucene' }, filters: [], }; - const hookFetcher = renderHook(useExistingFieldsFetcher, { + renderHook(useExistingFieldsFetcher, { initialProps: params, }); const hookReader = renderHook(useExistingFieldsReader); - await hookFetcher.waitForNextUpdate(); + await waitFor(() => null); expect(ExistingFieldsServiceApi.loadFieldExisting).toHaveBeenCalledWith( expect.objectContaining({ diff --git a/packages/kbn-unified-field-list/src/hooks/use_grouped_fields.test.tsx b/packages/kbn-unified-field-list/src/hooks/use_grouped_fields.test.tsx index a0a8e055e6d62..a30d14864a524 100644 --- a/packages/kbn-unified-field-list/src/hooks/use_grouped_fields.test.tsx +++ b/packages/kbn-unified-field-list/src/hooks/use_grouped_fields.test.tsx @@ -8,6 +8,7 @@ */ import { renderHook, act } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { stubDataViewWithoutTimeField, stubLogstashDataView as dataView, @@ -56,11 +57,11 @@ describe('UnifiedFieldList useGroupedFields()', () => { allFields: null, services: mockedServices, }; - const { result, waitForNextUpdate, rerender } = renderHook(useGroupedFields, { + const { result, rerender } = renderHook(useGroupedFields, { initialProps: props, }); - await waitForNextUpdate(); + await waitFor(() => null); let fieldListGroupedProps = result.current.fieldListGroupedProps; expect(fieldListGroupedProps.fieldGroups).toMatchSnapshot(); @@ -101,11 +102,11 @@ describe('UnifiedFieldList useGroupedFields()', () => { }) ); - const { result, waitForNextUpdate, rerender } = renderHook(useGroupedFields, { + const { result, rerender } = renderHook(useGroupedFields, { initialProps: props, }); - await waitForNextUpdate(); + await waitFor(() => null); let fieldListGroupedProps = result.current.fieldListGroupedProps; const fieldGroups = fieldListGroupedProps.fieldGroups; @@ -163,11 +164,11 @@ describe('UnifiedFieldList useGroupedFields()', () => { }) ); - const { result, waitForNextUpdate, rerender } = renderHook(useGroupedFields, { + const { result, rerender } = renderHook(useGroupedFields, { initialProps: props, }); - await waitForNextUpdate(); + await waitFor(() => null); let fieldListGroupedProps = result.current.fieldListGroupedProps; const fieldGroups = fieldListGroupedProps.fieldGroups; @@ -235,11 +236,11 @@ describe('UnifiedFieldList useGroupedFields()', () => { }) ); - const { result, waitForNextUpdate, rerender } = renderHook(useGroupedFields, { + const { result, rerender } = renderHook(useGroupedFields, { initialProps: props, }); - await waitForNextUpdate(); + await waitFor(() => null); let fieldListGroupedProps = result.current.fieldListGroupedProps; const fieldGroups = fieldListGroupedProps.fieldGroups; @@ -292,11 +293,11 @@ describe('UnifiedFieldList useGroupedFields()', () => { allFields: allFieldsIncludingUnmapped, services: mockedServices, }; - const { result, waitForNextUpdate } = renderHook(useGroupedFields, { + const { result } = renderHook(useGroupedFields, { initialProps: props, }); - await waitForNextUpdate(); + await waitFor(() => null); let fieldGroups = result.current.fieldListGroupedProps.fieldGroups; @@ -373,11 +374,11 @@ describe('UnifiedFieldList useGroupedFields()', () => { allFields, services: mockedServices, }; - const { result, waitForNextUpdate, rerender } = renderHook(useGroupedFields, { + const { result, rerender } = renderHook(useGroupedFields, { initialProps: props, }); - await waitForNextUpdate(); + await waitFor(() => null); const scrollToTopResetCounter1 = result.current.fieldListGroupedProps.scrollToTopResetCounter; @@ -392,7 +393,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { }); it('should work correctly when custom unsupported fields are skipped', async () => { - const { result, waitForNextUpdate } = renderHook(useGroupedFields, { + const { result } = renderHook(useGroupedFields, { initialProps: { dataViewId: dataView.id!, allFields, @@ -401,7 +402,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { }, }); - await waitForNextUpdate(); + await waitFor(() => null); const fieldGroups = result.current.fieldListGroupedProps.fieldGroups; @@ -422,7 +423,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { }); it('should work correctly when selected fields are present', async () => { - const { result, waitForNextUpdate } = renderHook(useGroupedFields, { + const { result } = renderHook(useGroupedFields, { initialProps: { dataViewId: dataView.id!, allFields, @@ -432,7 +433,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { }, }); - await waitForNextUpdate(); + await waitFor(() => null); const fieldGroups = result.current.fieldListGroupedProps.fieldGroups; @@ -531,7 +532,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { }; } }); - const { result, waitForNextUpdate } = renderHook(useGroupedFields, { + const { result } = renderHook(useGroupedFields, { initialProps: { dataViewId: dataView.id!, allFields, @@ -540,7 +541,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { }, }); - await waitForNextUpdate(); + await waitFor(() => null); const fieldGroups = result.current.fieldListGroupedProps.fieldGroups; @@ -572,10 +573,10 @@ describe('UnifiedFieldList useGroupedFields()', () => { }) ); - const { result, waitForNextUpdate, rerender } = renderHook(useGroupedFields, { + const { result, rerender } = renderHook(useGroupedFields, { initialProps: props, }); - await waitForNextUpdate(); + await waitFor(() => null); let fieldListGroupedProps = result.current.fieldListGroupedProps; fieldGroups = fieldListGroupedProps.fieldGroups; @@ -604,7 +605,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { allFields: anotherDataView.fields, }); - await waitForNextUpdate(); + await waitFor(() => null); fieldListGroupedProps = result.current.fieldListGroupedProps; fieldGroups = fieldListGroupedProps.fieldGroups; @@ -633,7 +634,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { // `bytes` is popular, but we are skipping it here to test that it would not be shown under Popular and Available const onSupportedFieldFilter = jest.fn((field) => field.name !== 'bytes'); - const { result, waitForNextUpdate } = renderHook(useGroupedFields, { + const { result } = renderHook(useGroupedFields, { initialProps: { dataViewId: dataView.id!, allFields, @@ -643,7 +644,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { }, }); - await waitForNextUpdate(); + await waitFor(() => null); const fieldGroups = result.current.fieldListGroupedProps.fieldGroups; @@ -668,7 +669,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { }); it('should work correctly when global filters are set', async () => { - const { result, waitForNextUpdate } = renderHook(useGroupedFields, { + const { result } = renderHook(useGroupedFields, { initialProps: { dataViewId: dataView.id!, allFields: [], @@ -677,14 +678,14 @@ describe('UnifiedFieldList useGroupedFields()', () => { }, }); - await waitForNextUpdate(); + await waitFor(() => null); const fieldGroups = result.current.fieldListGroupedProps.fieldGroups; expect(fieldGroups).toMatchSnapshot(); }); it('should work correctly and show unmapped fields separately', async () => { - const { result, waitForNextUpdate } = renderHook(useGroupedFields, { + const { result } = renderHook(useGroupedFields, { initialProps: { dataViewId: dataView.id!, allFields: allFieldsIncludingUnmapped, @@ -692,7 +693,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { }, }); - await waitForNextUpdate(); + await waitFor(() => null); const fieldGroups = result.current.fieldListGroupedProps.fieldGroups; @@ -718,7 +719,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { allFields[2], allFields[0], ]; - const { result, waitForNextUpdate } = renderHook(useGroupedFields, { + const { result } = renderHook(useGroupedFields, { initialProps: { dataViewId: dataView.id!, allFields, @@ -727,7 +728,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { }, }); - await waitForNextUpdate(); + await waitFor(() => null); const fieldGroups = result.current.fieldListGroupedProps.fieldGroups; @@ -750,7 +751,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { }); it('should include filters props', async () => { - const { result, waitForNextUpdate } = renderHook(useGroupedFields, { + const { result } = renderHook(useGroupedFields, { initialProps: { dataViewId: dataView.id!, allFields, @@ -758,7 +759,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { }, }); - await waitForNextUpdate(); + await waitFor(() => null); const { fieldListFiltersProps, fieldListGroupedProps } = result.current; const fieldGroups = fieldListGroupedProps.fieldGroups; @@ -806,7 +807,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { const additionalFieldGroups = { smartFields, }; - const { result, waitForNextUpdate } = renderHook(useGroupedFields, { + const { result } = renderHook(useGroupedFields, { initialProps: { dataViewId: dataView.id!, allFields, @@ -815,7 +816,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { }, }); - await waitForNextUpdate(); + await waitFor(() => null); const fieldListGroupedProps = result.current.fieldListGroupedProps; const fieldGroups = fieldListGroupedProps.fieldGroups; expect(fieldGroups.SmartFields?.fields?.length).toBe(1); diff --git a/src/plugins/discover/public/context_awareness/hooks/use_root_profile.test.tsx b/src/plugins/discover/public/context_awareness/hooks/use_root_profile.test.tsx index 8edbc35ab11a1..0252660e2c112 100644 --- a/src/plugins/discover/public/context_awareness/hooks/use_root_profile.test.tsx +++ b/src/plugins/discover/public/context_awareness/hooks/use_root_profile.test.tsx @@ -9,6 +9,7 @@ import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import React from 'react'; import { discoverServiceMock } from '../../__mocks__/services'; import { useRootProfile } from './use_root_profile'; @@ -31,18 +32,18 @@ describe('useRootProfile', () => { }); it('should return rootProfileLoading as false', async () => { - const { result, waitForNextUpdate } = render(); - await waitForNextUpdate(); + const { result } = render(); + await waitFor(() => null); expect(result.current.rootProfileLoading).toBe(false); }); it('should return rootProfileLoading as true when solutionNavId changes', async () => { - const { result, rerender, waitForNextUpdate } = render(); - await waitForNextUpdate(); + const { result, rerender } = render(); + await waitFor(() => null); expect(result.current.rootProfileLoading).toBe(false); rerender({ solutionNavId: 'newSolutionNavId' }); expect(result.current.rootProfileLoading).toBe(true); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.rootProfileLoading).toBe(false); }); }); diff --git a/src/plugins/discover/public/hooks/use_data_view.test.tsx b/src/plugins/discover/public/hooks/use_data_view.test.tsx index 5ef2194ab8db1..e6a3ebb3c62cf 100644 --- a/src/plugins/discover/public/hooks/use_data_view.test.tsx +++ b/src/plugins/discover/public/hooks/use_data_view.test.tsx @@ -10,6 +10,7 @@ import React from 'react'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useDataView } from './use_data_view'; const adhocDataView = { @@ -42,7 +43,7 @@ const render = async ({ dataViewId }: { dataViewId: string }) => { {children} ), }); - await hookResult.waitForNextUpdate(); + await waitFor(() => null); return hookResult; }; diff --git a/src/plugins/discover/public/hooks/use_navigation_props.test.tsx b/src/plugins/discover/public/hooks/use_navigation_props.test.tsx index 36c86e01a9bb9..1cdf8ef8ca93b 100644 --- a/src/plugins/discover/public/hooks/use_navigation_props.test.tsx +++ b/src/plugins/discover/public/hooks/use_navigation_props.test.tsx @@ -9,6 +9,7 @@ import React, { MouseEvent } from 'react'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useNavigationProps } from './use_navigation_props'; import type { DataView } from '@kbn/data-views-plugin/public'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; @@ -65,7 +66,7 @@ const render = async () => { ), } ); - await renderResult.waitForNextUpdate(); + await waitFor(() => null); return renderResult; }; diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.test.tsx b/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.test.tsx index 6457f721ddd16..57cb54251fcf7 100644 --- a/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.test.tsx +++ b/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.test.tsx @@ -28,7 +28,7 @@ describe('useEmbeddableFactory', () => { ); doStart(); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useEmbeddableFactory({ factory: getFactory(), input: { id: 'hello' } }) ); @@ -36,7 +36,7 @@ describe('useEmbeddableFactory', () => { expect(loading).toBe(true); - await waitForNextUpdate(); + await waitFor(() => null); const [embeddable] = result.current; expect(embeddable).toBeDefined(); diff --git a/src/plugins/unified_doc_viewer/public/hooks/use_es_doc_search.test.tsx b/src/plugins/unified_doc_viewer/public/hooks/use_es_doc_search.test.tsx index f86cd00f14ce1..861d389d4cf30 100644 --- a/src/plugins/unified_doc_viewer/public/hooks/use_es_doc_search.test.tsx +++ b/src/plugins/unified_doc_viewer/public/hooks/use_es_doc_search.test.tsx @@ -8,6 +8,7 @@ */ import { renderHook, act } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { type EsDocSearchProps, buildSearchBody, useEsDocSearch } from './use_es_doc_search'; import { Subject } from 'rxjs'; import type { DataView } from '@kbn/data-views-plugin/public'; @@ -281,9 +282,10 @@ describe('Test of helper / hook', () => { }, }); mockSearchResult.complete(); - await hook.waitForNextUpdate(); }); + await waitFor(() => null); + expect(hook.result.current.slice(0, 2)).toEqual([ ElasticRequestState.Found, buildDataTableRecord(record), diff --git a/src/plugins/vis_types/table/public/utils/use/use_ui_state.test.ts b/src/plugins/vis_types/table/public/utils/use/use_ui_state.test.ts index 37525bf12626b..6e46efeaf8345 100644 --- a/src/plugins/vis_types/table/public/utils/use/use_ui_state.test.ts +++ b/src/plugins/vis_types/table/public/utils/use/use_ui_state.test.ts @@ -8,6 +8,7 @@ */ import { act, renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import type { PersistedState } from '@kbn/visualizations-plugin/public'; import { TableVisUiState } from '../../types'; import { useUiState } from './use_ui_state'; @@ -39,7 +40,7 @@ describe('useUiState', () => { }); it('should subscribe on uiState changes and update local state', async () => { - const { result, unmount, waitForNextUpdate } = renderHook(() => useUiState(uiState)); + const { result, unmount } = renderHook(() => useUiState(uiState)); expect(uiState.on).toHaveBeenCalledWith('change', expect.any(Function)); // @ts-expect-error @@ -61,7 +62,7 @@ describe('useUiState', () => { updateOnChange(); }); - await waitForNextUpdate(); + await waitFor(() => null); // should update local state with new values expect(result.current).toEqual({ diff --git a/src/plugins/visualizations/public/visualize_app/utils/use/use_saved_vis_instance.test.ts b/src/plugins/visualizations/public/visualize_app/utils/use/use_saved_vis_instance.test.ts index 7c32fec754428..504b7905752a5 100644 --- a/src/plugins/visualizations/public/visualize_app/utils/use/use_saved_vis_instance.test.ts +++ b/src/plugins/visualizations/public/visualize_app/utils/use/use_saved_vis_instance.test.ts @@ -8,6 +8,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { EventEmitter } from 'events'; import { setTypes } from '../../../services'; @@ -127,7 +128,7 @@ describe('useSavedVisInstance', () => { describe('edit saved visualization route', () => { test('should load instance and initiate an editor if chrome is set up', async () => { - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useSavedVisInstance(mockServices, eventEmitter, true, undefined, savedVisId) ); @@ -135,7 +136,7 @@ describe('useSavedVisInstance', () => { expect(mockGetVisualizationInstance).toHaveBeenCalledWith(mockServices, savedVisId); expect(mockGetVisualizationInstance.mock.calls.length).toBe(1); - await waitForNextUpdate(); + await waitFor(() => null); expect(mockServices.chrome.setBreadcrumbs).toHaveBeenCalledWith('Test Vis'); expect(mockServices.chrome.docTitle.change).toHaveBeenCalledWith('Test Vis'); expect(getEditBreadcrumbs).toHaveBeenCalledWith( @@ -156,7 +157,7 @@ describe('useSavedVisInstance', () => { }, id: 'panel1', }; - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useSavedVisInstance( mockServices, eventEmitter, @@ -171,7 +172,7 @@ describe('useSavedVisInstance', () => { expect(mockGetVisualizationInstance).toHaveBeenCalledWith(mockServices, savedVisId); expect(mockGetVisualizationInstance.mock.calls.length).toBe(1); - await waitForNextUpdate(); + await waitFor(() => null); expect(mockServices.chrome.setBreadcrumbs).toHaveBeenCalledWith('Test Vis'); expect(mockServices.chrome.docTitle.change).toHaveBeenCalledWith('Test Vis'); expect(getEditBreadcrumbs).toHaveBeenCalledWith( @@ -189,13 +190,13 @@ describe('useSavedVisInstance', () => { }); test('should destroy the editor and the savedVis on unmount if chrome exists', async () => { - const { result, unmount, waitForNextUpdate } = renderHook(() => + const { result, unmount } = renderHook(() => useSavedVisInstance(mockServices, eventEmitter, true, undefined, savedVisId) ); result.current.visEditorRef.current = document.createElement('div'); - await waitForNextUpdate(); + await waitFor(() => null); unmount(); expect(mockDefaultEditorControllerDestroy.mock.calls.length).toBe(1); @@ -215,7 +216,7 @@ describe('useSavedVisInstance', () => { }); test('should create new visualization based on search params', async () => { - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useSavedVisInstance(mockServices, eventEmitter, true, undefined, undefined) ); @@ -226,7 +227,7 @@ describe('useSavedVisInstance', () => { type: 'area', }); - await waitForNextUpdate(); + await waitFor(() => null); expect(getCreateBreadcrumbs).toHaveBeenCalled(); expect(mockEmbeddableHandlerRender).not.toHaveBeenCalled(); @@ -263,7 +264,7 @@ describe('useSavedVisInstance', () => { describe('embeded mode', () => { test('should create new visualization based on search params', async () => { - const { result, unmount, waitForNextUpdate } = renderHook(() => + const { result, unmount } = renderHook(() => useSavedVisInstance(mockServices, eventEmitter, false, undefined, savedVisId) ); @@ -273,7 +274,7 @@ describe('useSavedVisInstance', () => { expect(mockGetVisualizationInstance).toHaveBeenCalledWith(mockServices, savedVisId); - await waitForNextUpdate(); + await waitFor(() => null); expect(mockEmbeddableHandlerRender).toHaveBeenCalled(); expect(result.current.visEditorController).toBeUndefined(); diff --git a/src/plugins/visualizations/public/visualize_app/utils/use/use_visualize_app_state.test.ts b/src/plugins/visualizations/public/visualize_app/utils/use/use_visualize_app_state.test.ts index f92bd7304a7e8..2acdbf322dad7 100644 --- a/src/plugins/visualizations/public/visualize_app/utils/use/use_visualize_app_state.test.ts +++ b/src/plugins/visualizations/public/visualize_app/utils/use/use_visualize_app_state.test.ts @@ -7,7 +7,8 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { EventEmitter } from 'events'; import { Observable } from 'rxjs'; @@ -159,11 +160,11 @@ describe('useVisualizeAppState', () => { it('should successfully update vis state and set up app state container', async () => { stateContainerGetStateMock.mockImplementation(() => state); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useVisualizeAppState(mockServices, eventEmitter, savedVisInstance) ); - await waitForNextUpdate(); + await waitFor(() => null); const { aggs, ...visState } = stateContainer.getState().vis; const expectedNewVisState = { @@ -183,11 +184,11 @@ describe('useVisualizeAppState', () => { ...visualizeAppStateStub, query: { query: 'test', language: 'kuery' }, })); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useVisualizeAppState(mockServices, eventEmitter, savedVisInstance) ); - await waitForNextUpdate(); + await waitFor(() => null); const { aggs, ...visState } = stateContainer.getState().vis; const expectedNewVisState = { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/anonymization_fields/use_fetch_anonymization_fields.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/anonymization_fields/use_fetch_anonymization_fields.test.tsx index 5352e60bcea45..63d658241ab7e 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/anonymization_fields/use_fetch_anonymization_fields.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/anonymization_fields/use_fetch_anonymization_fields.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import type { ReactNode } from 'react'; @@ -42,8 +43,8 @@ describe('useFetchAnonymizationFields', () => { }); await act(async () => { - const { waitForNextUpdate } = renderHook(() => useFetchAnonymizationFields()); - await waitForNextUpdate(); + renderHook(() => useFetchAnonymizationFields()); + await waitFor(() => null); expect(http.fetch).toHaveBeenCalledWith( '/api/security_ai_assistant/anonymization_fields/_find', { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/conversations/conversations.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/conversations/conversations.test.tsx index 7e87ca79e88ab..4e6aa96f6a00c 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/conversations/conversations.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/conversations/conversations.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { DeleteConversationParams, @@ -32,8 +33,8 @@ describe('conversations api', () => { await act(async () => { const deleteProps = { http, toasts, id: 'test' } as unknown as DeleteConversationParams; - const { waitForNextUpdate } = renderHook(() => deleteConversation(deleteProps)); - await waitForNextUpdate(); + renderHook(() => deleteConversation(deleteProps)); + await waitFor(() => null); expect(deleteProps.http.fetch).toHaveBeenCalledWith( '/api/security_ai_assistant/current_user/conversations/test', @@ -58,8 +59,8 @@ describe('conversations api', () => { it('should call api to get conversation', async () => { await act(async () => { const getProps = { http, toasts, id: 'test' } as unknown as GetConversationByIdParams; - const { waitForNextUpdate } = renderHook(() => getConversationById(getProps)); - await waitForNextUpdate(); + renderHook(() => getConversationById(getProps)); + await waitFor(() => null); expect(getProps.http.fetch).toHaveBeenCalledWith( '/api/security_ai_assistant/current_user/conversations/test', diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/conversations/use_fetch_current_user_conversations.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/conversations/use_fetch_current_user_conversations.test.tsx index 652764212e996..a7f8baf166376 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/conversations/use_fetch_current_user_conversations.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/conversations/use_fetch_current_user_conversations.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import type { ReactNode } from 'react'; @@ -42,10 +43,8 @@ describe('useFetchCurrentUserConversations', () => { }); await act(async () => { - const { waitForNextUpdate } = renderHook(() => - useFetchCurrentUserConversations(defaultProps) - ); - await waitForNextUpdate(); + renderHook(() => useFetchCurrentUserConversations(defaultProps)); + await waitFor(() => null); expect(defaultProps.http.fetch).toHaveBeenCalledWith( '/api/security_ai_assistant/current_user/conversations/_find', { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/evaluate/use_perform_evaluation.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/evaluate/use_perform_evaluation.test.tsx index 6d1296fc9aa64..9809467e41f2d 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/evaluate/use_perform_evaluation.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/evaluate/use_perform_evaluation.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { usePerformEvaluation, UsePerformEvaluationParams } from './use_perform_evaluation'; import { postEvaluation as _postEvaluation } from './evaluate'; import { useMutation as _useMutation } from '@tanstack/react-query'; @@ -51,8 +52,8 @@ describe('usePerformEvaluation', () => { }); it('should call api with undefined evalParams', async () => { await act(async () => { - const { waitForNextUpdate } = renderHook(() => usePerformEvaluation(defaultProps)); - await waitForNextUpdate(); + renderHook(() => usePerformEvaluation(defaultProps)); + await waitFor(() => null); expect(defaultProps.http.post).toHaveBeenCalledWith('/internal/elastic_assistant/evaluate', { body: undefined, @@ -81,8 +82,8 @@ describe('usePerformEvaluation', () => { } }); await act(async () => { - const { waitForNextUpdate } = renderHook(() => usePerformEvaluation(defaultProps)); - await waitForNextUpdate(); + renderHook(() => usePerformEvaluation(defaultProps)); + await waitFor(() => null); expect(defaultProps.http.post).toHaveBeenCalledWith('/internal/elastic_assistant/evaluate', { body: '{"graphs":["d","c"],"datasetName":"kewl","connectorIds":["h","g"],"runName":"test run"}', @@ -97,8 +98,8 @@ describe('usePerformEvaluation', () => { it('should return evaluation response', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => usePerformEvaluation(defaultProps)); - await waitForNextUpdate(); + const { result } = renderHook(() => usePerformEvaluation(defaultProps)); + await waitFor(() => null); await expect(result.current).resolves.toStrictEqual(statusResponse); }); @@ -107,8 +108,8 @@ describe('usePerformEvaluation', () => { it('should display error toast when api throws error', async () => { postEvaluationMock.mockRejectedValue(new Error('this is an error')); await act(async () => { - const { waitForNextUpdate } = renderHook(() => usePerformEvaluation(defaultProps)); - await waitForNextUpdate(); + renderHook(() => usePerformEvaluation(defaultProps)); + await waitFor(() => null); expect(toasts.addError).toHaveBeenCalled(); }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.test.tsx index b50c345edb3b3..10ce8bab59c6e 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useDeleteKnowledgeBase, UseDeleteKnowledgeBaseParams } from './use_delete_knowledge_base'; import { deleteKnowledgeBase as _deleteKnowledgeBase } from './api'; import { useMutation as _useMutation } from '@tanstack/react-query'; @@ -51,8 +52,8 @@ describe('useDeleteKnowledgeBase', () => { }); it('should call api to delete knowledge base', async () => { await act(async () => { - const { waitForNextUpdate } = renderHook(() => useDeleteKnowledgeBase(defaultProps)); - await waitForNextUpdate(); + renderHook(() => useDeleteKnowledgeBase(defaultProps)); + await waitFor(() => null); expect(defaultProps.http.fetch).toHaveBeenCalledWith( '/internal/elastic_assistant/knowledge_base/', @@ -75,8 +76,8 @@ describe('useDeleteKnowledgeBase', () => { } }); await act(async () => { - const { waitForNextUpdate } = renderHook(() => useDeleteKnowledgeBase(defaultProps)); - await waitForNextUpdate(); + renderHook(() => useDeleteKnowledgeBase(defaultProps)); + await waitFor(() => null); expect(defaultProps.http.fetch).toHaveBeenCalledWith( '/internal/elastic_assistant/knowledge_base/something', @@ -91,8 +92,8 @@ describe('useDeleteKnowledgeBase', () => { it('should return delete response', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useDeleteKnowledgeBase(defaultProps)); - await waitForNextUpdate(); + renderHook(() => useDeleteKnowledgeBase(defaultProps)); + await waitFor(() => null); await expect(result.current).resolves.toStrictEqual(statusResponse); }); @@ -101,8 +102,8 @@ describe('useDeleteKnowledgeBase', () => { it('should display error toast when api throws error', async () => { deleteKnowledgeBaseMock.mockRejectedValue(new Error('this is an error')); await act(async () => { - const { waitForNextUpdate } = renderHook(() => useDeleteKnowledgeBase(defaultProps)); - await waitForNextUpdate(); + renderHook(() => useDeleteKnowledgeBase(defaultProps)); + await waitFor(() => null); expect(toasts.addError).toHaveBeenCalled(); }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_knowledge_base_status.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_knowledge_base_status.test.tsx index 80ce3d27d8dcb..4c9d0bae2fcef 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_knowledge_base_status.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_knowledge_base_status.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useKnowledgeBaseStatus, UseKnowledgeBaseStatusParams } from './use_knowledge_base_status'; import { getKnowledgeBaseStatus as _getKnowledgeBaseStatus } from './api'; @@ -49,8 +50,8 @@ describe('useKnowledgeBaseStatus', () => { }); it('should call api to get knowledge base status without resource arg', async () => { await act(async () => { - const { waitForNextUpdate } = renderHook(() => useKnowledgeBaseStatus(defaultProps)); - await waitForNextUpdate(); + renderHook(() => useKnowledgeBaseStatus(defaultProps)); + await waitFor(() => null); expect(defaultProps.http.fetch).toHaveBeenCalledWith( '/internal/elastic_assistant/knowledge_base/', @@ -65,10 +66,8 @@ describe('useKnowledgeBaseStatus', () => { }); it('should call api to get knowledge base status with resource arg', async () => { await act(async () => { - const { waitForNextUpdate } = renderHook(() => - useKnowledgeBaseStatus({ ...defaultProps, resource: 'something' }) - ); - await waitForNextUpdate(); + renderHook(() => useKnowledgeBaseStatus({ ...defaultProps, resource: 'something' })); + await waitFor(() => null); expect(defaultProps.http.fetch).toHaveBeenCalledWith( '/internal/elastic_assistant/knowledge_base/something', @@ -83,8 +82,8 @@ describe('useKnowledgeBaseStatus', () => { it('should return status response', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useKnowledgeBaseStatus(defaultProps)); - await waitForNextUpdate(); + const { result } = renderHook(() => useKnowledgeBaseStatus(defaultProps)); + await waitFor(() => null); await expect(result.current).resolves.toStrictEqual(statusResponse); }); @@ -93,8 +92,8 @@ describe('useKnowledgeBaseStatus', () => { it('should display error toast when api throws error', async () => { getKnowledgeBaseStatusMock.mockRejectedValue(new Error('this is an error')); await act(async () => { - const { waitForNextUpdate } = renderHook(() => useKnowledgeBaseStatus(defaultProps)); - await waitForNextUpdate(); + renderHook(() => useKnowledgeBaseStatus(defaultProps)); + await waitFor(() => null); expect(toasts.addError).toHaveBeenCalled(); }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_setup_knowledge_base.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_setup_knowledge_base.test.tsx index c08f6f93617fc..084bb3c9f29c8 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_setup_knowledge_base.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_setup_knowledge_base.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useSetupKnowledgeBase, UseSetupKnowledgeBaseParams } from './use_setup_knowledge_base'; import { postKnowledgeBase as _postKnowledgeBase } from './api'; import { useMutation as _useMutation } from '@tanstack/react-query'; @@ -51,8 +52,8 @@ describe('useSetupKnowledgeBase', () => { }); it('should call api to post knowledge base setup', async () => { await act(async () => { - const { waitForNextUpdate } = renderHook(() => useSetupKnowledgeBase(defaultProps)); - await waitForNextUpdate(); + renderHook(() => useSetupKnowledgeBase(defaultProps)); + await waitFor(() => null); expect(defaultProps.http.fetch).toHaveBeenCalledWith( '/internal/elastic_assistant/knowledge_base/', @@ -74,8 +75,8 @@ describe('useSetupKnowledgeBase', () => { } }); await act(async () => { - const { waitForNextUpdate } = renderHook(() => useSetupKnowledgeBase(defaultProps)); - await waitForNextUpdate(); + renderHook(() => useSetupKnowledgeBase(defaultProps)); + await waitFor(() => null); expect(defaultProps.http.fetch).toHaveBeenCalledWith( '/internal/elastic_assistant/knowledge_base/something', @@ -89,8 +90,8 @@ describe('useSetupKnowledgeBase', () => { it('should return setup response', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useSetupKnowledgeBase(defaultProps)); - await waitForNextUpdate(); + const { result } = renderHook(() => useSetupKnowledgeBase(defaultProps)); + await waitFor(() => null); await expect(result.current).resolves.toStrictEqual(statusResponse); }); @@ -99,8 +100,8 @@ describe('useSetupKnowledgeBase', () => { it('should display error toast when api throws error', async () => { postKnowledgeBaseMock.mockRejectedValue(new Error('this is an error')); await act(async () => { - const { waitForNextUpdate } = renderHook(() => useSetupKnowledgeBase(defaultProps)); - await waitForNextUpdate(); + renderHook(() => useSetupKnowledgeBase(defaultProps)); + await waitFor(() => null); expect(toasts.addError).toHaveBeenCalled(); }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.test.tsx index 8e228d2787a36..2e8b0e79c9382 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/prompts/use_fetch_prompts.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import type { ReactNode } from 'react'; @@ -42,8 +43,8 @@ describe('useFetchPrompts', () => { }); await act(async () => { - const { waitForNextUpdate } = renderHook(() => useFetchPrompts()); - await waitForNextUpdate(); + renderHook(() => useFetchPrompts()); + await waitFor(() => null); expect(http.fetch).toHaveBeenCalledWith('/api/security_ai_assistant/prompts/_find', { method: 'GET', query: { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx index e3a6ab1fc75b5..715f8371f7567 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/settings/use_settings_updater/use_settings_updater.test.tsx @@ -4,7 +4,9 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; + +import { act, waitFor } from '@testing-library/react'; import { DEFAULT_LATEST_ALERTS } from '../../../assistant_context/constants'; import { alertConvo, welcomeConvo } from '../../../mock/conversation'; @@ -99,7 +101,7 @@ describe('useSettingsUpdater', () => { }); it('should set all state variables to their initial values when resetSettings is called', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useSettingsUpdater( mockConversations, { @@ -113,7 +115,7 @@ describe('useSettingsUpdater', () => { anonymizationFields ) ); - await waitForNextUpdate(); + await waitFor(() => null); const { setConversationSettings, setConversationsSettingsBulkActions, @@ -156,7 +158,7 @@ describe('useSettingsUpdater', () => { it('should update all state variables to their updated values when saveSettings is called', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useSettingsUpdater( mockConversations, { @@ -170,7 +172,7 @@ describe('useSettingsUpdater', () => { anonymizationFields ) ); - await waitForNextUpdate(); + await waitFor(() => null); const { setConversationSettings, setConversationsSettingsBulkActions, @@ -204,7 +206,7 @@ describe('useSettingsUpdater', () => { }); it('should track when alerts count is updated', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useSettingsUpdater( mockConversations, { @@ -218,7 +220,7 @@ describe('useSettingsUpdater', () => { anonymizationFields ) ); - await waitForNextUpdate(); + await waitFor(() => null); const { setUpdatedKnowledgeBaseSettings } = result.current; setUpdatedKnowledgeBaseSettings({ @@ -230,7 +232,7 @@ describe('useSettingsUpdater', () => { }); it('should track when streaming is updated', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useSettingsUpdater( mockConversations, { @@ -244,7 +246,7 @@ describe('useSettingsUpdater', () => { anonymizationFields ) ); - await waitForNextUpdate(); + await waitFor(() => null); const { setUpdatedAssistantStreamingEnabled } = result.current; setUpdatedAssistantStreamingEnabled(false); @@ -256,7 +258,7 @@ describe('useSettingsUpdater', () => { }); it('if no settings update, do not track anything', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useSettingsUpdater( mockConversations, { @@ -270,7 +272,7 @@ describe('useSettingsUpdater', () => { anonymizationFields ) ); - await waitForNextUpdate(); + await waitFor(() => null); const { setUpdatedKnowledgeBaseSettings } = result.current; setUpdatedKnowledgeBaseSettings(mockValues.knowledgeBase); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.test.tsx index 696a2e41b37c2..4fc8e64ca8525 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.test.tsx @@ -6,7 +6,8 @@ */ import { useConversation } from '.'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { TestProviders } from '../../mock/test_providers/test_providers'; import React from 'react'; import { MessageRole } from '@kbn/elastic-assistant-common'; @@ -54,79 +55,86 @@ describe('useConversation', () => { }); it('should create a new conversation when called with valid conversationId and message', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useConversation(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( - {children} - ), - }); - await waitForNextUpdate(); - createConversation.mockResolvedValue(mockConvo); + const { result } = renderHook(() => useConversation(), { + wrapper: ({ children }) => ( + {children} + ), + }); + + await waitFor(() => null); + + createConversation.mockResolvedValue(mockConvo); + + let createResult; - const createResult = await result.current.createConversation({ + act(async () => { + createResult = await result.current.createConversation({ ...mockConvo, replacements: {}, title: mockConvo.title, category: 'assistant', }); - - expect(createResult).toEqual(mockConvo); }); + + expect(createResult).toEqual(mockConvo); }); it('should delete an existing conversation when called with valid conversationId', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useConversation(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( - {children} - ), - }); - await waitForNextUpdate(); + const { result } = renderHook(() => useConversation(), { + wrapper: ({ children }) => ( + {children} + ), + }); + + await waitFor(() => null); + act(async () => { await result.current.deleteConversation('new-convo'); + }); - expect(deleteConversation).toHaveBeenCalledWith({ - http: httpMock, - id: 'new-convo', - }); + expect(deleteConversation).toHaveBeenCalledWith({ + http: httpMock, + id: 'new-convo', }); }); it('should update the apiConfig for an existing conversation when called with a valid conversationId and apiConfig', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useConversation(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( - {children} - ), - }); - await waitForNextUpdate(); + const { result } = renderHook(() => useConversation(), { + wrapper: ({ children }) => ( + {children} + ), + }); + await waitFor(() => null); + act(async () => { await result.current.setApiConfig({ conversation: WELCOME_CONVERSATION, apiConfig: mockConvo.apiConfig, }); + }); - expect(createConversation).toHaveBeenCalledWith({ - http: httpMock, - conversation: { ...WELCOME_CONVERSATION, apiConfig: mockConvo.apiConfig, id: '' }, - }); + expect(createConversation).toHaveBeenCalledWith({ + http: httpMock, + conversation: { ...WELCOME_CONVERSATION, apiConfig: mockConvo.apiConfig, id: '' }, }); }); it('should remove the last message from a conversation when called with valid conversationId', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useConversation(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( - {children} - ), - }); - await waitForNextUpdate(); + const { result } = renderHook(() => useConversation(), { + wrapper: ({ children }) => ( + {children} + ), + }); + await waitFor(() => null); - getConversationById.mockResolvedValue(mockConvo); + getConversationById.mockResolvedValue(mockConvo); - const removeResult = await result.current.removeLastMessage('new-convo'); + let removeResult; - expect(removeResult).toEqual([message]); + act(async () => { + removeResult = await result.current.removeLastMessage('new-convo'); }); + + expect(removeResult).toEqual([message]); }); }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_action_types/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_action_types/index.test.tsx index 50d3a73797413..ab955c13bd10e 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_action_types/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_action_types/index.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useLoadActionTypes, Props } from '.'; import { mockActionTypes } from '../../mock/connectors'; @@ -33,8 +34,8 @@ describe('useLoadActionTypes', () => { }); it('should call api to load action types', async () => { await act(async () => { - const { waitForNextUpdate } = renderHook(() => useLoadActionTypes(defaultProps)); - await waitForNextUpdate(); + renderHook(() => useLoadActionTypes(defaultProps)); + await waitFor(() => null); expect(defaultProps.http.get).toHaveBeenCalledWith('/api/actions/connector_types', { query: { feature_id: 'generativeAIForSecurity' }, @@ -45,8 +46,8 @@ describe('useLoadActionTypes', () => { it('should return sorted action types', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useLoadActionTypes(defaultProps)); - await waitForNextUpdate(); + const { result } = renderHook(() => useLoadActionTypes(defaultProps)); + await waitFor(() => null); await expect(result.current).resolves.toStrictEqual( mockActionTypes.sort((a, b) => a.name.localeCompare(b.name)) @@ -58,10 +59,8 @@ describe('useLoadActionTypes', () => { const mockHttp = { get: jest.fn().mockRejectedValue(new Error('this is an error')), } as unknown as Props['http']; - const { waitForNextUpdate } = renderHook(() => - useLoadActionTypes({ ...defaultProps, http: mockHttp }) - ); - await waitForNextUpdate(); + renderHook(() => useLoadActionTypes({ ...defaultProps, http: mockHttp })); + await waitFor(() => null); expect(toasts.addError).toHaveBeenCalled(); }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_connectors/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_connectors/index.test.tsx index b29274efb19c0..740d854773a8a 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_connectors/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_connectors/index.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useLoadConnectors, Props } from '.'; import { mockConnectors } from '../../mock/connectors'; @@ -69,8 +70,8 @@ describe('useLoadConnectors', () => { }); it('should call api to load action types', async () => { await act(async () => { - const { waitForNextUpdate } = renderHook(() => useLoadConnectors(defaultProps)); - await waitForNextUpdate(); + renderHook(() => useLoadConnectors(defaultProps)); + await waitFor(() => null); expect(defaultProps.http.get).toHaveBeenCalledWith('/api/actions/connectors'); expect(toasts.addError).not.toHaveBeenCalled(); @@ -79,8 +80,8 @@ describe('useLoadConnectors', () => { it('should return sorted action types, removing isMissingSecrets and wrong action type ids', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useLoadConnectors(defaultProps)); - await waitForNextUpdate(); + const { result } = renderHook(() => useLoadConnectors(defaultProps)); + await waitFor(() => null); await expect(result.current).resolves.toStrictEqual( // @ts-ignore ts does not like config, but we define it in the mock data @@ -93,10 +94,8 @@ describe('useLoadConnectors', () => { const mockHttp = { get: jest.fn().mockRejectedValue(new Error('this is an error')), } as unknown as Props['http']; - const { waitForNextUpdate } = renderHook(() => - useLoadConnectors({ ...defaultProps, http: mockHttp }) - ); - await waitForNextUpdate(); + renderHook(() => useLoadConnectors({ ...defaultProps, http: mockHttp })); + await waitFor(() => null); expect(toasts.addError).toHaveBeenCalled(); }); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/hooks/use_ilm_explain/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/hooks/use_ilm_explain/index.test.tsx index bfc66c3711dbb..7e0721ccc1cf1 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/hooks/use_ilm_explain/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/hooks/use_ilm_explain/index.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import React from 'react'; import { DataQualityProvider } from '../../../../../data_quality_context'; @@ -89,10 +90,10 @@ describe('useIlmExplain', () => { beforeEach(async () => { mockHttpFetch.mockResolvedValue(mockIlmExplain); - const { result, waitForNextUpdate } = renderHook(() => useIlmExplain(pattern), { + const { result } = renderHook(() => useIlmExplain(pattern), { wrapper: ContextWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); ilmExplainResult = await result.current; }); @@ -113,8 +114,8 @@ describe('useIlmExplain', () => { let ilmExplainResult: UseIlmExplain | undefined; beforeEach(async () => { - const { result, waitForNextUpdate } = renderHook(() => useIlmExplain(pattern), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + const { result } = renderHook(() => useIlmExplain(pattern), { + wrapper: ({ children }) => ( { ), }); - await waitForNextUpdate(); + await waitFor(() => null); ilmExplainResult = await result.current; }); @@ -184,10 +185,10 @@ describe('useIlmExplain', () => { beforeEach(async () => { mockHttpFetch.mockRejectedValue(new Error(errorMessage)); - const { result, waitForNextUpdate } = renderHook(() => useIlmExplain(pattern), { + const { result } = renderHook(() => useIlmExplain(pattern), { wrapper: ContextWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); ilmExplainResult = await result.current; }); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/hooks/use_stats/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/hooks/use_stats/index.test.tsx index 061bbb5aa6824..f46e07b98cf39 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/hooks/use_stats/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/hooks/use_stats/index.test.tsx @@ -146,10 +146,10 @@ describe('useStats', () => { beforeEach(async () => { mockHttpFetch.mockResolvedValue(mockStatsAuditbeatIndex); - const { waitForNextUpdate } = renderHook(() => useStats({ pattern, startDate, endDate }), { + renderHook(() => useStats({ pattern, startDate, endDate }), { wrapper: ContextWrapperILMNotAvailable, }); - await waitForNextUpdate(); + await waitFor(() => null); }); test(`it calls the stats api with the expected params`, async () => { expect(mockHttpFetch.mock.calls[0][1].query).toEqual(queryParams); @@ -162,10 +162,10 @@ describe('useStats', () => { beforeEach(async () => { mockHttpFetch.mockResolvedValue(mockStatsAuditbeatIndex); - const { result, waitForNextUpdate } = renderHook(() => useStats(params), { + const { result } = renderHook(() => useStats(params), { wrapper: ContextWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); statsResult = await result.current; }); @@ -193,10 +193,10 @@ describe('useStats', () => { beforeEach(async () => { mockHttpFetch.mockRejectedValue(new Error(errorMessage)); - const { result, waitForNextUpdate } = renderHook(() => useStats(params), { + const { result } = renderHook(() => useStats(params), { wrapper: ContextWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); statsResult = await result.current; }); diff --git a/x-pack/plugins/cases/public/containers/configure/use_action_types.test.tsx b/x-pack/plugins/cases/public/containers/configure/use_action_types.test.tsx index 5718b07438a98..01f2585ec3818 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_action_types.test.tsx +++ b/x-pack/plugins/cases/public/containers/configure/use_action_types.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import * as api from './api'; import type { AppMockRenderer } from '../../common/mock'; import { createAppMockRenderer } from '../../common/mock'; @@ -43,10 +44,10 @@ describe('useActionTypes', () => { (useToasts as jest.Mock).mockReturnValue({ addError: addErrorMock }); - const { waitForNextUpdate } = renderHook(() => useGetActionTypes(), { + renderHook(() => useGetActionTypes(), { wrapper: appMockRenderer.AppWrapper, }); - await waitForNextUpdate({ timeout: 2000 }); + await waitFor(() => null, { timeout: 2000 }); expect(addErrorMock).toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/cases/public/containers/configure/use_get_all_case_configurations.test.ts b/x-pack/plugins/cases/public/containers/configure/use_get_all_case_configurations.test.ts index cd9e44d1bdaae..a50aa3e53b3c2 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_get_all_case_configurations.test.ts +++ b/x-pack/plugins/cases/public/containers/configure/use_get_all_case_configurations.test.ts @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useGetAllCaseConfigurations } from './use_get_all_case_configurations'; import * as api from './api'; import type { AppMockRenderer } from '../../common/mock'; @@ -32,11 +33,11 @@ describe('Use get all case configurations hook', () => { { id: 'my-configuration-3', owner: '3' }, ]); - const { result, waitForNextUpdate } = renderHook(() => useGetAllCaseConfigurations(), { + const { result } = renderHook(() => useGetAllCaseConfigurations(), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); /** * Ensures that the initial data is returned≠ @@ -71,11 +72,11 @@ describe('Use get all case configurations hook', () => { const spy = jest.spyOn(api, 'getCaseConfigure'); spy.mockResolvedValue([]); - const { result, waitForNextUpdate } = renderHook(() => useGetAllCaseConfigurations(), { + const { result } = renderHook(() => useGetAllCaseConfigurations(), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); /** * Ensures that the initial data is returned≠ diff --git a/x-pack/plugins/cases/public/containers/configure/use_get_case_configuration.test.tsx b/x-pack/plugins/cases/public/containers/configure/use_get_case_configuration.test.tsx index e504bd22e9cc8..2ac0a4573e6da 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_get_case_configuration.test.tsx +++ b/x-pack/plugins/cases/public/containers/configure/use_get_case_configuration.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useGetCaseConfiguration } from './use_get_case_configuration'; import * as api from './api'; import type { AppMockRenderer } from '../../common/mock'; @@ -35,11 +36,11 @@ describe('Use get case configuration hook', () => { targetConfiguration, ]); - const { result, waitForNextUpdate } = renderHook(() => useGetCaseConfiguration(), { + const { result } = renderHook(() => useGetCaseConfiguration(), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); /** * The response after fetching @@ -59,11 +60,11 @@ describe('Use get case configuration hook', () => { { ...initialConfiguration, id: 'my-new-configuration-2', owner: 'bar' }, ]); - const { result, waitForNextUpdate } = renderHook(() => useGetCaseConfiguration(), { + const { result } = renderHook(() => useGetCaseConfiguration(), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); /** * The response after fetching @@ -76,11 +77,11 @@ describe('Use get case configuration hook', () => { spy.mockResolvedValue([]); - const { result, waitForNextUpdate } = renderHook(() => useGetCaseConfiguration(), { + const { result } = renderHook(() => useGetCaseConfiguration(), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); /** * The response after fetching @@ -94,11 +95,11 @@ describe('Use get case configuration hook', () => { spy.mockResolvedValue([]); - const { result, waitForNextUpdate } = renderHook(() => useGetCaseConfiguration(), { + const { result } = renderHook(() => useGetCaseConfiguration(), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); /** * The response after fetching diff --git a/x-pack/plugins/cases/public/containers/configure/use_get_supported_action_connectors.tsx.test.tsx b/x-pack/plugins/cases/public/containers/configure/use_get_supported_action_connectors.tsx.test.tsx index a81d6ac46d189..cebbd3bb5c924 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_get_supported_action_connectors.tsx.test.tsx +++ b/x-pack/plugins/cases/public/containers/configure/use_get_supported_action_connectors.tsx.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import * as api from './api'; import { noConnectorsCasePermission, TestProviders } from '../../common/mock'; import { useApplicationCapabilities, useToasts } from '../../common/lib/kibana'; @@ -26,13 +27,11 @@ describe('useConnectors', () => { it('fetches connectors', async () => { const spy = jest.spyOn(api, 'getSupportedActionConnectors'); - const { waitForNextUpdate } = renderHook(() => useGetSupportedActionConnectors(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( - {children} - ), + renderHook(() => useGetSupportedActionConnectors(), { + wrapper: ({ children }) => {children}, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith({ signal: expect.any(AbortSignal) }); }); @@ -46,12 +45,10 @@ describe('useConnectors', () => { throw new Error('Something went wrong'); }); - const { waitForNextUpdate } = renderHook(() => useGetSupportedActionConnectors(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( - {children} - ), + renderHook(() => useGetSupportedActionConnectors(), { + wrapper: ({ children }) => {children}, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addError).toHaveBeenCalled(); }); @@ -60,13 +57,11 @@ describe('useConnectors', () => { const spyOnFetchConnectors = jest.spyOn(api, 'getSupportedActionConnectors'); useApplicationCapabilitiesMock().actions = { crud: false, read: false }; - const { result, waitForNextUpdate } = renderHook(() => useGetSupportedActionConnectors(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( - {children} - ), + const { result } = renderHook(() => useGetSupportedActionConnectors(), { + wrapper: ({ children }) => {children}, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spyOnFetchConnectors).not.toHaveBeenCalled(); expect(result.current.data).toEqual([]); @@ -76,13 +71,13 @@ describe('useConnectors', () => { const spyOnFetchConnectors = jest.spyOn(api, 'getSupportedActionConnectors'); useApplicationCapabilitiesMock().actions = { crud: true, read: true }; - const { result, waitForNextUpdate } = renderHook(() => useGetSupportedActionConnectors(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + const { result } = renderHook(() => useGetSupportedActionConnectors(), { + wrapper: ({ children }) => ( {children} ), }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spyOnFetchConnectors).not.toHaveBeenCalled(); expect(result.current.data).toEqual([]); diff --git a/x-pack/plugins/cases/public/containers/use_bulk_update_case.test.tsx b/x-pack/plugins/cases/public/containers/use_bulk_update_case.test.tsx index 17b4568cc9de7..d4d5fadc40b3c 100644 --- a/x-pack/plugins/cases/public/containers/use_bulk_update_case.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_bulk_update_case.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useUpdateCases } from './use_bulk_update_case'; import { allCases } from './mock'; import { useToasts } from '../common/lib/kibana'; @@ -32,7 +33,7 @@ describe('useUpdateCases', () => { it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'updateCases'); - const { waitForNextUpdate, result } = renderHook(() => useUpdateCases(), { + const { result } = renderHook(() => useUpdateCases(), { wrapper: appMockRender.AppWrapper, }); @@ -40,14 +41,14 @@ describe('useUpdateCases', () => { result.current.mutate({ cases: allCases.cases, successToasterTitle: 'Success title' }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith({ cases: allCases.cases }); }); it('invalidates the queries correctly', async () => { const queryClientSpy = jest.spyOn(appMockRender.queryClient, 'invalidateQueries'); - const { waitForNextUpdate, result } = renderHook(() => useUpdateCases(), { + const { result } = renderHook(() => useUpdateCases(), { wrapper: appMockRender.AppWrapper, }); @@ -55,7 +56,7 @@ describe('useUpdateCases', () => { result.current.mutate({ cases: allCases.cases, successToasterTitle: 'Success title' }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.casesList()); expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags()); @@ -63,7 +64,7 @@ describe('useUpdateCases', () => { }); it('shows a success toaster', async () => { - const { waitForNextUpdate, result } = renderHook(() => useUpdateCases(), { + const { result } = renderHook(() => useUpdateCases(), { wrapper: appMockRender.AppWrapper, }); @@ -71,7 +72,7 @@ describe('useUpdateCases', () => { result.current.mutate({ cases: allCases.cases, successToasterTitle: 'Success title' }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addSuccess).toHaveBeenCalledWith({ title: 'Success title', @@ -82,7 +83,7 @@ describe('useUpdateCases', () => { it('shows a toast error when the api return an error', async () => { jest.spyOn(api, 'updateCases').mockRejectedValue(new Error('useUpdateCases: Test error')); - const { waitForNextUpdate, result } = renderHook(() => useUpdateCases(), { + const { result } = renderHook(() => useUpdateCases(), { wrapper: appMockRender.AppWrapper, }); @@ -90,7 +91,7 @@ describe('useUpdateCases', () => { result.current.mutate({ cases: allCases.cases, successToasterTitle: 'Success title' }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addError).toHaveBeenCalled(); }); diff --git a/x-pack/plugins/cases/public/containers/use_create_attachments.test.tsx b/x-pack/plugins/cases/public/containers/use_create_attachments.test.tsx index 14d4477df62da..da1cdad28d70c 100644 --- a/x-pack/plugins/cases/public/containers/use_create_attachments.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_create_attachments.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { AttachmentType } from '../../common/types/domain'; import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; @@ -58,7 +59,7 @@ describe('useCreateAttachments', () => { it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'createAttachments'); - const { waitForNextUpdate, result } = renderHook(() => useCreateAttachments(), { + const { result } = renderHook(() => useCreateAttachments(), { wrapper: appMockRender.AppWrapper, }); @@ -66,13 +67,13 @@ describe('useCreateAttachments', () => { result.current.mutate(request); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith({ attachments: attachmentsWithOwner, caseId: request.caseId }); }); it('does not show a success toaster', async () => { - const { waitForNextUpdate, result } = renderHook(() => useCreateAttachments(), { + const { result } = renderHook(() => useCreateAttachments(), { wrapper: appMockRender.AppWrapper, }); @@ -80,7 +81,7 @@ describe('useCreateAttachments', () => { result.current.mutate(request); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addSuccess).not.toHaveBeenCalled(); }); @@ -90,7 +91,7 @@ describe('useCreateAttachments', () => { .spyOn(api, 'createAttachments') .mockRejectedValue(new Error('useCreateAttachments: Test error')); - const { waitForNextUpdate, result } = renderHook(() => useCreateAttachments(), { + const { result } = renderHook(() => useCreateAttachments(), { wrapper: appMockRender.AppWrapper, }); @@ -98,7 +99,7 @@ describe('useCreateAttachments', () => { result.current.mutate(request); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addError).toHaveBeenCalled(); }); diff --git a/x-pack/plugins/cases/public/containers/use_delete_cases.test.tsx b/x-pack/plugins/cases/public/containers/use_delete_cases.test.tsx index f0ec4e9a43d87..bd2230f1a7f9c 100644 --- a/x-pack/plugins/cases/public/containers/use_delete_cases.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_delete_cases.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useDeleteCases } from './use_delete_cases'; import * as api from './api'; @@ -32,7 +33,7 @@ describe('useDeleteCases', () => { it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'deleteCases'); - const { waitForNextUpdate, result } = renderHook(() => useDeleteCases(), { + const { result } = renderHook(() => useDeleteCases(), { wrapper: appMockRender.AppWrapper, }); @@ -40,14 +41,14 @@ describe('useDeleteCases', () => { result.current.mutate({ caseIds: ['1', '2'], successToasterTitle: 'Success title' }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith({ caseIds: ['1', '2'] }); }); it('invalidates the queries correctly', async () => { const queryClientSpy = jest.spyOn(appMockRender.queryClient, 'invalidateQueries'); - const { waitForNextUpdate, result } = renderHook(() => useDeleteCases(), { + const { result } = renderHook(() => useDeleteCases(), { wrapper: appMockRender.AppWrapper, }); @@ -55,7 +56,7 @@ describe('useDeleteCases', () => { result.current.mutate({ caseIds: ['1', '2'], successToasterTitle: 'Success title' }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.casesList()); expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags()); @@ -63,7 +64,7 @@ describe('useDeleteCases', () => { }); it('shows a success toaster', async () => { - const { waitForNextUpdate, result } = renderHook(() => useDeleteCases(), { + const { result } = renderHook(() => useDeleteCases(), { wrapper: appMockRender.AppWrapper, }); @@ -71,7 +72,7 @@ describe('useDeleteCases', () => { result.current.mutate({ caseIds: ['1', '2'], successToasterTitle: 'Success title' }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addSuccess).toHaveBeenCalledWith({ title: 'Success title', @@ -82,7 +83,7 @@ describe('useDeleteCases', () => { it('shows a toast error when the api return an error', async () => { jest.spyOn(api, 'deleteCases').mockRejectedValue(new Error('useDeleteCases: Test error')); - const { waitForNextUpdate, result } = renderHook(() => useDeleteCases(), { + const { result } = renderHook(() => useDeleteCases(), { wrapper: appMockRender.AppWrapper, }); @@ -90,7 +91,7 @@ describe('useDeleteCases', () => { result.current.mutate({ caseIds: ['1', '2'], successToasterTitle: 'Success title' }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addError).toHaveBeenCalled(); }); diff --git a/x-pack/plugins/cases/public/containers/use_delete_comment.test.tsx b/x-pack/plugins/cases/public/containers/use_delete_comment.test.tsx index c185a7394c887..6c0d534847b12 100644 --- a/x-pack/plugins/cases/public/containers/use_delete_comment.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_delete_comment.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useDeleteComment } from './use_delete_comment'; import * as api from './api'; import { basicCaseId } from './mock'; @@ -45,7 +46,7 @@ describe('useDeleteComment', () => { it('calls deleteComment with correct arguments - case', async () => { const spyOnDeleteComment = jest.spyOn(api, 'deleteComment'); - const { waitForNextUpdate, result } = renderHook(() => useDeleteComment(), { + const { result } = renderHook(() => useDeleteComment(), { wrapper: appMockRender.AppWrapper, }); @@ -57,7 +58,7 @@ describe('useDeleteComment', () => { }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spyOnDeleteComment).toBeCalledWith({ caseId: basicCaseId, @@ -66,7 +67,7 @@ describe('useDeleteComment', () => { }); it('refreshes the case page view after delete', async () => { - const { waitForNextUpdate, result } = renderHook(() => useDeleteComment(), { + const { result } = renderHook(() => useDeleteComment(), { wrapper: appMockRender.AppWrapper, }); @@ -76,13 +77,13 @@ describe('useDeleteComment', () => { successToasterTitle, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(useRefreshCaseViewPage()).toBeCalled(); }); it('shows a success toaster correctly', async () => { - const { waitForNextUpdate, result } = renderHook(() => useDeleteComment(), { + const { result } = renderHook(() => useDeleteComment(), { wrapper: appMockRender.AppWrapper, }); @@ -94,7 +95,7 @@ describe('useDeleteComment', () => { }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addSuccess).toHaveBeenCalledWith({ title: 'Deleted', @@ -106,7 +107,7 @@ describe('useDeleteComment', () => { const spyOnDeleteComment = jest.spyOn(api, 'deleteComment'); spyOnDeleteComment.mockRejectedValue(new Error('Error')); - const { waitForNextUpdate, result } = renderHook(() => useDeleteComment(), { + const { result } = renderHook(() => useDeleteComment(), { wrapper: appMockRender.AppWrapper, }); @@ -116,7 +117,7 @@ describe('useDeleteComment', () => { successToasterTitle, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spyOnDeleteComment).toBeCalledWith({ caseId: basicCaseId, diff --git a/x-pack/plugins/cases/public/containers/use_delete_file_attachment.test.tsx b/x-pack/plugins/cases/public/containers/use_delete_file_attachment.test.tsx index 51382a0f548da..fc6749ffc999a 100644 --- a/x-pack/plugins/cases/public/containers/use_delete_file_attachment.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_delete_file_attachment.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import * as api from './api'; import { basicCaseId, basicFileMock } from './mock'; import { useRefreshCaseViewPage } from '../components/case_view/use_on_refresh_case_view_page'; @@ -34,7 +35,7 @@ describe('useDeleteFileAttachment', () => { it('calls deleteFileAttachment with correct arguments - case', async () => { const spyOnDeleteFileAttachments = jest.spyOn(api, 'deleteFileAttachments'); - const { waitForNextUpdate, result } = renderHook(() => useDeleteFileAttachment(), { + const { result } = renderHook(() => useDeleteFileAttachment(), { wrapper: appMockRender.AppWrapper, }); @@ -45,7 +46,7 @@ describe('useDeleteFileAttachment', () => { }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spyOnDeleteFileAttachments).toHaveBeenCalledWith({ caseId: basicCaseId, @@ -54,7 +55,7 @@ describe('useDeleteFileAttachment', () => { }); it('refreshes the case page view', async () => { - const { waitForNextUpdate, result } = renderHook(() => useDeleteFileAttachment(), { + const { result } = renderHook(() => useDeleteFileAttachment(), { wrapper: appMockRender.AppWrapper, }); @@ -65,13 +66,13 @@ describe('useDeleteFileAttachment', () => { }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(useRefreshCaseViewPage()).toBeCalled(); }); it('shows a success toaster correctly', async () => { - const { waitForNextUpdate, result } = renderHook(() => useDeleteFileAttachment(), { + const { result } = renderHook(() => useDeleteFileAttachment(), { wrapper: appMockRender.AppWrapper, }); @@ -82,7 +83,7 @@ describe('useDeleteFileAttachment', () => { }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(addSuccess).toHaveBeenCalledWith({ title: 'File deleted successfully', @@ -94,7 +95,7 @@ describe('useDeleteFileAttachment', () => { const spyOnDeleteFileAttachments = jest.spyOn(api, 'deleteFileAttachments'); spyOnDeleteFileAttachments.mockRejectedValue(new Error('Error')); - const { waitForNextUpdate, result } = renderHook(() => useDeleteFileAttachment(), { + const { result } = renderHook(() => useDeleteFileAttachment(), { wrapper: appMockRender.AppWrapper, }); @@ -105,7 +106,7 @@ describe('useDeleteFileAttachment', () => { }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(spyOnDeleteFileAttachments).toBeCalledWith({ caseId: basicCaseId, diff --git a/x-pack/plugins/cases/public/containers/use_find_case_user_actions.test.tsx b/x-pack/plugins/cases/public/containers/use_find_case_user_actions.test.tsx index 67110c8ebc0b9..6690a7f0be2f0 100644 --- a/x-pack/plugins/cases/public/containers/use_find_case_user_actions.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_find_case_user_actions.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useFindCaseUserActions } from './use_find_case_user_actions'; import type { CaseUserActionTypeWithAll } from '../../common/ui/types'; import { basicCase, findCaseUserActionsResponse } from './mock'; @@ -43,12 +44,11 @@ describe('UseFindCaseUserActions', () => { }); it('returns proper state on findCaseUserActions', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useFindCaseUserActions(basicCase.id, params, isEnabled), - { wrapper: appMockRender.AppWrapper } - ); + const { result } = renderHook(() => useFindCaseUserActions(basicCase.id, params, isEnabled), { + wrapper: appMockRender.AppWrapper, + }); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual( expect.objectContaining({ @@ -69,7 +69,7 @@ describe('UseFindCaseUserActions', () => { it('calls the API with correct parameters', async () => { const spy = jest.spyOn(api, 'findCaseUserActions').mockRejectedValue(initialData); - const { waitForNextUpdate } = renderHook( + renderHook( () => useFindCaseUserActions( basicCase.id, @@ -84,7 +84,7 @@ describe('UseFindCaseUserActions', () => { { wrapper: appMockRender.AppWrapper } ); - await waitForNextUpdate(); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith( basicCase.id, @@ -120,14 +120,11 @@ describe('UseFindCaseUserActions', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addError }); - const { waitForNextUpdate } = renderHook( - () => useFindCaseUserActions(basicCase.id, params, isEnabled), - { - wrapper: appMockRender.AppWrapper, - } - ); + renderHook(() => useFindCaseUserActions(basicCase.id, params, isEnabled), { + wrapper: appMockRender.AppWrapper, + }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith( basicCase.id, diff --git a/x-pack/plugins/cases/public/containers/use_get_action_license.test.tsx b/x-pack/plugins/cases/public/containers/use_get_action_license.test.tsx index 43e445fa39aab..d708164ac1171 100644 --- a/x-pack/plugins/cases/public/containers/use_get_action_license.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_action_license.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import * as api from './api'; import { useGetActionLicense } from './use_get_action_license'; import type { AppMockRenderer } from '../common/mock'; @@ -25,11 +26,11 @@ describe('useGetActionLicense', () => { it('calls getActionLicense with correct arguments', async () => { const spyOnGetActionLicense = jest.spyOn(api, 'getActionLicense'); - const { waitForNextUpdate } = renderHook(() => useGetActionLicense(), { + renderHook(() => useGetActionLicense(), { wrapper: appMockRenderer.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spyOnGetActionLicense).toBeCalledWith(abortCtrl.signal); }); @@ -42,10 +43,10 @@ describe('useGetActionLicense', () => { throw new Error('Something went wrong'); }); - const { waitForNextUpdate } = renderHook(() => useGetActionLicense(), { + renderHook(() => useGetActionLicense(), { wrapper: appMockRenderer.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addError).toHaveBeenCalled(); }); diff --git a/x-pack/plugins/cases/public/containers/use_get_case.test.tsx b/x-pack/plugins/cases/public/containers/use_get_case.test.tsx index 1187c7de07d28..074a9e8b61b69 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case.test.tsx @@ -32,8 +32,8 @@ const wrapper: FC> = ({ children }) => { describe.skip('Use get case hook', () => { it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'resolveCase'); - const { waitForNextUpdate } = renderHook(() => useGetCase('case-1'), { wrapper }); - await waitForNextUpdate(); + renderHook(() => useGetCase('case-1'), { wrapper }); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith({ caseId: 'case-1', includeComments: true, @@ -45,8 +45,8 @@ describe.skip('Use get case hook', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addError }); const spy = jest.spyOn(api, 'resolveCase').mockRejectedValue(new Error("C'est la vie")); - const { waitForNextUpdate } = renderHook(() => useGetCase('case-1'), { wrapper }); - await waitForNextUpdate(); + renderHook(() => useGetCase('case-1'), { wrapper }); + await waitFor(() => null); await waitFor(() => { expect(spy).toHaveBeenCalledWith({ caseId: 'case-1', diff --git a/x-pack/plugins/cases/public/containers/use_get_case_file_stats.test.tsx b/x-pack/plugins/cases/public/containers/use_get_case_file_stats.test.tsx index e7c55cd1fc0c5..3b1c91b810767 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_file_stats.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_file_stats.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { basicCase } from './mock'; @@ -37,10 +38,10 @@ describe('useGetCaseFileStats', () => { }); it('calls filesClient.list with correct arguments', async () => { - const { waitForNextUpdate } = renderHook(() => useGetCaseFileStats(hookParams), { + renderHook(() => useGetCaseFileStats(hookParams), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(appMockRender.getFilesClient().list).toHaveBeenCalledWith(expectedCallParams); }); @@ -53,10 +54,10 @@ describe('useGetCaseFileStats', () => { throw new Error('Something went wrong'); }); - const { waitForNextUpdate } = renderHook(() => useGetCaseFileStats(hookParams), { + renderHook(() => useGetCaseFileStats(hookParams), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(appMockRender.getFilesClient().list).toHaveBeenCalledWith(expectedCallParams); expect(addError).toHaveBeenCalled(); diff --git a/x-pack/plugins/cases/public/containers/use_get_case_files.test.tsx b/x-pack/plugins/cases/public/containers/use_get_case_files.test.tsx index 2be8dd6052408..2d3aa26ba6565 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_files.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_files.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { basicCase } from './mock'; @@ -48,21 +49,21 @@ describe('useGetCaseFiles', () => { throw new Error('Something went wrong'); }); - const { waitForNextUpdate } = renderHook(() => useGetCaseFiles(hookParams), { + renderHook(() => useGetCaseFiles(hookParams), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(appMockRender.getFilesClient().list).toBeCalledWith(expectedCallParams); expect(addError).toHaveBeenCalled(); }); it('calls filesClient.list with correct arguments', async () => { - const { waitForNextUpdate } = renderHook(() => useGetCaseFiles(hookParams), { + renderHook(() => useGetCaseFiles(hookParams), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(appMockRender.getFilesClient().list).toBeCalledWith(expectedCallParams); }); diff --git a/x-pack/plugins/cases/public/containers/use_get_case_metrics.test.tsx b/x-pack/plugins/cases/public/containers/use_get_case_metrics.test.tsx index 3cda384f1c63c..9ace26d964017 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_metrics.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_metrics.test.tsx @@ -8,6 +8,7 @@ import type { FC, PropsWithChildren } from 'react'; import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import type { SingleCaseMetricsFeature } from '../../common/ui'; import { useGetCaseMetrics } from './use_get_case_metrics'; import { basicCase } from './mock'; @@ -34,11 +35,11 @@ describe('useGetCaseMetrics', () => { it('calls getSingleCaseMetrics with correct arguments', async () => { const spyOnGetCaseMetrics = jest.spyOn(api, 'getSingleCaseMetrics'); - const { waitForNextUpdate } = renderHook(() => useGetCaseMetrics(basicCase.id, features), { + renderHook(() => useGetCaseMetrics(basicCase.id, features), { wrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spyOnGetCaseMetrics).toBeCalledWith(basicCase.id, features, abortCtrl.signal); }); @@ -51,11 +52,11 @@ describe('useGetCaseMetrics', () => { throw new Error('Something went wrong'); }); - const { waitForNextUpdate } = renderHook(() => useGetCaseMetrics(basicCase.id, features), { + renderHook(() => useGetCaseMetrics(basicCase.id, features), { wrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spyOnGetCaseMetrics).toBeCalledWith(basicCase.id, features, abortCtrl.signal); expect(addError).toHaveBeenCalled(); diff --git a/x-pack/plugins/cases/public/containers/use_get_case_user_actions_stats.test.tsx b/x-pack/plugins/cases/public/containers/use_get_case_user_actions_stats.test.tsx index b81f9d1448aa2..9a2b14527ff87 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_user_actions_stats.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_user_actions_stats.test.tsx @@ -6,6 +6,8 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; + import { useToasts } from '../common/lib/kibana'; import type { AppMockRenderer } from '../common/mock'; import { createAppMockRenderer } from '../common/mock'; @@ -31,12 +33,11 @@ describe('useGetCaseUserActionsStats', () => { }); it('returns proper state on getCaseUserActionsStats', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useGetCaseUserActionsStats(basicCase.id), - { wrapper: appMockRender.AppWrapper } - ); + const { result } = renderHook(() => useGetCaseUserActionsStats(basicCase.id), { + wrapper: appMockRender.AppWrapper, + }); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual( expect.objectContaining({ @@ -61,11 +62,11 @@ describe('useGetCaseUserActionsStats', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addError }); - const { waitForNextUpdate } = renderHook(() => useGetCaseUserActionsStats(basicCase.id), { + renderHook(() => useGetCaseUserActionsStats(basicCase.id), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith(basicCase.id, expect.any(AbortSignal)); expect(addError).toHaveBeenCalled(); @@ -74,11 +75,11 @@ describe('useGetCaseUserActionsStats', () => { it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'getCaseUserActionsStats'); - const { waitForNextUpdate } = renderHook(() => useGetCaseUserActionsStats(basicCase.id), { + renderHook(() => useGetCaseUserActionsStats(basicCase.id), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith(basicCase.id, expect.any(AbortSignal)); }); diff --git a/x-pack/plugins/cases/public/containers/use_get_case_users.test.tsx b/x-pack/plugins/cases/public/containers/use_get_case_users.test.tsx index e35e41c3d49f6..39d8bb21207ba 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_users.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_users.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useGetCaseUsers } from './use_get_case_users'; import * as api from './api'; import { useToasts } from '../common/lib/kibana'; @@ -26,11 +27,11 @@ describe('useGetCaseUsers', () => { it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'getCaseUsers'); - const { waitForNextUpdate } = renderHook(() => useGetCaseUsers('case-1'), { + renderHook(() => useGetCaseUsers('case-1'), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith({ caseId: 'case-1', signal: expect.any(AbortSignal) }); }); @@ -40,11 +41,11 @@ describe('useGetCaseUsers', () => { (useToasts as jest.Mock).mockReturnValue({ addError }); const spy = jest.spyOn(api, 'getCaseUsers').mockRejectedValue(new Error("C'est la vie")); - const { waitForNextUpdate } = renderHook(() => useGetCaseUsers('case-1'), { + renderHook(() => useGetCaseUsers('case-1'), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith({ caseId: 'case-1', signal: expect.any(AbortSignal) }); expect(addError).toHaveBeenCalled(); diff --git a/x-pack/plugins/cases/public/containers/use_get_cases_metrics.test.tsx b/x-pack/plugins/cases/public/containers/use_get_cases_metrics.test.tsx index 619e1ea4e1ebf..553983f0bebb2 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases_metrics.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases_metrics.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import * as api from '../api'; import type { AppMockRenderer } from '../common/mock'; import { createAppMockRenderer } from '../common/mock'; @@ -33,11 +34,11 @@ describe('useGetCasesMetrics', () => { it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'getCasesMetrics'); - const { waitForNextUpdate } = renderHook(() => useGetCasesMetrics(), { + renderHook(() => useGetCasesMetrics(), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith({ http: expect.anything(), @@ -51,11 +52,11 @@ describe('useGetCasesMetrics', () => { .spyOn(api, 'getCasesMetrics') .mockRejectedValue(new Error('useGetCasesMetrics: Test error')); - const { waitForNextUpdate } = renderHook(() => useGetCasesMetrics(), { + renderHook(() => useGetCasesMetrics(), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addError).toHaveBeenCalled(); }); diff --git a/x-pack/plugins/cases/public/containers/use_get_cases_status.test.tsx b/x-pack/plugins/cases/public/containers/use_get_cases_status.test.tsx index fed7159ac15e3..d2337b9728904 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases_status.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases_status.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useGetCasesStatus } from './use_get_cases_status'; import * as api from '../api'; import type { AppMockRenderer } from '../common/mock'; @@ -32,11 +33,11 @@ describe('useGetCasesMetrics', () => { it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'getCasesStatus'); - const { waitForNextUpdate } = renderHook(() => useGetCasesStatus(), { + renderHook(() => useGetCasesStatus(), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith({ http: expect.anything(), @@ -50,11 +51,11 @@ describe('useGetCasesMetrics', () => { .spyOn(api, 'getCasesStatus') .mockRejectedValue(new Error('useGetCasesMetrics: Test error')); - const { waitForNextUpdate } = renderHook(() => useGetCasesStatus(), { + renderHook(() => useGetCasesStatus(), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addError).toHaveBeenCalled(); }); diff --git a/x-pack/plugins/cases/public/containers/use_get_categories.test.tsx b/x-pack/plugins/cases/public/containers/use_get_categories.test.tsx index d80f03822ec7a..702715190876d 100644 --- a/x-pack/plugins/cases/public/containers/use_get_categories.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_categories.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import * as api from './api'; import { TestProviders } from '../common/mock'; import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; @@ -24,13 +25,11 @@ describe('useGetCategories', () => { it('calls getCategories api', async () => { const spyOnGetCategories = jest.spyOn(api, 'getCategories'); - const { waitForNextUpdate } = renderHook(() => useGetCategories(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( - {children} - ), + renderHook(() => useGetCategories(), { + wrapper: ({ children }) => {children}, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spyOnGetCategories).toBeCalledWith({ signal: abortCtrl.signal, @@ -47,13 +46,11 @@ describe('useGetCategories', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addError }); - const { waitForNextUpdate } = renderHook(() => useGetCategories(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( - {children} - ), + renderHook(() => useGetCategories(), { + wrapper: ({ children }) => {children}, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addError).toBeCalled(); }); diff --git a/x-pack/plugins/cases/public/containers/use_get_feature_ids.test.tsx b/x-pack/plugins/cases/public/containers/use_get_feature_ids.test.tsx index 9446007e367d5..398542a2647fc 100644 --- a/x-pack/plugins/cases/public/containers/use_get_feature_ids.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_feature_ids.test.tsx @@ -32,11 +32,11 @@ describe('useGetFeaturesIds', () => { it('returns the features ids correctly', async () => { const spy = jest.spyOn(api, 'getFeatureIds').mockRejectedValue([]); - const { waitForNextUpdate } = renderHook(() => useGetFeatureIds(['alert-id-1'], true), { + renderHook(() => useGetFeatureIds(['alert-id-1'], true), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); await waitFor(() => { expect(spy).toHaveBeenCalledWith({ @@ -67,11 +67,11 @@ describe('useGetFeaturesIds', () => { .spyOn(api, 'getFeatureIds') .mockRejectedValue(new Error('Something went wrong')); - const { waitForNextUpdate } = renderHook(() => useGetFeatureIds(['alert-id-1'], true), { + renderHook(() => useGetFeatureIds(['alert-id-1'], true), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); await waitFor(() => { expect(spy).toHaveBeenCalledWith({ diff --git a/x-pack/plugins/cases/public/containers/use_get_tags.test.tsx b/x-pack/plugins/cases/public/containers/use_get_tags.test.tsx index a19074ff279ee..60205588e807d 100644 --- a/x-pack/plugins/cases/public/containers/use_get_tags.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_tags.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import * as api from './api'; import { TestProviders } from '../common/mock'; import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; @@ -24,12 +25,10 @@ describe('useGetTags', () => { it('calls getTags api', async () => { const spyOnGetTags = jest.spyOn(api, 'getTags'); - const { waitForNextUpdate } = renderHook(() => useGetTags(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( - {children} - ), + renderHook(() => useGetTags(), { + wrapper: ({ children }) => {children}, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spyOnGetTags).toBeCalledWith({ owner: [SECURITY_SOLUTION_OWNER], signal: abortCtrl.signal, @@ -43,12 +42,10 @@ describe('useGetTags', () => { spyOnGetTags.mockImplementation(() => { throw new Error('Something went wrong'); }); - const { waitForNextUpdate } = renderHook(() => useGetTags(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( - {children} - ), + renderHook(() => useGetTags(), { + wrapper: ({ children }) => {children}, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addError).toBeCalled(); }); }); diff --git a/x-pack/plugins/cases/public/containers/use_infinite_find_case_user_actions.test.tsx b/x-pack/plugins/cases/public/containers/use_infinite_find_case_user_actions.test.tsx index b3df805033ba8..a6dff220fa1eb 100644 --- a/x-pack/plugins/cases/public/containers/use_infinite_find_case_user_actions.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_infinite_find_case_user_actions.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useInfiniteFindCaseUserActions } from './use_infinite_find_case_user_actions'; import type { CaseUserActionTypeWithAll } from '../../common/ui/types'; @@ -42,12 +43,12 @@ describe('UseInfiniteFindCaseUserActions', () => { }); it('returns proper state on findCaseUserActions', async () => { - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => useInfiniteFindCaseUserActions(basicCase.id, params, isEnabled), { wrapper: appMockRender.AppWrapper } ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual( expect.objectContaining({ @@ -73,7 +74,7 @@ describe('UseInfiniteFindCaseUserActions', () => { it('calls the API with correct parameters', async () => { const spy = jest.spyOn(api, 'findCaseUserActions').mockRejectedValue(initialData); - const { waitForNextUpdate } = renderHook( + renderHook( () => useInfiniteFindCaseUserActions( basicCase.id, @@ -87,7 +88,7 @@ describe('UseInfiniteFindCaseUserActions', () => { { wrapper: appMockRender.AppWrapper } ); - await waitForNextUpdate(); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith( basicCase.id, @@ -122,14 +123,11 @@ describe('UseInfiniteFindCaseUserActions', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addError }); - const { waitForNextUpdate } = renderHook( - () => useInfiniteFindCaseUserActions(basicCase.id, params, isEnabled), - { - wrapper: appMockRender.AppWrapper, - } - ); + renderHook(() => useInfiniteFindCaseUserActions(basicCase.id, params, isEnabled), { + wrapper: appMockRender.AppWrapper, + }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith( basicCase.id, @@ -143,7 +141,7 @@ describe('UseInfiniteFindCaseUserActions', () => { it('fetches next page with correct params', async () => { const spy = jest.spyOn(api, 'findCaseUserActions'); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useInfiniteFindCaseUserActions(basicCase.id, params, isEnabled), { wrapper: appMockRender.AppWrapper } ); diff --git a/x-pack/plugins/cases/public/containers/use_messages_storage.test.tsx b/x-pack/plugins/cases/public/containers/use_messages_storage.test.tsx index ef4a164e759ba..2e0f258b81020 100644 --- a/x-pack/plugins/cases/public/containers/use_messages_storage.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_messages_storage.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import type { UseMessagesStorage } from './use_messages_storage'; import { useMessagesStorage } from './use_messages_storage'; @@ -19,10 +20,8 @@ describe('useMessagesStorage', () => { it('should return an empty array when there is no messages', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useMessagesStorage() - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); const { getMessages } = result.current; expect(getMessages('case')).toEqual([]); }); @@ -30,10 +29,8 @@ describe('useMessagesStorage', () => { it('should add a message', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useMessagesStorage() - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); const { getMessages, addMessage } = result.current; addMessage('case', 'id-1'); expect(getMessages('case')).toEqual(['id-1']); @@ -42,10 +39,8 @@ describe('useMessagesStorage', () => { it('should add multiple messages', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useMessagesStorage() - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); const { getMessages, addMessage } = result.current; addMessage('case', 'id-1'); addMessage('case', 'id-2'); @@ -55,10 +50,8 @@ describe('useMessagesStorage', () => { it('should remove a message', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useMessagesStorage() - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); const { getMessages, addMessage, removeMessage } = result.current; addMessage('case', 'id-1'); addMessage('case', 'id-2'); @@ -69,10 +62,8 @@ describe('useMessagesStorage', () => { it('should return presence of a message', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useMessagesStorage() - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); const { hasMessage, addMessage, removeMessage } = result.current; addMessage('case', 'id-1'); addMessage('case', 'id-2'); @@ -84,10 +75,8 @@ describe('useMessagesStorage', () => { it('should clear all messages', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useMessagesStorage() - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); const { getMessages, addMessage, clearAllMessages } = result.current; addMessage('case', 'id-1'); addMessage('case', 'id-2'); diff --git a/x-pack/plugins/cases/public/containers/use_post_case.test.tsx b/x-pack/plugins/cases/public/containers/use_post_case.test.tsx index 58a878b32e578..c171b36a531f4 100644 --- a/x-pack/plugins/cases/public/containers/use_post_case.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_post_case.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import * as api from './api'; import { ConnectorTypes } from '../../common/types/domain'; import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; @@ -49,7 +50,7 @@ describe('usePostCase', () => { it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'postCase'); - const { waitForNextUpdate, result } = renderHook(() => usePostCase(), { + const { result } = renderHook(() => usePostCase(), { wrapper: appMockRender.AppWrapper, }); @@ -57,14 +58,14 @@ describe('usePostCase', () => { result.current.mutate({ request: samplePost }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith({ newCase: samplePost }); }); it('invalidates the queries correctly', async () => { const queryClientSpy = jest.spyOn(appMockRender.queryClient, 'invalidateQueries'); - const { waitForNextUpdate, result } = renderHook(() => usePostCase(), { + const { result } = renderHook(() => usePostCase(), { wrapper: appMockRender.AppWrapper, }); @@ -72,7 +73,7 @@ describe('usePostCase', () => { result.current.mutate({ request: samplePost }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.casesList()); expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags()); @@ -80,7 +81,7 @@ describe('usePostCase', () => { }); it('does not show a success toaster', async () => { - const { waitForNextUpdate, result } = renderHook(() => usePostCase(), { + const { result } = renderHook(() => usePostCase(), { wrapper: appMockRender.AppWrapper, }); @@ -88,7 +89,7 @@ describe('usePostCase', () => { result.current.mutate({ request: samplePost }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addSuccess).not.toHaveBeenCalled(); }); @@ -96,7 +97,7 @@ describe('usePostCase', () => { it('shows a toast error when the api return an error', async () => { jest.spyOn(api, 'postCase').mockRejectedValue(new Error('usePostCase: Test error')); - const { waitForNextUpdate, result } = renderHook(() => usePostCase(), { + const { result } = renderHook(() => usePostCase(), { wrapper: appMockRender.AppWrapper, }); @@ -104,7 +105,7 @@ describe('usePostCase', () => { result.current.mutate({ request: samplePost }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addError).toHaveBeenCalled(); }); diff --git a/x-pack/plugins/cases/public/containers/use_post_push_to_service.test.tsx b/x-pack/plugins/cases/public/containers/use_post_push_to_service.test.tsx index 1d802b3737c96..f255aa3835b5f 100644 --- a/x-pack/plugins/cases/public/containers/use_post_push_to_service.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_post_push_to_service.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useToasts } from '../common/lib/kibana'; import { usePostPushToService } from './use_post_push_to_service'; import { pushedCase } from './mock'; @@ -42,7 +43,7 @@ describe('usePostPushToService', () => { it('refresh the case after pushing', async () => { const queryClientSpy = jest.spyOn(appMockRender.queryClient, 'invalidateQueries'); - const { waitForNextUpdate, result } = renderHook(() => usePostPushToService(), { + const { result } = renderHook(() => usePostPushToService(), { wrapper: appMockRender.AppWrapper, }); @@ -50,7 +51,7 @@ describe('usePostPushToService', () => { result.current.mutate({ caseId, connector }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.caseView()); expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags()); @@ -58,7 +59,7 @@ describe('usePostPushToService', () => { it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'pushCase'); - const { waitForNextUpdate, result } = renderHook(() => usePostPushToService(), { + const { result } = renderHook(() => usePostPushToService(), { wrapper: appMockRender.AppWrapper, }); @@ -66,13 +67,13 @@ describe('usePostPushToService', () => { result.current.mutate({ caseId, connector }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith({ caseId, connectorId: connector.id }); }); it('shows a success toaster', async () => { - const { waitForNextUpdate, result } = renderHook(() => usePostPushToService(), { + const { result } = renderHook(() => usePostPushToService(), { wrapper: appMockRender.AppWrapper, }); @@ -80,7 +81,7 @@ describe('usePostPushToService', () => { result.current.mutate({ caseId, connector }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addSuccess).toHaveBeenCalledWith({ title: 'Successfully sent to My connector', @@ -91,7 +92,7 @@ describe('usePostPushToService', () => { it('shows a toast error when the api return an error', async () => { jest.spyOn(api, 'pushCase').mockRejectedValue(new Error('usePostPushToService: Test error')); - const { waitForNextUpdate, result } = renderHook(() => usePostPushToService(), { + const { result } = renderHook(() => usePostPushToService(), { wrapper: appMockRender.AppWrapper, }); @@ -99,7 +100,7 @@ describe('usePostPushToService', () => { result.current.mutate({ caseId, connector }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addError).toHaveBeenCalled(); }); diff --git a/x-pack/plugins/cases/public/containers/use_replace_custom_field.test.tsx b/x-pack/plugins/cases/public/containers/use_replace_custom_field.test.tsx index 366d946af1d90..0e3cc77a7f7c9 100644 --- a/x-pack/plugins/cases/public/containers/use_replace_custom_field.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_replace_custom_field.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { basicCase } from './mock'; import * as api from './api'; import type { AppMockRenderer } from '../common/mock'; @@ -39,7 +40,7 @@ describe('useReplaceCustomField', () => { it('replace a customField and refresh the case page', async () => { const queryClientSpy = jest.spyOn(appMockRender.queryClient, 'invalidateQueries'); - const { waitForNextUpdate, result } = renderHook(() => useReplaceCustomField(), { + const { result } = renderHook(() => useReplaceCustomField(), { wrapper: appMockRender.AppWrapper, }); @@ -47,7 +48,7 @@ describe('useReplaceCustomField', () => { result.current.mutate(sampleData); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.caseView()); expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags()); @@ -55,7 +56,7 @@ describe('useReplaceCustomField', () => { it('calls the api when invoked with the correct parameters', async () => { const patchCustomFieldSpy = jest.spyOn(api, 'replaceCustomField'); - const { waitForNextUpdate, result } = renderHook(() => useReplaceCustomField(), { + const { result } = renderHook(() => useReplaceCustomField(), { wrapper: appMockRender.AppWrapper, }); @@ -63,7 +64,7 @@ describe('useReplaceCustomField', () => { result.current.mutate(sampleData); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(patchCustomFieldSpy).toHaveBeenCalledWith({ caseId: sampleData.caseId, @@ -83,7 +84,7 @@ describe('useReplaceCustomField', () => { caseVersion: basicCase.version, }; const patchCustomFieldSpy = jest.spyOn(api, 'replaceCustomField'); - const { waitForNextUpdate, result } = renderHook(() => useReplaceCustomField(), { + const { result } = renderHook(() => useReplaceCustomField(), { wrapper: appMockRender.AppWrapper, }); @@ -91,7 +92,7 @@ describe('useReplaceCustomField', () => { result.current.mutate(newData); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(patchCustomFieldSpy).toHaveBeenCalledWith({ caseId: newData.caseId, @@ -111,7 +112,7 @@ describe('useReplaceCustomField', () => { caseVersion: basicCase.version, }; const patchCustomFieldSpy = jest.spyOn(api, 'replaceCustomField'); - const { waitForNextUpdate, result } = renderHook(() => useReplaceCustomField(), { + const { result } = renderHook(() => useReplaceCustomField(), { wrapper: appMockRender.AppWrapper, }); @@ -119,7 +120,7 @@ describe('useReplaceCustomField', () => { result.current.mutate(newData); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(patchCustomFieldSpy).toHaveBeenCalledWith({ caseId: newData.caseId, @@ -136,7 +137,7 @@ describe('useReplaceCustomField', () => { .spyOn(api, 'replaceCustomField') .mockRejectedValue(new Error('useUpdateComment: Test error')); - const { waitForNextUpdate, result } = renderHook(() => useReplaceCustomField(), { + const { result } = renderHook(() => useReplaceCustomField(), { wrapper: appMockRender.AppWrapper, }); @@ -144,7 +145,7 @@ describe('useReplaceCustomField', () => { result.current.mutate(sampleData); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addError).toHaveBeenCalled(); }); diff --git a/x-pack/plugins/cases/public/containers/use_update_case.test.tsx b/x-pack/plugins/cases/public/containers/use_update_case.test.tsx index f8d4ff82078c1..7f41290162def 100644 --- a/x-pack/plugins/cases/public/containers/use_update_case.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_update_case.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useUpdateCase } from './use_update_case'; import { basicCase } from './mock'; import * as api from './api'; @@ -41,7 +42,7 @@ describe('useUpdateCase', () => { it('patch case and refresh the case page', async () => { const queryClientSpy = jest.spyOn(appMockRender.queryClient, 'invalidateQueries'); - const { waitForNextUpdate, result } = renderHook(() => useUpdateCase(), { + const { result } = renderHook(() => useUpdateCase(), { wrapper: appMockRender.AppWrapper, }); @@ -49,7 +50,7 @@ describe('useUpdateCase', () => { result.current.mutate(sampleUpdate); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.caseView()); expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags()); @@ -57,7 +58,7 @@ describe('useUpdateCase', () => { it('calls the api when invoked with the correct parameters', async () => { const patchCaseSpy = jest.spyOn(api, 'patchCase'); - const { waitForNextUpdate, result } = renderHook(() => useUpdateCase(), { + const { result } = renderHook(() => useUpdateCase(), { wrapper: appMockRender.AppWrapper, }); @@ -65,7 +66,7 @@ describe('useUpdateCase', () => { result.current.mutate(sampleUpdate); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(patchCaseSpy).toHaveBeenCalledWith({ caseId: basicCase.id, @@ -75,7 +76,7 @@ describe('useUpdateCase', () => { }); it('shows a success toaster', async () => { - const { waitForNextUpdate, result } = renderHook(() => useUpdateCase(), { + const { result } = renderHook(() => useUpdateCase(), { wrapper: appMockRender.AppWrapper, }); @@ -83,7 +84,7 @@ describe('useUpdateCase', () => { result.current.mutate(sampleUpdate); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addSuccess).toHaveBeenCalledWith({ title: 'Updated "Another horrible breach!!"', @@ -94,7 +95,7 @@ describe('useUpdateCase', () => { it('shows a toast error when the api return an error', async () => { jest.spyOn(api, 'patchCase').mockRejectedValue(new Error('useUpdateCase: Test error')); - const { waitForNextUpdate, result } = renderHook(() => useUpdateCase(), { + const { result } = renderHook(() => useUpdateCase(), { wrapper: appMockRender.AppWrapper, }); @@ -102,7 +103,7 @@ describe('useUpdateCase', () => { result.current.mutate(sampleUpdate); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addError).toHaveBeenCalled(); }); diff --git a/x-pack/plugins/cases/public/containers/use_update_comment.test.tsx b/x-pack/plugins/cases/public/containers/use_update_comment.test.tsx index 59c06bd545c89..97ee969e82d08 100644 --- a/x-pack/plugins/cases/public/containers/use_update_comment.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_update_comment.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { basicCase } from './mock'; import * as api from './api'; import type { AppMockRenderer } from '../common/mock'; @@ -39,7 +40,7 @@ describe('useUpdateComment', () => { it('patch case and refresh the case page', async () => { const queryClientSpy = jest.spyOn(appMockRender.queryClient, 'invalidateQueries'); - const { waitForNextUpdate, result } = renderHook(() => useUpdateComment(), { + const { result } = renderHook(() => useUpdateComment(), { wrapper: appMockRender.AppWrapper, }); @@ -47,7 +48,7 @@ describe('useUpdateComment', () => { result.current.mutate(sampleUpdate); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.caseView()); expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags()); @@ -55,7 +56,7 @@ describe('useUpdateComment', () => { it('calls the api when invoked with the correct parameters', async () => { const patchCommentSpy = jest.spyOn(api, 'patchComment'); - const { waitForNextUpdate, result } = renderHook(() => useUpdateComment(), { + const { result } = renderHook(() => useUpdateComment(), { wrapper: appMockRender.AppWrapper, }); @@ -63,7 +64,7 @@ describe('useUpdateComment', () => { result.current.mutate(sampleUpdate); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(patchCommentSpy).toHaveBeenCalledWith({ ...sampleUpdate, @@ -74,7 +75,7 @@ describe('useUpdateComment', () => { it('shows a toast error when the api return an error', async () => { jest.spyOn(api, 'patchComment').mockRejectedValue(new Error('useUpdateComment: Test error')); - const { waitForNextUpdate, result } = renderHook(() => useUpdateComment(), { + const { result } = renderHook(() => useUpdateComment(), { wrapper: appMockRender.AppWrapper, }); @@ -82,7 +83,7 @@ describe('useUpdateComment', () => { result.current.mutate(sampleUpdate); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addError).toHaveBeenCalled(); }); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_change_csp_rule_state.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_change_csp_rule_state.test.tsx index 6c28df502e5fc..ce254e1efc19e 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_change_csp_rule_state.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_change_csp_rule_state.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ import React from 'react'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import type { RuleStateAttributes } from '@kbn/cloud-security-posture-common/schema/rules/v4'; @@ -87,7 +88,7 @@ describe('use_change_csp_rule_state', () => { const appMockRender = testWrapper(); const httpPostSpy = jest.spyOn(useKibana().services.http!, 'post'); - const { result, waitForNextUpdate } = await renderHook(() => useChangeCspRuleState(), { + const { result } = await renderHook(() => useChangeCspRuleState(), { wrapper: appMockRender.wrapper, }); @@ -107,7 +108,7 @@ describe('use_change_csp_rule_state', () => { result.current.mutate(mockRuleStateUpdateRequest); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(httpPostSpy).toHaveBeenCalledWith(CSP_BENCHMARK_RULES_BULK_ACTION_ROUTE_PATH, { version: '1', @@ -131,7 +132,7 @@ describe('use_change_csp_rule_state', () => { const queryClientGetSpy = jest.spyOn(appMockRender.queryClient, 'getQueryData'); const mockSetQueryDataSpy = jest.spyOn(appMockRender.queryClient, 'setQueryData'); - const { result, waitForNextUpdate } = await renderHook(() => useChangeCspRuleState(), { + const { result } = await renderHook(() => useChangeCspRuleState(), { wrapper: appMockRender.wrapper, }); @@ -151,7 +152,7 @@ describe('use_change_csp_rule_state', () => { result.current.mutate(mockRuleStateUpdateRequest); }); - await waitForNextUpdate(); + await waitFor(() => null); const expectedMutatedRules = { ...initialRules, @@ -168,7 +169,7 @@ describe('use_change_csp_rule_state', () => { const appMockRender = testWrapper(); const mockInvalidateQueriesSpy = jest.spyOn(appMockRender.queryClient, 'invalidateQueries'); - const { result, waitForNextUpdate } = await renderHook(() => useChangeCspRuleState(), { + const { result } = await renderHook(() => useChangeCspRuleState(), { wrapper: appMockRender.wrapper, }); @@ -188,7 +189,7 @@ describe('use_change_csp_rule_state', () => { result.current.mutate(mockRuleStateUpdateRequest); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(mockInvalidateQueriesSpy).toHaveBeenCalledWith(BENCHMARK_INTEGRATION_QUERY_KEY_V2); expect(mockInvalidateQueriesSpy).toHaveBeenCalledWith(CSPM_STATS_QUERY_KEY); @@ -200,7 +201,7 @@ describe('use_change_csp_rule_state', () => { const appMockRender = testWrapper(); const mockSetQueryDataSpy = jest.spyOn(appMockRender.queryClient, 'setQueryData'); - const { result, waitForNextUpdate } = await renderHook(() => useChangeCspRuleState(), { + const { result } = await renderHook(() => useChangeCspRuleState(), { wrapper: appMockRender.wrapper, }); @@ -221,7 +222,7 @@ describe('use_change_csp_rule_state', () => { result.current.mutate(mockRuleStateUpdateRequest); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(mockSetQueryDataSpy).toHaveBeenCalled(); expect(mockSetQueryDataSpy).toHaveReturnedWith(initialRules); diff --git a/x-pack/plugins/fields_metadata/public/hooks/use_fields_metadata/use_fields_metadata.test.ts b/x-pack/plugins/fields_metadata/public/hooks/use_fields_metadata/use_fields_metadata.test.ts index eaae7c5542c0b..7b6f40be3371e 100644 --- a/x-pack/plugins/fields_metadata/public/hooks/use_fields_metadata/use_fields_metadata.test.ts +++ b/x-pack/plugins/fields_metadata/public/hooks/use_fields_metadata/use_fields_metadata.test.ts @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { createUseFieldsMetadataHook, UseFieldsMetadataParams } from './use_fields_metadata'; import { FindFieldsMetadataResponsePayload } from '../../../common/latest'; @@ -46,12 +47,12 @@ describe('useFieldsMetadata', () => { it('should return the fieldsMetadata value from the API', async () => { fieldsMetadataClient.find.mockResolvedValue(mockedFieldsMetadataResponse); - const { result, waitForNextUpdate } = renderHook(() => useFieldsMetadata()); + const { result } = renderHook(() => useFieldsMetadata()); expect(result.current.loading).toBe(true); expect(result.current.fieldsMetadata).toEqual(undefined); - await waitForNextUpdate(); + await waitFor(() => null); const { fieldsMetadata, loading, error } = result.current; expect(fieldsMetadata).toEqual(fields); @@ -68,9 +69,9 @@ describe('useFieldsMetadata', () => { dataset: 'dataset_name', }; - const { waitForNextUpdate } = renderHook(() => useFieldsMetadata(params)); + renderHook(() => useFieldsMetadata(params)); - await waitForNextUpdate(); + await waitFor(() => null); expect(fieldsMetadataClient.find).toHaveBeenCalledWith(params); }); @@ -79,9 +80,9 @@ describe('useFieldsMetadata', () => { const error = new Error('Fetch fields metadata Failed'); fieldsMetadataClient.find.mockRejectedValueOnce(error); - const { result, waitForNextUpdate } = renderHook(() => useFieldsMetadata()); + const { result } = renderHook(() => useFieldsMetadata()); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.error?.message).toMatch(error.message); }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_apm_service_href.test.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_apm_service_href.test.ts index 4a2eaddbc45d9..467bff5ac5d4e 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_apm_service_href.test.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_apm_service_href.test.ts @@ -6,6 +6,8 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; + import type { DataStream } from '../types'; import * as useLocatorModule from '../../../hooks/use_locator'; @@ -29,9 +31,9 @@ describe('useApmServiceHref hook', () => { package: 'elastic_agent', } as DataStream; - const { result, waitForNextUpdate } = renderHook(() => useAPMServiceDetailHref(datastream)); + const { result } = renderHook(() => useAPMServiceDetailHref(datastream)); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toMatchObject({ isSuccessful: true, href: undefined }); expect(apmLocatorMock).not.toBeCalled(); @@ -83,9 +85,9 @@ describe('useApmServiceHref hook', () => { it.each(testCases)( 'it passes the correct params to apm locator for %s', async (datastream, locatorParams) => { - const { result, waitForNextUpdate } = renderHook(() => useAPMServiceDetailHref(datastream)); + const { result } = renderHook(() => useAPMServiceDetailHref(datastream)); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toMatchObject({ isSuccessful: true, href: '' }); expect(apmLocatorMock).toBeCalledWith(expect.objectContaining(locatorParams)); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/hooks.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/hooks.test.tsx index 85a241fe828c9..da7866d9e2d9b 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/hooks.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/hooks.test.tsx @@ -5,6 +5,8 @@ * 2.0. */ +import { waitFor } from '@testing-library/react'; + import { createFleetTestRendererMock } from '../../../../../../mock'; import type { MockedFleetStartServices } from '../../../../../../mock'; import { useLicense } from '../../../../../../hooks/use_license'; @@ -189,12 +191,10 @@ describe('useOutputOptions', () => { hasAtLeast: () => true, } as unknown as LicenseService); mockApiCallsWithOutputs(testRenderer.startServices.http); - const { result, waitForNextUpdate } = testRenderer.renderHook(() => - useOutputOptions({} as AgentPolicy) - ); + const { result } = testRenderer.renderHook(() => useOutputOptions({} as AgentPolicy)); expect(result.current.isLoading).toBeTruthy(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.dataOutputOptions).toMatchInlineSnapshot(` Array [ Object { @@ -317,12 +317,10 @@ describe('useOutputOptions', () => { hasAtLeast: () => false, } as unknown as LicenseService); mockApiCallsWithOutputs(testRenderer.startServices.http); - const { result, waitForNextUpdate } = testRenderer.renderHook(() => - useOutputOptions({} as AgentPolicy) - ); + const { result } = testRenderer.renderHook(() => useOutputOptions({} as AgentPolicy)); expect(result.current.isLoading).toBeTruthy(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.dataOutputOptions).toMatchInlineSnapshot(` Array [ Object { @@ -445,12 +443,10 @@ describe('useOutputOptions', () => { hasAtLeast: () => true, } as unknown as LicenseService); mockApiCallsWithLogstashOutputs(testRenderer.startServices.http); - const { result, waitForNextUpdate } = testRenderer.renderHook(() => - useOutputOptions({} as AgentPolicy) - ); + const { result } = testRenderer.renderHook(() => useOutputOptions({} as AgentPolicy)); expect(result.current.isLoading).toBeTruthy(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.dataOutputOptions).toMatchInlineSnapshot(` Array [ Object { @@ -497,7 +493,7 @@ describe('useOutputOptions', () => { hasAtLeast: () => true, } as unknown as LicenseService); mockApiCallsWithLogstashOutputs(testRenderer.startServices.http); - const { result, waitForNextUpdate } = testRenderer.renderHook(() => + const { result } = testRenderer.renderHook(() => useOutputOptions({ package_policies: [ { @@ -510,7 +506,7 @@ describe('useOutputOptions', () => { ); expect(result.current.isLoading).toBeTruthy(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.dataOutputOptions).toMatchInlineSnapshot(` Array [ Object { @@ -601,12 +597,10 @@ describe('useOutputOptions', () => { hasAtLeast: () => true, } as unknown as LicenseService); mockApiCallsWithRemoteESOutputs(testRenderer.startServices.http); - const { result, waitForNextUpdate } = testRenderer.renderHook(() => - useOutputOptions({} as AgentPolicy) - ); + const { result } = testRenderer.renderHook(() => useOutputOptions({} as AgentPolicy)); expect(result.current.isLoading).toBeTruthy(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.dataOutputOptions.length).toEqual(2); expect(result.current.dataOutputOptions[1].value).toEqual('remote1'); expect(result.current.monitoringOutputOptions.length).toEqual(2); @@ -619,12 +613,10 @@ describe('useOutputOptions', () => { hasAtLeast: () => true, } as unknown as LicenseService); mockApiCallsWithInternalOutputs(testRenderer.startServices.http); - const { result, waitForNextUpdate } = testRenderer.renderHook(() => - useOutputOptions({} as AgentPolicy) - ); + const { result } = testRenderer.renderHook(() => useOutputOptions({} as AgentPolicy)); expect(result.current.isLoading).toBeTruthy(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.dataOutputOptions).toMatchInlineSnapshot(` Array [ Object { @@ -670,12 +662,10 @@ describe('useFleetServerHostsOptions', () => { it('should not enable internal fleet server hosts', async () => { const testRenderer = createFleetTestRendererMock(); mockApiCallsWithInternalFleetServerHost(testRenderer.startServices.http); - const { result, waitForNextUpdate } = testRenderer.renderHook(() => - useFleetServerHostsOptions({} as AgentPolicy) - ); + const { result } = testRenderer.renderHook(() => useFleetServerHostsOptions({} as AgentPolicy)); expect(result.current.isLoading).toBeTruthy(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.fleetServerHostsOptions).toMatchInlineSnapshot(` Array [ Object { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts index 550a288dad371..616feb04408ee 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts @@ -195,7 +195,7 @@ describe('useSetupTechnology', () => { }); it('should fetch agentless policy if agentless feature is enabled and isServerless is true', async () => { - const { waitForNextUpdate } = renderHook(() => + renderHook(() => useSetupTechnology({ setNewAgentPolicy, newAgentPolicy: newAgentPolicyMock, @@ -205,7 +205,7 @@ describe('useSetupTechnology', () => { }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(sendGetOneAgentPolicy).toHaveBeenCalled(); }); @@ -253,7 +253,7 @@ describe('useSetupTechnology', () => { isCloudEnabled: true, }, }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useSetupTechnology({ setNewAgentPolicy, newAgentPolicy: newAgentPolicyMock, @@ -268,14 +268,13 @@ describe('useSetupTechnology', () => { act(() => { result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS); }); - - waitForNextUpdate(); - - expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENTLESS); - expect(setNewAgentPolicy).toHaveBeenCalledWith({ - name: 'Agentless policy for endpoint-1', - supports_agentless: true, - inactivity_timeout: 3600, + waitFor(() => { + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENTLESS); + expect(setNewAgentPolicy).toHaveBeenCalledWith({ + name: 'Agentless policy for endpoint-1', + supports_agentless: true, + inactivity_timeout: 3600, + }); }); }); @@ -344,7 +343,7 @@ describe('useSetupTechnology', () => { }, }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useSetupTechnology({ setNewAgentPolicy, newAgentPolicy: newAgentPolicyMock, @@ -360,7 +359,7 @@ describe('useSetupTechnology', () => { result.current.handleSetupTechnologyChange(SetupTechnology.AGENT_BASED); }); - waitForNextUpdate(); + waitFor(() => null); expect(setNewAgentPolicy).toHaveBeenCalledTimes(0); }); @@ -386,7 +385,7 @@ describe('useSetupTechnology', () => { }); it('should update agent policy and selected policy tab when setup technology is agentless', async () => { - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useSetupTechnology({ setNewAgentPolicy, newAgentPolicy: newAgentPolicyMock, @@ -396,7 +395,7 @@ describe('useSetupTechnology', () => { }) ); - await waitForNextUpdate(); + await waitFor(() => null); act(() => { result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS); @@ -407,7 +406,7 @@ describe('useSetupTechnology', () => { }); it('should update new agent policy and selected policy tab when setup technology is agent-based', async () => { - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useSetupTechnology({ setNewAgentPolicy, newAgentPolicy: newAgentPolicyMock, @@ -417,7 +416,7 @@ describe('useSetupTechnology', () => { }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); @@ -462,7 +461,7 @@ describe('useSetupTechnology', () => { }); it('should not update agent policy and selected policy tab when setup technology matches the current one ', async () => { - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useSetupTechnology({ setNewAgentPolicy, newAgentPolicy: newAgentPolicyMock, @@ -472,7 +471,7 @@ describe('useSetupTechnology', () => { }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); @@ -487,7 +486,7 @@ describe('useSetupTechnology', () => { }); it('should revert the agent policy name to the original value when switching from agentless back to agent-based', async () => { - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useSetupTechnology({ setNewAgentPolicy, newAgentPolicy: newAgentPolicyMock, @@ -497,7 +496,7 @@ describe('useSetupTechnology', () => { }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy.test.tsx index 67b8f35a22eb4..c55868a495f56 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy.test.tsx @@ -12,6 +12,7 @@ * 2.0. */ +import { waitFor } from '@testing-library/react'; import { omit } from 'lodash'; import { sendGetPackageInfoByKey, sendUpgradePackagePolicyDryRun } from '../../../../../../hooks'; @@ -274,22 +275,22 @@ jest.mock('../../../../../../hooks/use_request', () => ({ describe('usePackagePolicy', () => { it('should load the package policy if this is a not an upgrade', async () => { const renderer = createFleetTestRendererMock(); - const { result, waitForNextUpdate } = renderer.renderHook(() => + const { result } = renderer.renderHook(() => usePackagePolicyWithRelatedData('package-policy-1', {}) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.packagePolicy).toEqual(omit(mockPackagePolicy, 'id')); }); it('should load the package policy if this is an upgrade', async () => { const renderer = createFleetTestRendererMock(); - const { result, waitForNextUpdate } = renderer.renderHook(() => + const { result } = renderer.renderHook(() => usePackagePolicyWithRelatedData('package-policy-1', { forceUpgrade: true, }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.packagePolicy).toMatchInlineSnapshot(` Object { "description": "Nginx description", @@ -514,12 +515,12 @@ describe('usePackagePolicy', () => { isLoading: false, } as any); const renderer = createFleetTestRendererMock(); - const { result, waitForNextUpdate } = renderer.renderHook(() => + const { result } = renderer.renderHook(() => usePackagePolicyWithRelatedData('package-policy-2', { forceUpgrade: true, }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.packagePolicy).toMatchInlineSnapshot(` Object { "description": "Nginx description", diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_agent_soft_limit.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_agent_soft_limit.test.tsx index 4b9d908baa84d..38ab07031086f 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_agent_soft_limit.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_agent_soft_limit.test.tsx @@ -38,8 +38,8 @@ describe('useAgentSoftLimit', () => { total: 5, }, } as any); - const { result, waitForNextUpdate } = renderer.renderHook(() => useAgentSoftLimit()); - await waitForNextUpdate(); + const { result, waitFor } = renderer.renderHook(() => useAgentSoftLimit()); + await waitFor(() => null); expect(mockedSendGetAgents).toBeCalled(); expect(result.current.shouldDisplayAgentSoftLimit).toEqual(false); @@ -53,8 +53,8 @@ describe('useAgentSoftLimit', () => { total: 15, }, } as any); - const { result, waitForNextUpdate } = renderer.renderHook(() => useAgentSoftLimit()); - await waitForNextUpdate(); + const { result, waitFor } = renderer.renderHook(() => useAgentSoftLimit()); + await waitFor(() => null); expect(mockedSendGetAgents).toBeCalled(); expect(result.current.shouldDisplayAgentSoftLimit).toEqual(true); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_fetch_agents_data.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_fetch_agents_data.test.tsx index db4cff14e4804..f633602ce0592 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_fetch_agents_data.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_fetch_agents_data.test.tsx @@ -118,10 +118,8 @@ describe('useFetchAgentsData', () => { it('should fetch agents and agent policies data', async () => { const renderer = createFleetTestRendererMock(); - const { result, waitForNextUpdate } = renderer.renderHook(() => useFetchAgentsData()); - await act(async () => { - await waitForNextUpdate(); - }); + const { result, waitFor } = renderer.renderHook(() => useFetchAgentsData()); + await waitFor(() => null); expect(result?.current.selectedStatus).toEqual(['healthy', 'unhealthy', 'updating', 'offline']); expect(result?.current.allAgentPolicies).toEqual([ @@ -155,27 +153,28 @@ describe('useFetchAgentsData', () => { it('sync querystring kuery with current search', async () => { const renderer = createFleetTestRendererMock(); - const { result, waitForNextUpdate } = renderer.renderHook(() => useFetchAgentsData()); - await act(async () => { - await waitForNextUpdate(); - }); + const { result, waitFor } = renderer.renderHook(() => useFetchAgentsData()); + + await waitFor(() => null); expect(renderer.history.location.search).toEqual(''); // Set search await act(async () => { result.current.setSearch('active:true'); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(renderer.history.location.search).toEqual('?kuery=active%3Atrue'); // Clear search await act(async () => { result.current.setSearch(''); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(renderer.history.location.search).toEqual(''); }); }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy.test.tsx index 7372edf0ada2a..4f9aa30f1ba4f 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy.test.tsx @@ -46,8 +46,8 @@ describe('useFleetServerUnhealthy', () => { }, }); - const { result, waitForNextUpdate } = testRenderer.renderHook(() => useFleetServerUnhealthy()); - await waitForNextUpdate(); + const { result, waitFor } = testRenderer.renderHook(() => useFleetServerUnhealthy()); + await waitFor(() => null); expect(result.current.isLoading).toBeFalsy(); expect(result.current.isUnhealthy).toBeFalsy(); }); @@ -62,8 +62,8 @@ describe('useFleetServerUnhealthy', () => { }, }, }); - const { result, waitForNextUpdate } = testRenderer.renderHook(() => useFleetServerUnhealthy()); - await waitForNextUpdate(); + const { result, waitFor } = testRenderer.renderHook(() => useFleetServerUnhealthy()); + await waitFor(() => null); expect(result.current.isLoading).toBeFalsy(); expect(result.current.isUnhealthy).toBeTruthy(); }); @@ -73,8 +73,8 @@ describe('useFleetServerUnhealthy', () => { error: new Error('Invalid request'), data: null, }); - const { result, waitForNextUpdate } = testRenderer.renderHook(() => useFleetServerUnhealthy()); - await waitForNextUpdate(); + const { result, waitFor } = testRenderer.renderHook(() => useFleetServerUnhealthy()); + await waitFor(() => null); expect(result.current.isLoading).toBeFalsy(); expect(result.current.isUnhealthy).toBeFalsy(); expect(testRenderer.startServices.notifications.toasts.addError).toBeCalled(); diff --git a/x-pack/plugins/fleet/public/hooks/use_agent_version.test.ts b/x-pack/plugins/fleet/public/hooks/use_agent_version.test.ts index 34a7afe33baaa..5d3b51e9d6d41 100644 --- a/x-pack/plugins/fleet/public/hooks/use_agent_version.test.ts +++ b/x-pack/plugins/fleet/public/hooks/use_agent_version.test.ts @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useAgentVersion } from './use_agent_version'; import { useKibanaVersion } from './use_kibana_version'; @@ -28,11 +29,11 @@ describe('useAgentVersion', () => { data: { items: mockAvailableVersions }, }); - const { result, waitForNextUpdate } = renderHook(() => useAgentVersion()); + const { result } = renderHook(() => useAgentVersion()); expect(sendGetAgentsAvailableVersions).toHaveBeenCalled(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual(mockKibanaVersion); }); @@ -46,11 +47,11 @@ describe('useAgentVersion', () => { data: { items: mockAvailableVersions }, }); - const { result, waitForNextUpdate } = renderHook(() => useAgentVersion()); + const { result } = renderHook(() => useAgentVersion()); expect(sendGetAgentsAvailableVersions).toHaveBeenCalled(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual('8.8.2'); }); @@ -64,11 +65,11 @@ describe('useAgentVersion', () => { data: { items: mockAvailableVersions }, }); - const { result, waitForNextUpdate } = renderHook(() => useAgentVersion()); + const { result } = renderHook(() => useAgentVersion()); expect(sendGetAgentsAvailableVersions).toHaveBeenCalled(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual('8.9.2'); }); @@ -82,11 +83,11 @@ describe('useAgentVersion', () => { data: { items: mockAvailableVersions }, }); - const { result, waitForNextUpdate } = renderHook(() => useAgentVersion()); + const { result } = renderHook(() => useAgentVersion()); expect(sendGetAgentsAvailableVersions).toHaveBeenCalled(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual('8.8.2'); }); @@ -100,11 +101,11 @@ describe('useAgentVersion', () => { data: { items: mockAvailableVersions }, }); - const { result, waitForNextUpdate } = renderHook(() => useAgentVersion()); + const { result } = renderHook(() => useAgentVersion()); expect(sendGetAgentsAvailableVersions).toHaveBeenCalled(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual('8.9.2'); }); @@ -118,11 +119,11 @@ describe('useAgentVersion', () => { data: { items: mockAvailableVersions }, }); - const { result, waitForNextUpdate } = renderHook(() => useAgentVersion()); + const { result } = renderHook(() => useAgentVersion()); expect(sendGetAgentsAvailableVersions).toHaveBeenCalled(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual('8.11.0'); }); @@ -133,10 +134,10 @@ describe('useAgentVersion', () => { (useKibanaVersion as jest.Mock).mockReturnValue(mockKibanaVersion); (sendGetAgentsAvailableVersions as jest.Mock).mockRejectedValue(new Error('Fetching error')); - const { result, waitForNextUpdate } = renderHook(() => useAgentVersion()); + const { result } = renderHook(() => useAgentVersion()); expect(sendGetAgentsAvailableVersions).toHaveBeenCalled(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual(mockKibanaVersion); }); @@ -157,11 +158,11 @@ describe('useAgentVersion', () => { data: { items: mockAvailableVersions }, }); - const { result, waitForNextUpdate } = renderHook(() => useAgentVersion()); + const { result } = renderHook(() => useAgentVersion()); expect(sendGetAgentsAvailableVersions).toHaveBeenCalled(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual('8.11.1+build123456789'); }); diff --git a/x-pack/plugins/fleet/public/mock/create_test_renderer.tsx b/x-pack/plugins/fleet/public/mock/create_test_renderer.tsx index 3a69f5fdc52e3..363bda2968ced 100644 --- a/x-pack/plugins/fleet/public/mock/create_test_renderer.tsx +++ b/x-pack/plugins/fleet/public/mock/create_test_renderer.tsx @@ -9,7 +9,7 @@ import type { History } from 'history'; import { createMemoryHistory } from 'history'; import React, { memo } from 'react'; import type { RenderOptions, RenderResult } from '@testing-library/react'; -import { render as reactRender, act } from '@testing-library/react'; +import { render as reactRender, act, waitFor } from '@testing-library/react'; import { renderHook, type WrapperComponent } from '@testing-library/react-hooks'; import type { RenderHookResult } from '@testing-library/react-hooks'; import { Router } from '@kbn/shared-ux-router'; @@ -57,6 +57,7 @@ export interface TestRenderer { wrapper?: WrapperComponent ) => RenderHookResult; setHeaderActionMenu: Function; + waitFor: typeof waitFor; } const queryClient = new QueryClient(); @@ -125,6 +126,7 @@ export const createFleetTestRendererMock = (): TestRenderer => { wrapper, }); }, + waitFor, render: (ui, options) => { let renderResponse: RenderResult; act(() => { @@ -208,6 +210,7 @@ export const createIntegrationsTestRendererMock = (): TestRenderer => { wrapper, }); }, + waitFor, }; return testRendererMocks; diff --git a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts b/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts index 7cb2311c5e10a..9a7cc24910802 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts +++ b/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import * as api from '@kbn/securitysolution-list-api'; import { PersistHookProps } from '@kbn/securitysolution-io-ts-list-types'; import { @@ -46,12 +47,11 @@ describe('usePersistExceptionItem', () => { test('"isLoading" is "true" when exception item is being saved', async () => { await act(async () => { - const { result, rerender, waitForNextUpdate } = renderHook< - PersistHookProps, - ReturnPersistExceptionItem - >(() => usePersistExceptionItem({ http: mockKibanaHttpService, onError })); + const { result, rerender } = renderHook(() => + usePersistExceptionItem({ http: mockKibanaHttpService, onError }) + ); - await waitForNextUpdate(); + await waitFor(() => null); result.current[1](getCreateExceptionListItemSchemaMock()); rerender(); @@ -61,14 +61,13 @@ describe('usePersistExceptionItem', () => { test('"isSaved" is "true" when exception item saved successfully', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook< - PersistHookProps, - ReturnPersistExceptionItem - >(() => usePersistExceptionItem({ http: mockKibanaHttpService, onError })); + const { result } = renderHook(() => + usePersistExceptionItem({ http: mockKibanaHttpService, onError }) + ); - await waitForNextUpdate(); + await waitFor(() => null); result.current[1](getCreateExceptionListItemSchemaMock()); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); }); @@ -78,17 +77,16 @@ describe('usePersistExceptionItem', () => { const addExceptionListItem = jest.spyOn(api, 'addExceptionListItem'); const updateExceptionListItem = jest.spyOn(api, 'updateExceptionListItem'); await act(async () => { - const { result, waitForNextUpdate } = renderHook< - PersistHookProps, - ReturnPersistExceptionItem - >(() => usePersistExceptionItem({ http: mockKibanaHttpService, onError })); + const { result } = renderHook(() => + usePersistExceptionItem({ http: mockKibanaHttpService, onError }) + ); - await waitForNextUpdate(); + await waitFor(() => null); // NOTE: Take note here passing in an exception item where it's // entries have been enriched with ids to ensure that they get stripped // before the call goes through result.current[1]({ ...getUpdateExceptionListItemSchemaMock(), entries: ENTRIES_WITH_IDS }); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); expect(addExceptionListItem).not.toHaveBeenCalled(); @@ -104,17 +102,16 @@ describe('usePersistExceptionItem', () => { const updateExceptionListItem = jest.spyOn(api, 'updateExceptionListItem'); const addExceptionListItem = jest.spyOn(api, 'addExceptionListItem'); await act(async () => { - const { result, waitForNextUpdate } = renderHook< - PersistHookProps, - ReturnPersistExceptionItem - >(() => usePersistExceptionItem({ http: mockKibanaHttpService, onError })); + const { result } = renderHook(() => + usePersistExceptionItem({ http: mockKibanaHttpService, onError }) + ); - await waitForNextUpdate(); + await waitFor(() => null); // NOTE: Take note here passing in an exception item where it's // entries have been enriched with ids to ensure that they get stripped // before the call goes through result.current[1]({ ...getCreateExceptionListItemSchemaMock(), entries: ENTRIES_WITH_IDS }); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); expect(updateExceptionListItem).not.toHaveBeenCalled(); @@ -131,14 +128,13 @@ describe('usePersistExceptionItem', () => { jest.spyOn(api, 'addExceptionListItem').mockRejectedValue(error); await act(async () => { - const { result, waitForNextUpdate } = renderHook< - PersistHookProps, - ReturnPersistExceptionItem - >(() => usePersistExceptionItem({ http: mockKibanaHttpService, onError })); + const { result } = renderHook(() => + usePersistExceptionItem({ http: mockKibanaHttpService, onError }) + ); - await waitForNextUpdate(); + await waitFor(() => null); result.current[1](getCreateExceptionListItemSchemaMock()); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual([{ isLoading: false, isSaved: false }, result.current[1]]); expect(onError).toHaveBeenCalledWith(error); diff --git a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_list.test.ts b/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_list.test.ts index 09257c489a895..6cb70feb49b68 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_list.test.ts +++ b/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_list.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import * as api from '@kbn/securitysolution-list-api'; import { PersistHookProps } from '@kbn/securitysolution-io-ts-list-types'; import { @@ -46,11 +47,10 @@ describe('usePersistExceptionList', () => { test('"isLoading" is "true" when exception item is being saved', async () => { await act(async () => { - const { result, rerender, waitForNextUpdate } = renderHook< - PersistHookProps, - ReturnPersistExceptionList - >(() => usePersistExceptionList({ http: mockKibanaHttpService, onError })); - await waitForNextUpdate(); + const { result, rerender } = renderHook(() => + usePersistExceptionList({ http: mockKibanaHttpService, onError }) + ); + await waitFor(() => null); result.current[1](getCreateExceptionListSchemaMock()); rerender(); @@ -60,13 +60,12 @@ describe('usePersistExceptionList', () => { test('"isSaved" is "true" when exception item saved successfully', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook< - PersistHookProps, - ReturnPersistExceptionList - >(() => usePersistExceptionList({ http: mockKibanaHttpService, onError })); - await waitForNextUpdate(); + const { result } = renderHook(() => + usePersistExceptionList({ http: mockKibanaHttpService, onError }) + ); + await waitFor(() => null); result.current[1](getCreateExceptionListSchemaMock()); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); }); @@ -76,14 +75,13 @@ describe('usePersistExceptionList', () => { const addException = jest.spyOn(api, 'addExceptionList'); const updateException = jest.spyOn(api, 'updateExceptionList'); await act(async () => { - const { result, waitForNextUpdate } = renderHook< - PersistHookProps, - ReturnPersistExceptionList - >(() => usePersistExceptionList({ http: mockKibanaHttpService, onError })); + const { result } = renderHook(() => + usePersistExceptionList({ http: mockKibanaHttpService, onError }) + ); - await waitForNextUpdate(); + await waitFor(() => null); result.current[1](getUpdateExceptionListSchemaMock()); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); expect(addException).not.toHaveBeenCalled(); @@ -96,13 +94,12 @@ describe('usePersistExceptionList', () => { jest.spyOn(api, 'addExceptionList').mockRejectedValue(error); await act(async () => { - const { result, waitForNextUpdate } = renderHook< - PersistHookProps, - ReturnPersistExceptionList - >(() => usePersistExceptionList({ http: mockKibanaHttpService, onError })); - await waitForNextUpdate(); + const { result } = renderHook(() => + usePersistExceptionList({ http: mockKibanaHttpService, onError }) + ); + await waitFor(() => null); result.current[1](getCreateExceptionListSchemaMock()); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual([{ isLoading: false, isSaved: false }, result.current[1]]); expect(onError).toHaveBeenCalledWith(error); diff --git a/x-pack/plugins/lists/public/exceptions/hooks/use_api.test.ts b/x-pack/plugins/lists/public/exceptions/hooks/use_api.test.ts index 55c8ebde7cebd..ea7ac5171c032 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/use_api.test.ts +++ b/x-pack/plugins/lists/public/exceptions/hooks/use_api.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import * as api from '@kbn/securitysolution-list-api'; import { ExceptionsApi, useApi } from '@kbn/securitysolution-list-hooks'; import type { @@ -51,54 +52,50 @@ describe('useApi', () => { .spyOn(api, 'deleteExceptionListItemById') .mockResolvedValue(payload); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useApi(mockKibanaHttpService) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useApi(mockKibanaHttpService)); + await waitFor(() => null); - const { id, namespace_type: namespaceType } = payload; + const { id, namespace_type: namespaceType } = payload; + await act(async () => { await result.current.deleteExceptionItem({ id, namespaceType, onError: jest.fn(), onSuccess: onSuccessMock, }); + }); - const expected: ApiCallByIdProps = { - http: mockKibanaHttpService, - id, - namespaceType, - signal: new AbortController().signal, - }; + const expected: ApiCallByIdProps = { + http: mockKibanaHttpService, + id, + namespaceType, + signal: new AbortController().signal, + }; - expect(spyOnDeleteExceptionListItemById).toHaveBeenCalledWith(expected); - expect(onSuccessMock).toHaveBeenCalled(); - }); + expect(spyOnDeleteExceptionListItemById).toHaveBeenCalledWith(expected); + expect(onSuccessMock).toHaveBeenCalled(); }); test('invokes "onError" callback if "deleteExceptionListItemById" fails', async () => { const mockError = new Error('failed to delete item'); jest.spyOn(api, 'deleteExceptionListItemById').mockRejectedValue(mockError); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useApi(mockKibanaHttpService) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useApi(mockKibanaHttpService)); + await waitFor(() => null); - const { id, namespace_type: namespaceType } = getExceptionListItemSchemaMock(); + const { id, namespace_type: namespaceType } = getExceptionListItemSchemaMock(); + await act(async () => { await result.current.deleteExceptionItem({ id, namespaceType, onError: onErrorMock, onSuccess: jest.fn(), }); - - expect(onErrorMock).toHaveBeenCalledWith(mockError); }); + + expect(onErrorMock).toHaveBeenCalledWith(mockError); }); }); @@ -110,54 +107,50 @@ describe('useApi', () => { .spyOn(api, 'deleteExceptionListById') .mockResolvedValue(payload); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useApi(mockKibanaHttpService) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useApi(mockKibanaHttpService)); + await waitFor(() => null); - const { id, namespace_type: namespaceType } = payload; + const { id, namespace_type: namespaceType } = payload; + await act(async () => { await result.current.deleteExceptionList({ id, namespaceType, onError: jest.fn(), onSuccess: onSuccessMock, }); + }); - const expected: ApiCallByIdProps = { - http: mockKibanaHttpService, - id, - namespaceType, - signal: new AbortController().signal, - }; + const expected: ApiCallByIdProps = { + http: mockKibanaHttpService, + id, + namespaceType, + signal: new AbortController().signal, + }; - expect(spyOnDeleteExceptionListById).toHaveBeenCalledWith(expected); - expect(onSuccessMock).toHaveBeenCalled(); - }); + expect(spyOnDeleteExceptionListById).toHaveBeenCalledWith(expected); + expect(onSuccessMock).toHaveBeenCalled(); }); test('invokes "onError" callback if "deleteExceptionListById" fails', async () => { const mockError = new Error('failed to delete item'); jest.spyOn(api, 'deleteExceptionListById').mockRejectedValue(mockError); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useApi(mockKibanaHttpService) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useApi(mockKibanaHttpService)); + await waitFor(() => null); - const { id, namespace_type: namespaceType } = getExceptionListSchemaMock(); + const { id, namespace_type: namespaceType } = getExceptionListSchemaMock(); + await act(async () => { await result.current.deleteExceptionList({ id, namespaceType, onError: onErrorMock, onSuccess: jest.fn(), }); - - expect(onErrorMock).toHaveBeenCalledWith(mockError); }); + + expect(onErrorMock).toHaveBeenCalledWith(mockError); }); }); @@ -169,58 +162,54 @@ describe('useApi', () => { .spyOn(api, 'fetchExceptionListItemById') .mockResolvedValue(payload); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useApi(mockKibanaHttpService) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useApi(mockKibanaHttpService)); + await waitFor(() => null); - const { id, namespace_type: namespaceType } = payload; + const { id, namespace_type: namespaceType } = payload; + await act(async () => { await result.current.getExceptionItem({ id, namespaceType, onError: jest.fn(), onSuccess: onSuccessMock, }); - - const expected: ApiCallByIdProps = { - http: mockKibanaHttpService, - id, - namespaceType, - signal: new AbortController().signal, - }; - const expectedExceptionListItem = { - ...getExceptionListItemSchemaMock(), - entries: ENTRIES_WITH_IDS, - }; - - expect(spyOnFetchExceptionListItemById).toHaveBeenCalledWith(expected); - expect(onSuccessMock).toHaveBeenCalledWith(expectedExceptionListItem); }); + + const expected: ApiCallByIdProps = { + http: mockKibanaHttpService, + id, + namespaceType, + signal: new AbortController().signal, + }; + const expectedExceptionListItem = { + ...getExceptionListItemSchemaMock(), + entries: ENTRIES_WITH_IDS, + }; + + expect(spyOnFetchExceptionListItemById).toHaveBeenCalledWith(expected); + expect(onSuccessMock).toHaveBeenCalledWith(expectedExceptionListItem); }); test('invokes "onError" callback if "fetchExceptionListItemById" fails', async () => { const mockError = new Error('failed to delete item'); jest.spyOn(api, 'fetchExceptionListItemById').mockRejectedValue(mockError); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useApi(mockKibanaHttpService) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useApi(mockKibanaHttpService)); + await waitFor(() => null); - const { id, namespace_type: namespaceType } = getExceptionListSchemaMock(); + const { id, namespace_type: namespaceType } = getExceptionListSchemaMock(); + await act(async () => { await result.current.getExceptionItem({ id, namespaceType, onError: onErrorMock, onSuccess: jest.fn(), }); - - expect(onErrorMock).toHaveBeenCalledWith(mockError); }); + + expect(onErrorMock).toHaveBeenCalledWith(mockError); }); }); @@ -232,54 +221,50 @@ describe('useApi', () => { .spyOn(api, 'fetchExceptionListById') .mockResolvedValue(payload); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useApi(mockKibanaHttpService) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useApi(mockKibanaHttpService)); + await waitFor(() => null); - const { id, namespace_type: namespaceType } = payload; + const { id, namespace_type: namespaceType } = payload; + await act(async () => { await result.current.getExceptionList({ id, namespaceType, onError: jest.fn(), onSuccess: onSuccessMock, }); + }); - const expected: ApiCallByIdProps = { - http: mockKibanaHttpService, - id, - namespaceType, - signal: new AbortController().signal, - }; + const expected: ApiCallByIdProps = { + http: mockKibanaHttpService, + id, + namespaceType, + signal: new AbortController().signal, + }; - expect(spyOnFetchExceptionListById).toHaveBeenCalledWith(expected); - expect(onSuccessMock).toHaveBeenCalled(); - }); + expect(spyOnFetchExceptionListById).toHaveBeenCalledWith(expected); + expect(onSuccessMock).toHaveBeenCalled(); }); test('invokes "onError" callback if "fetchExceptionListById" fails', async () => { const mockError = new Error('failed to delete item'); jest.spyOn(api, 'fetchExceptionListById').mockRejectedValue(mockError); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useApi(mockKibanaHttpService) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useApi(mockKibanaHttpService)); + await waitFor(() => null); - const { id, namespace_type: namespaceType } = getExceptionListSchemaMock(); + const { id, namespace_type: namespaceType } = getExceptionListSchemaMock(); + await act(async () => { await result.current.getExceptionList({ id, namespaceType, onError: onErrorMock, onSuccess: jest.fn(), }); - - expect(onErrorMock).toHaveBeenCalledWith(mockError); }); + + expect(onErrorMock).toHaveBeenCalledWith(mockError); }); }); @@ -291,12 +276,10 @@ describe('useApi', () => { .spyOn(api, 'fetchExceptionListsItemsByListIds') .mockResolvedValue(output); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useApi(mockKibanaHttpService) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useApi(mockKibanaHttpService)); + await waitFor(() => null); + await act(async () => { await result.current.getExceptionListsItems({ lists: [ { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, @@ -311,28 +294,28 @@ describe('useApi', () => { showDetectionsListsOnly: false, showEndpointListsOnly: false, }); + }); - const expected: ApiCallByListIdProps = { - http: mockKibanaHttpService, - listIds: ['list_id'], - namespaceTypes: ['single'], - pagination: { - page: 1, - perPage: 1, - total: 0, - }, - signal: new AbortController().signal, - }; - - expect(spyOnFetchExceptionListsItemsByListIds).toHaveBeenCalledWith(expected); - expect(onSuccessMock).toHaveBeenCalledWith({ - exceptions: [{ ...getExceptionListItemSchemaMock(), entries: ENTRIES_WITH_IDS }], - pagination: { - page: 1, - perPage: 1, - total: 1, - }, - }); + const expected: ApiCallByListIdProps = { + http: mockKibanaHttpService, + listIds: ['list_id'], + namespaceTypes: ['single'], + pagination: { + page: 1, + perPage: 1, + total: 0, + }, + signal: new AbortController().signal, + }; + + expect(spyOnFetchExceptionListsItemsByListIds).toHaveBeenCalledWith(expected); + expect(onSuccessMock).toHaveBeenCalledWith({ + exceptions: [{ ...getExceptionListItemSchemaMock(), entries: ENTRIES_WITH_IDS }], + pagination: { + page: 1, + perPage: 1, + total: 1, + }, }); }); @@ -343,12 +326,10 @@ describe('useApi', () => { .spyOn(api, 'fetchExceptionListsItemsByListIds') .mockResolvedValue(output); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useApi(mockKibanaHttpService) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useApi(mockKibanaHttpService)); + await waitFor(() => null); + await act(async () => { await result.current.getExceptionListsItems({ lists: [ { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, @@ -363,16 +344,16 @@ describe('useApi', () => { showDetectionsListsOnly: false, showEndpointListsOnly: true, }); + }); - expect(spyOnFetchExceptionListsItemsByListIds).not.toHaveBeenCalled(); - expect(onSuccessMock).toHaveBeenCalledWith({ - exceptions: [], - pagination: { - page: 0, - perPage: 20, - total: 0, - }, - }); + expect(spyOnFetchExceptionListsItemsByListIds).not.toHaveBeenCalled(); + expect(onSuccessMock).toHaveBeenCalledWith({ + exceptions: [], + pagination: { + page: 0, + perPage: 20, + total: 0, + }, }); }); @@ -380,12 +361,10 @@ describe('useApi', () => { const mockError = new Error('failed to delete item'); jest.spyOn(api, 'fetchExceptionListsItemsByListIds').mockRejectedValue(mockError); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useApi(mockKibanaHttpService) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useApi(mockKibanaHttpService)); + await waitFor(() => null); + await act(async () => { await result.current.getExceptionListsItems({ lists: [ { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, @@ -400,9 +379,9 @@ describe('useApi', () => { showDetectionsListsOnly: false, showEndpointListsOnly: false, }); - - expect(onErrorMock).toHaveBeenCalledWith(mockError); }); + + expect(onErrorMock).toHaveBeenCalledWith(mockError); }); }); @@ -414,24 +393,22 @@ describe('useApi', () => { .spyOn(api, 'addExceptionListItem') .mockResolvedValue(payload); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useApi(mockKibanaHttpService) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useApi(mockKibanaHttpService)); + await waitFor(() => null); + await act(async () => { await result.current.addExceptionListItem({ listItem: itemToCreate, }); + }); - const expected: AddExceptionListItemProps = { - http: mockKibanaHttpService, - listItem: getCreateExceptionListItemSchemaMock(), - signal: new AbortController().signal, - }; + const expected: AddExceptionListItemProps = { + http: mockKibanaHttpService, + listItem: getCreateExceptionListItemSchemaMock(), + signal: new AbortController().signal, + }; - expect(spyOnFetchExceptionListItemById).toHaveBeenCalledWith(expected); - }); + expect(spyOnFetchExceptionListItemById).toHaveBeenCalledWith(expected); }); }); @@ -443,24 +420,22 @@ describe('useApi', () => { .spyOn(api, 'updateExceptionListItem') .mockResolvedValue(payload); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useApi(mockKibanaHttpService) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useApi(mockKibanaHttpService)); + await waitFor(() => null); + await act(async () => { await result.current.updateExceptionListItem({ listItem: itemToUpdate, }); + }); - const expected: UpdateExceptionListItemProps = { - http: mockKibanaHttpService, - listItem: getUpdateExceptionListItemSchemaMock(), - signal: new AbortController().signal, - }; + const expected: UpdateExceptionListItemProps = { + http: mockKibanaHttpService, + listItem: getUpdateExceptionListItemSchemaMock(), + signal: new AbortController().signal, + }; - expect(spyOnUpdateExceptionListItem).toHaveBeenCalledWith(expected); - }); + expect(spyOnUpdateExceptionListItem).toHaveBeenCalledWith(expected); }); }); @@ -471,12 +446,10 @@ describe('useApi', () => { .spyOn(api, 'duplicateExceptionList') .mockResolvedValue(getExceptionListSchemaMock()); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useApi(mockKibanaHttpService) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useApi(mockKibanaHttpService)); + await waitFor(() => null); + await act(async () => { await result.current.duplicateExceptionList({ includeExpiredExceptions: false, listId: 'my_list', @@ -484,30 +457,28 @@ describe('useApi', () => { onError: jest.fn(), onSuccess: onSuccessMock, }); + }); - const expected: DuplicateExceptionListProps = { - http: mockKibanaHttpService, - includeExpiredExceptions: false, - listId: 'my_list', - namespaceType: 'single', - signal: new AbortController().signal, - }; + const expected: DuplicateExceptionListProps = { + http: mockKibanaHttpService, + includeExpiredExceptions: false, + listId: 'my_list', + namespaceType: 'single', + signal: new AbortController().signal, + }; - expect(spyOnDuplicateExceptionList).toHaveBeenCalledWith(expected); - expect(onSuccessMock).toHaveBeenCalled(); - }); + expect(spyOnDuplicateExceptionList).toHaveBeenCalledWith(expected); + expect(onSuccessMock).toHaveBeenCalled(); }); test('invokes "onError" callback if "duplicateExceptionList" fails', async () => { const mockError = new Error('failed to duplicate item'); jest.spyOn(api, 'duplicateExceptionList').mockRejectedValue(mockError); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useApi(mockKibanaHttpService) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useApi(mockKibanaHttpService)); + await waitFor(() => null); + await act(async () => { await result.current.duplicateExceptionList({ includeExpiredExceptions: false, listId: 'my_list', @@ -515,9 +486,9 @@ describe('useApi', () => { onError: onErrorMock, onSuccess: jest.fn(), }); - - expect(onErrorMock).toHaveBeenCalledWith(mockError); }); + + expect(onErrorMock).toHaveBeenCalledWith(mockError); }); }); }); diff --git a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_lists.test.ts b/x-pack/plugins/lists/public/exceptions/hooks/use_exception_lists.test.ts index 0148feff83d58..281504856ef91 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_lists.test.ts +++ b/x-pack/plugins/lists/public/exceptions/hooks/use_exception_lists.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import type { ExceptionListSchema, UseExceptionListsProps, @@ -32,199 +33,195 @@ describe('useExceptionLists', () => { }); test('initializes hook', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - UseExceptionListsProps, - ReturnExceptionLists - >(() => - useExceptionLists({ - errorMessage: 'Uh oh', - filterOptions: {}, - http: mockKibanaHttpService, - initialPagination: { - page: 1, - perPage: 20, - total: 0, - }, - namespaceTypes: ['single', 'agnostic'], - notifications: mockKibanaNotificationsService, - }) - ); - await waitForNextUpdate(); - - expect(result.current).toEqual([ - true, - [], - { + const { result } = renderHook(() => + useExceptionLists({ + errorMessage: 'Uh oh', + filterOptions: {}, + http: mockKibanaHttpService, + initialPagination: { page: 1, perPage: 20, total: 0, }, - expect.any(Function), - expect.any(Function), - { field: 'created_at', order: 'desc' }, - expect.any(Function), - ]); - }); + namespaceTypes: ['single', 'agnostic'], + notifications: mockKibanaNotificationsService, + }) + ); + + await waitFor(() => null); + + expect(result.current).toEqual([ + true, + [], + { + page: 1, + perPage: 20, + total: 0, + }, + expect.any(Function), + expect.any(Function), + { field: 'created_at', order: 'desc' }, + expect.any(Function), + ]); }); test('fetches exception lists', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - UseExceptionListsProps, - ReturnExceptionLists - >(() => - useExceptionLists({ - errorMessage: 'Uh oh', - filterOptions: {}, - http: mockKibanaHttpService, - initialPagination: { - page: 1, - perPage: 20, - total: 0, - }, - namespaceTypes: ['single', 'agnostic'], - notifications: mockKibanaNotificationsService, - }) - ); - // NOTE: First `waitForNextUpdate` is initialization - // Second call applies the params - await waitForNextUpdate(); - await waitForNextUpdate(); - - const expectedListItemsResult: ExceptionListSchema[] = getFoundExceptionListSchemaMock().data; - - expect(result.current).toEqual([ - false, - expectedListItemsResult, - { + const { result } = renderHook(() => + useExceptionLists({ + errorMessage: 'Uh oh', + filterOptions: {}, + http: mockKibanaHttpService, + initialPagination: { page: 1, perPage: 20, - total: 1, + total: 0, }, - expect.any(Function), - expect.any(Function), - { field: 'created_at', order: 'desc' }, - expect.any(Function), - ]); - }); + namespaceTypes: ['single', 'agnostic'], + notifications: mockKibanaNotificationsService, + }) + ); + + await waitFor(() => null); + + const expectedListItemsResult: ExceptionListSchema[] = getFoundExceptionListSchemaMock().data; + + expect(result.current).toEqual([ + false, + expectedListItemsResult, + { + page: 1, + perPage: 20, + total: 1, + }, + expect.any(Function), + expect.any(Function), + { field: 'created_at', order: 'desc' }, + expect.any(Function), + ]); }); test('does not fetch specific list id if it is added to the hideLists array', async () => { const spyOnfetchExceptionLists = jest.spyOn(api, 'fetchExceptionLists'); - await act(async () => { - const { waitForNextUpdate } = renderHook(() => - useExceptionLists({ - errorMessage: 'Uh oh', - filterOptions: {}, - hideLists: ['listId-1'], - http: mockKibanaHttpService, - initialPagination: { - page: 1, - perPage: 20, - total: 0, - }, - namespaceTypes: ['single', 'agnostic'], - notifications: mockKibanaNotificationsService, - }) - ); - // NOTE: First `waitForNextUpdate` is initialization - // Second call applies the params - await waitForNextUpdate(); - await waitForNextUpdate(); - - expect(spyOnfetchExceptionLists).toHaveBeenCalledWith({ - filters: - '(not exception-list.attributes.list_id: listId-1* AND not exception-list-agnostic.attributes.list_id: listId-1*)', + renderHook(() => + useExceptionLists({ + errorMessage: 'Uh oh', + filterOptions: {}, + hideLists: ['listId-1'], http: mockKibanaHttpService, - namespaceTypes: 'single,agnostic', - pagination: { page: 1, perPage: 20 }, - signal: new AbortController().signal, - sort: { field: 'created_at', order: 'desc' }, - }); + initialPagination: { + page: 1, + perPage: 20, + total: 0, + }, + namespaceTypes: ['single', 'agnostic'], + notifications: mockKibanaNotificationsService, + }) + ); + + await waitFor(() => null); + + expect(spyOnfetchExceptionLists).toHaveBeenCalledWith({ + filters: + '(not exception-list.attributes.list_id: listId-1* AND not exception-list-agnostic.attributes.list_id: listId-1*)', + http: mockKibanaHttpService, + namespaceTypes: 'single,agnostic', + pagination: { page: 1, perPage: 20 }, + signal: new AbortController().signal, + sort: { field: 'created_at', order: 'desc' }, }); }); test('applies filters to query', async () => { const spyOnfetchExceptionLists = jest.spyOn(api, 'fetchExceptionLists'); - await act(async () => { - const { waitForNextUpdate } = renderHook(() => + renderHook(() => + useExceptionLists({ + errorMessage: 'Uh oh', + filterOptions: { + created_by: 'Moi', + name: 'Sample Endpoint', + }, + hideLists: ['listId-1'], + http: mockKibanaHttpService, + initialPagination: { + page: 1, + perPage: 20, + total: 0, + }, + namespaceTypes: ['single', 'agnostic'], + notifications: mockKibanaNotificationsService, + }) + ); + + await waitFor(() => null); + + expect(spyOnfetchExceptionLists).toHaveBeenCalledWith({ + filters: + '(exception-list.attributes.created_by:Moi OR exception-list-agnostic.attributes.created_by:Moi) AND (exception-list.attributes.name.text:Sample Endpoint OR exception-list-agnostic.attributes.name.text:Sample Endpoint) AND (not exception-list.attributes.list_id: listId-1* AND not exception-list-agnostic.attributes.list_id: listId-1*)', + http: mockKibanaHttpService, + namespaceTypes: 'single,agnostic', + pagination: { page: 1, perPage: 20 }, + signal: new AbortController().signal, + sort: { + field: 'created_at', + order: 'desc', + }, + }); + }); + + test('fetches a new exception list and its items when props change', async () => { + const spyOnfetchExceptionLists = jest.spyOn(api, 'fetchExceptionLists'); + const { rerender } = renderHook( + ({ errorMessage, filterOptions, http, initialPagination, namespaceTypes, notifications }) => useExceptionLists({ + errorMessage, + filterOptions, + http, + initialPagination, + namespaceTypes, + notifications, + }), + { + initialProps: { errorMessage: 'Uh oh', - filterOptions: { - created_by: 'Moi', - name: 'Sample Endpoint', - }, - hideLists: ['listId-1'], + filterOptions: {}, http: mockKibanaHttpService, initialPagination: { page: 1, perPage: 20, total: 0, }, - namespaceTypes: ['single', 'agnostic'], + namespaceTypes: ['single'], notifications: mockKibanaNotificationsService, - }) - ); - // NOTE: First `waitForNextUpdate` is initialization - // Second call applies the params - await waitForNextUpdate(); - await waitForNextUpdate(); - - expect(spyOnfetchExceptionLists).toHaveBeenCalledWith({ - filters: - '(exception-list.attributes.created_by:Moi OR exception-list-agnostic.attributes.created_by:Moi) AND (exception-list.attributes.name.text:Sample Endpoint OR exception-list-agnostic.attributes.name.text:Sample Endpoint) AND (not exception-list.attributes.list_id: listId-1* AND not exception-list-agnostic.attributes.list_id: listId-1*)', - http: mockKibanaHttpService, - namespaceTypes: 'single,agnostic', - pagination: { page: 1, perPage: 20 }, - signal: new AbortController().signal, - sort: { - field: 'created_at', - order: 'desc', }, - }); + } + ); + + await waitFor(() => null); + + rerender({ + errorMessage: 'Uh oh', + filterOptions: {}, + http: mockKibanaHttpService, + initialPagination: { + page: 1, + perPage: 20, + total: 0, + }, + namespaceTypes: ['single', 'agnostic'], + notifications: mockKibanaNotificationsService, }); + + await waitFor(() => null); + + expect(spyOnfetchExceptionLists).toHaveBeenCalledTimes(2); }); - test('fetches a new exception list and its items when props change', async () => { + test('fetches list when refreshExceptionList callback invoked', async () => { const spyOnfetchExceptionLists = jest.spyOn(api, 'fetchExceptionLists'); - await act(async () => { - const { rerender, waitForNextUpdate } = renderHook< - UseExceptionListsProps, - ReturnExceptionLists - >( - ({ errorMessage, filterOptions, http, initialPagination, namespaceTypes, notifications }) => - useExceptionLists({ - errorMessage, - filterOptions, - http, - initialPagination, - namespaceTypes, - notifications, - }), - { - initialProps: { - errorMessage: 'Uh oh', - filterOptions: {}, - http: mockKibanaHttpService, - initialPagination: { - page: 1, - perPage: 20, - total: 0, - }, - namespaceTypes: ['single'], - notifications: mockKibanaNotificationsService, - }, - } - ); - // NOTE: First `waitForNextUpdate` is initialization - // Second call applies the params - await waitForNextUpdate(); - await waitForNextUpdate(); - - rerender({ + const { result } = renderHook(() => + useExceptionLists({ errorMessage: 'Uh oh', filterOptions: {}, http: mockKibanaHttpService, @@ -235,49 +232,20 @@ describe('useExceptionLists', () => { }, namespaceTypes: ['single', 'agnostic'], notifications: mockKibanaNotificationsService, - }); - // NOTE: Only need one call here because hook already initilaized - await waitForNextUpdate(); + }) + ); - expect(spyOnfetchExceptionLists).toHaveBeenCalledTimes(2); - }); - }); + await waitFor(() => null); - test('fetches list when refreshExceptionList callback invoked', async () => { - const spyOnfetchExceptionLists = jest.spyOn(api, 'fetchExceptionLists'); - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - UseExceptionListsProps, - ReturnExceptionLists - >(() => - useExceptionLists({ - errorMessage: 'Uh oh', - filterOptions: {}, - http: mockKibanaHttpService, - initialPagination: { - page: 1, - perPage: 20, - total: 0, - }, - namespaceTypes: ['single', 'agnostic'], - notifications: mockKibanaNotificationsService, - }) - ); - // NOTE: First `waitForNextUpdate` is initialization - // Second call applies the params - await waitForNextUpdate(); - await waitForNextUpdate(); + expect(typeof result.current[3]).toEqual('function'); - expect(typeof result.current[3]).toEqual('function'); + if (result.current[4] != null) { + result.current[4](); + } - if (result.current[4] != null) { - result.current[4](); - } - // NOTE: Only need one call here because hook already initilaized - await waitForNextUpdate(); + await waitFor(() => null); - expect(spyOnfetchExceptionLists).toHaveBeenCalledTimes(2); - }); + expect(spyOnfetchExceptionLists).toHaveBeenCalledTimes(2); }); test('invokes notifications service if "fetchExceptionLists" fails', async () => { @@ -285,30 +253,26 @@ describe('useExceptionLists', () => { const spyOnfetchExceptionLists = jest .spyOn(api, 'fetchExceptionLists') .mockRejectedValue(mockError); - await act(async () => { - const { waitForNextUpdate } = renderHook(() => - useExceptionLists({ - errorMessage: 'Uh oh', - filterOptions: {}, - http: mockKibanaHttpService, - initialPagination: { - page: 1, - perPage: 20, - total: 0, - }, - namespaceTypes: ['single', 'agnostic'], - notifications: mockKibanaNotificationsService, - }) - ); - // NOTE: First `waitForNextUpdate` is initialization - // Second call applies the params - await waitForNextUpdate(); - await waitForNextUpdate(); - - expect(mockKibanaNotificationsService.toasts.addError).toHaveBeenCalledWith(mockError, { - title: 'Uh oh', - }); - expect(spyOnfetchExceptionLists).toHaveBeenCalledTimes(1); + renderHook(() => + useExceptionLists({ + errorMessage: 'Uh oh', + filterOptions: {}, + http: mockKibanaHttpService, + initialPagination: { + page: 1, + perPage: 20, + total: 0, + }, + namespaceTypes: ['single', 'agnostic'], + notifications: mockKibanaNotificationsService, + }) + ); + + await waitFor(() => null); + + expect(mockKibanaNotificationsService.toasts.addError).toHaveBeenCalledWith(mockError, { + title: 'Uh oh', }); + expect(spyOnfetchExceptionLists).toHaveBeenCalledTimes(1); }); }); diff --git a/x-pack/plugins/lists/public/lists/hooks/use_create_list_index.test.ts b/x-pack/plugins/lists/public/lists/hooks/use_create_list_index.test.ts index 3e91e9b269830..d6fd3191a9d97 100644 --- a/x-pack/plugins/lists/public/lists/hooks/use_create_list_index.test.ts +++ b/x-pack/plugins/lists/public/lists/hooks/use_create_list_index.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useCreateListIndex } from '@kbn/securitysolution-list-hooks'; import * as Api from '@kbn/securitysolution-list-api'; import { httpServiceMock } from '@kbn/core/public/mocks'; @@ -28,13 +29,13 @@ describe('useCreateListIndex', () => { }); it('should call Api.createListIndex when start() executes', async () => { - const { result, waitForNextUpdate } = renderHook(() => useCreateListIndex({ http: httpMock }), { + const { result } = renderHook(() => useCreateListIndex({ http: httpMock }), { wrapper: queryWrapper, }); act(() => { result.current.start(); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(Api.createListIndex).toHaveBeenCalledWith(expect.objectContaining({ http: httpMock })); }); @@ -43,15 +44,14 @@ describe('useCreateListIndex', () => { const onError = jest.fn(); jest.spyOn(Api, 'createListIndex').mockRejectedValue(new Error('Mocked error')); - const { result, waitForNextUpdate } = renderHook( - () => useCreateListIndex({ http: httpMock, onError }), - { wrapper: queryWrapper } - ); + const { result } = renderHook(() => useCreateListIndex({ http: httpMock, onError }), { + wrapper: queryWrapper, + }); act(() => { result.current.start(); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(onError).toHaveBeenCalledWith(new Error('Mocked error'), undefined, undefined); }); @@ -60,20 +60,20 @@ describe('useCreateListIndex', () => { jest.spyOn(Api, 'createListIndex').mockRejectedValue(new Error('Mocked error')); const invalidateQueriesSpy = jest.spyOn(queryClient, 'invalidateQueries'); - const { result, waitForNextUpdate } = renderHook(() => useCreateListIndex({ http: httpMock }), { + const { result } = renderHook(() => useCreateListIndex({ http: httpMock }), { wrapper: queryWrapper, }); act(() => { result.current.start(); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(invalidateQueriesSpy).not.toHaveBeenCalled(); }); it('should invalidate read index query on success', async () => { - const { result, waitForNextUpdate } = renderHook(() => useCreateListIndex({ http: httpMock }), { + const { result } = renderHook(() => useCreateListIndex({ http: httpMock }), { wrapper: queryWrapper, }); const invalidateQueriesSpy = jest.spyOn(queryClient, 'invalidateQueries'); @@ -81,7 +81,7 @@ describe('useCreateListIndex', () => { act(() => { result.current.start(); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(invalidateQueriesSpy).toHaveBeenCalledWith(['detectionEngine', 'listIndex']); }); diff --git a/x-pack/plugins/lists/public/lists/hooks/use_delete_list.test.ts b/x-pack/plugins/lists/public/lists/hooks/use_delete_list.test.ts index aac604a89bc8a..740913588d628 100644 --- a/x-pack/plugins/lists/public/lists/hooks/use_delete_list.test.ts +++ b/x-pack/plugins/lists/public/lists/hooks/use_delete_list.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useDeleteList } from '@kbn/securitysolution-list-hooks'; import * as Api from '@kbn/securitysolution-list-api'; import { httpServiceMock } from '@kbn/core/public/mocks'; @@ -25,11 +26,11 @@ describe('useDeleteList', () => { }); it('invokes Api.deleteList', async () => { - const { result, waitForNextUpdate } = renderHook(() => useDeleteList()); + const { result } = renderHook(() => useDeleteList()); act(() => { result.current.start({ http: httpMock, id: 'list' }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(Api.deleteList).toHaveBeenCalledWith( expect.objectContaining({ http: httpMock, id: 'list' }) diff --git a/x-pack/plugins/lists/public/lists/hooks/use_export_list.test.ts b/x-pack/plugins/lists/public/lists/hooks/use_export_list.test.ts index 4977d585fe43b..58e376e0a2c43 100644 --- a/x-pack/plugins/lists/public/lists/hooks/use_export_list.test.ts +++ b/x-pack/plugins/lists/public/lists/hooks/use_export_list.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useExportList } from '@kbn/securitysolution-list-hooks'; import * as Api from '@kbn/securitysolution-list-api'; import { httpServiceMock } from '@kbn/core/public/mocks'; @@ -23,11 +24,11 @@ describe('useExportList', () => { }); it('invokes Api.exportList', async () => { - const { result, waitForNextUpdate } = renderHook(() => useExportList()); + const { result } = renderHook(() => useExportList()); act(() => { result.current.start({ http: httpMock, listId: 'list' }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(Api.exportList).toHaveBeenCalledWith( expect.objectContaining({ http: httpMock, listId: 'list' }) diff --git a/x-pack/plugins/lists/public/lists/hooks/use_import_list.test.ts b/x-pack/plugins/lists/public/lists/hooks/use_import_list.test.ts index 4a1557e94fe79..19032893fa5a7 100644 --- a/x-pack/plugins/lists/public/lists/hooks/use_import_list.test.ts +++ b/x-pack/plugins/lists/public/lists/hooks/use_import_list.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useImportList } from '@kbn/securitysolution-list-hooks'; import * as Api from '@kbn/securitysolution-list-api'; import { httpServiceMock } from '@kbn/core/public/mocks'; @@ -32,7 +33,7 @@ describe('useImportList', () => { it('invokes Api.importList', async () => { const fileMock = 'my file' as unknown as File; - const { result, waitForNextUpdate } = renderHook(() => useImportList()); + const { result } = renderHook(() => useImportList()); act(() => { result.current.start({ @@ -42,7 +43,7 @@ describe('useImportList', () => { type: 'keyword', }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(Api.importList).toHaveBeenCalledWith( expect.objectContaining({ @@ -56,7 +57,7 @@ describe('useImportList', () => { it('populates result with the response of Api.importList', async () => { const fileMock = 'my file' as unknown as File; - const { result, waitForNextUpdate } = renderHook(() => useImportList()); + const { result } = renderHook(() => useImportList()); act(() => { result.current.start({ @@ -66,7 +67,7 @@ describe('useImportList', () => { type: 'keyword', }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.result).toEqual(getListResponseMock()); }); @@ -74,7 +75,7 @@ describe('useImportList', () => { it('error is populated if importList rejects', async () => { const fileMock = 'my file' as unknown as File; (Api.importList as jest.Mock).mockRejectedValue(new Error('whoops')); - const { result, waitForNextUpdate } = renderHook(() => useImportList()); + const { result } = renderHook(() => useImportList()); act(() => { result.current.start({ @@ -85,7 +86,7 @@ describe('useImportList', () => { }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.result).toBeUndefined(); expect(result.current.error).toEqual(new Error('whoops')); diff --git a/x-pack/plugins/lists/public/lists/hooks/use_read_list_index.test.ts b/x-pack/plugins/lists/public/lists/hooks/use_read_list_index.test.ts index dc57825d9acfa..03db39c84f455 100644 --- a/x-pack/plugins/lists/public/lists/hooks/use_read_list_index.test.ts +++ b/x-pack/plugins/lists/public/lists/hooks/use_read_list_index.test.ts @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useReadListIndex } from '@kbn/securitysolution-list-hooks'; import * as Api from '@kbn/securitysolution-list-api'; import { httpServiceMock } from '@kbn/core/public/mocks'; @@ -30,14 +31,11 @@ describe.skip('useReadListIndex', () => { }); it('should call Api.readListIndex when is enabled', async () => { - const { waitForNextUpdate } = renderHook( - () => useReadListIndex({ http: httpMock, isEnabled: true }), - { - wrapper: queryWrapper, - } - ); + renderHook(() => useReadListIndex({ http: httpMock, isEnabled: true }), { + wrapper: queryWrapper, + }); - await waitForNextUpdate(); + await waitFor(() => null); expect(Api.readListIndex).toHaveBeenCalled(); }); @@ -54,14 +52,11 @@ describe.skip('useReadListIndex', () => { const onError = jest.fn(); jest.spyOn(Api, 'readListIndex').mockRejectedValue(new Error('Mocked error')); - const { waitForNextUpdate } = renderHook( - () => useReadListIndex({ http: httpMock, isEnabled: true, onError }), - { - wrapper: queryWrapper, - } - ); + renderHook(() => useReadListIndex({ http: httpMock, isEnabled: true, onError }), { + wrapper: queryWrapper, + }); - await waitForNextUpdate(); + await waitFor(() => null); expect(onError).toHaveBeenCalledWith(new Error('Mocked error')); }); diff --git a/x-pack/plugins/ml/common/types/storage.test.tsx b/x-pack/plugins/ml/common/types/storage.test.tsx index a1473b23c5dcd..b00e639507d23 100644 --- a/x-pack/plugins/ml/common/types/storage.test.tsx +++ b/x-pack/plugins/ml/common/types/storage.test.tsx @@ -7,7 +7,9 @@ import type { FC } from 'react'; import React from 'react'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; + +import { act, waitFor } from '@testing-library/react'; import type { Storage } from '@kbn/kibana-utils-plugin/public'; import { StorageContextProvider, useStorage } from '@kbn/ml-local-storage'; @@ -61,12 +63,9 @@ describe('useStorage', () => { }); test('updates the storage value', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useStorage('ml.gettingStarted.isDismissed'), - { - wrapper: Provider, - } - ); + const { result } = renderHook(() => useStorage('ml.gettingStarted.isDismissed'), { + wrapper: Provider, + }); const [value, setValue] = result.current; @@ -74,20 +73,18 @@ describe('useStorage', () => { await act(async () => { setValue(false); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(result.current[0]).toBe(false); expect(mockSet).toHaveBeenCalledWith('ml.gettingStarted.isDismissed', false); }); test('removes the storage value', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useStorage('ml.gettingStarted.isDismissed'), - { - wrapper: Provider, - } - ); + const { result } = renderHook(() => useStorage('ml.gettingStarted.isDismissed'), { + wrapper: Provider, + }); const [value, setValue] = result.current; @@ -95,20 +92,18 @@ describe('useStorage', () => { await act(async () => { setValue(undefined); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(result.current[0]).toBe(undefined); expect(mockRemove).toHaveBeenCalledWith('ml.gettingStarted.isDismissed'); }); test('updates the value on storage event', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useStorage('ml.gettingStarted.isDismissed'), - { - wrapper: Provider, - } - ); + const { result } = renderHook(() => useStorage('ml.gettingStarted.isDismissed'), { + wrapper: Provider, + }); expect(result.current[0]).toBe(true); @@ -130,9 +125,10 @@ describe('useStorage', () => { newValue: null, }) ); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(result.current[0]).toBe(undefined); await act(async () => { @@ -142,9 +138,10 @@ describe('useStorage', () => { newValue: 'false', }) ); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(result.current[0]).toBe(false); }); }); diff --git a/x-pack/plugins/ml/public/application/hooks/use_as_observable.test.ts b/x-pack/plugins/ml/public/application/hooks/use_as_observable.test.ts index d8680f8393e6e..8908b09b37e4d 100644 --- a/x-pack/plugins/ml/public/application/hooks/use_as_observable.test.ts +++ b/x-pack/plugins/ml/public/application/hooks/use_as_observable.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useAsObservable } from './use_as_observable'; describe('useAsObservable', () => { @@ -35,7 +36,7 @@ describe('useAsObservable', () => { }); test('updates the subject with a new value', async () => { - const { result, rerender, waitForNextUpdate } = renderHook(useAsObservable, { + const { result, rerender } = renderHook(useAsObservable, { initialProps: 'test', }); @@ -50,9 +51,10 @@ describe('useAsObservable', () => { await act(async () => { rerender('test update'); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(subscriptionMock).toHaveBeenCalledTimes(2); expect(subscriptionMock).toHaveBeenCalledWith('test update'); expect(observableValue).toEqual('test update'); diff --git a/x-pack/plugins/ml/public/application/routing/use_resolver.test.ts b/x-pack/plugins/ml/public/application/routing/use_resolver.test.ts index b3b59c3f12a4b..28ed16883997b 100644 --- a/x-pack/plugins/ml/public/application/routing/use_resolver.test.ts +++ b/x-pack/plugins/ml/public/application/routing/use_resolver.test.ts @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useMlKibana, useMlLicenseInfo } from '../contexts/kibana'; import { usePermissionCheck } from '../capabilities/check_capabilities'; import { useRouteResolver } from './use_resolver'; @@ -63,8 +64,8 @@ describe('useResolver', () => { it.skip('redirects to the access denied page if some required capabilities are missing', async () => { (usePermissionCheck as jest.Mock).mockReturnValueOnce([false]); - const { waitForNextUpdate } = renderHook(() => useRouteResolver('full', ['canGetCalendars'])); - await waitForNextUpdate(); + renderHook(() => useRouteResolver('full', ['canGetCalendars'])); + await waitFor(() => null); expect(useMlKibana().services.application.navigateToUrl).toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/correlations/use_failed_transactions_correlations.test.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/correlations/use_failed_transactions_correlations.test.tsx index 5432c70e57ab1..79d32177bf909 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/correlations/use_failed_transactions_correlations.test.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/correlations/use_failed_transactions_correlations.test.tsx @@ -8,7 +8,9 @@ import React, { ReactNode } from 'react'; import { merge } from 'lodash'; import { createMemoryHistory } from 'history'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; + +import { act, waitFor } from '@testing-library/react'; import { ApmPluginContextValue } from '../../../context/apm_plugin/apm_plugin_context'; import { @@ -139,7 +141,7 @@ describe('useFailedTransactionsCorrelations', () => { }); it('should receive partial updates and finish running', async () => { - const { result, unmount, waitFor } = renderHook(() => useFailedTransactionsCorrelations(), { + const { result, unmount } = renderHook(() => useFailedTransactionsCorrelations(), { wrapper, }); @@ -292,7 +294,7 @@ describe('useFailedTransactionsCorrelations', () => { }); it('should stop and return an error after more than 100ms', async () => { - const { result, unmount, waitFor } = renderHook(() => useFailedTransactionsCorrelations(), { + const { result, unmount } = renderHook(() => useFailedTransactionsCorrelations(), { wrapper, initialProps: { error: true, @@ -316,7 +318,7 @@ describe('useFailedTransactionsCorrelations', () => { describe('when canceled', () => { it('should stop running', async () => { - const { result, unmount, waitFor } = renderHook(() => useFailedTransactionsCorrelations(), { + const { result, unmount } = renderHook(() => useFailedTransactionsCorrelations(), { wrapper, }); diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_container_metrics_charts.test.ts b/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_container_metrics_charts.test.ts index 392582d4f9eed..e81ad220d4120 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_container_metrics_charts.test.ts +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_container_metrics_charts.test.ts @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { ContainerMetricTypes } from '../charts/types'; import { useK8sContainerPageViewMetricsCharts, @@ -48,10 +49,10 @@ describe('useDockerContainerCharts', () => { async (metric) => { const expectedOrder = getContainerChartsExpectedOrder(metric); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useDockerContainerPageViewMetricsCharts({ metricsDataViewId, metric }) ); - await waitForNextUpdate(); + await waitFor(() => null); const { charts } = result.current; @@ -68,10 +69,10 @@ describe('useDockerContainerCharts', () => { describe('useDockerKPIMetricsCharts', () => { it('should return an array of charts with correct order', async () => { const expectedOrder = ['cpuUsage', 'memoryUsage']; - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useDockerContainerKpiCharts({ dataViewId: metricsDataViewId }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toHaveLength(expectedOrder.length); result.current.forEach((chart, index) => { expect(chart).toHaveProperty('id', expectedOrder[index]); @@ -86,10 +87,10 @@ describe('useK8sContainerCharts', () => { async (metric) => { const expectedOrder = getK8sContainerChartsExpectedOrder(metric); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useK8sContainerPageViewMetricsCharts({ metricsDataViewId, metric }) ); - await waitForNextUpdate(); + await waitFor(() => null); const { charts } = result.current; @@ -106,10 +107,10 @@ describe('useK8sContainerCharts', () => { describe('useK8sContainerKPIMetricsCharts', () => { it('should return an array of charts with correct order', async () => { const expectedOrder = ['k8sCpuUsage', 'k8sMemoryUsage']; - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useK8sContainerKpiCharts({ dataViewId: metricsDataViewId }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toHaveLength(expectedOrder.length); result.current.forEach((chart, index) => { expect(chart).toHaveProperty('id', expectedOrder[index]); diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_host_metrics_charts.test.ts b/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_host_metrics_charts.test.ts index 006fae9bec753..955f0831aa515 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_host_metrics_charts.test.ts +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_host_metrics_charts.test.ts @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { HostMetricTypes } from '../charts/types'; import { useHostKpiCharts, useHostCharts, useKubernetesCharts } from './use_host_metrics_charts'; @@ -40,10 +41,8 @@ describe('useHostCharts', () => { async (metric) => { const expectedOrder = getHostChartsExpectedOrder(metric, false); - const { result, waitForNextUpdate } = renderHook(() => - useHostCharts({ dataViewId, metric }) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useHostCharts({ dataViewId, metric })); + await waitFor(() => null); const { charts } = result.current; @@ -60,10 +59,10 @@ describe('useHostCharts', () => { async (metric) => { const expectedOrder = getHostChartsExpectedOrder(metric, true); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useHostCharts({ dataViewId, metric, overview: true }) ); - await waitForNextUpdate(); + await waitFor(() => null); const { charts } = result.current; @@ -80,10 +79,8 @@ describe('useHostCharts', () => { describe('useKubernetesCharts', () => { it('should return an array of charts with correct order - overview', async () => { - const { result, waitForNextUpdate } = renderHook(() => - useKubernetesCharts({ dataViewId, overview: true }) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useKubernetesCharts({ dataViewId, overview: true })); + await waitFor(() => null); const expectedOrder = ['nodeCpuCapacity', 'nodeMemoryCapacity']; @@ -97,8 +94,8 @@ describe('useKubernetesCharts', () => { }); it('should return an array of charts with correct order', async () => { - const { result, waitForNextUpdate } = renderHook(() => useKubernetesCharts({ dataViewId })); - await waitForNextUpdate(); + const { result } = renderHook(() => useKubernetesCharts({ dataViewId })); + await waitFor(() => null); const expectedOrder = [ 'nodeCpuCapacity', @@ -119,8 +116,8 @@ describe('useKubernetesCharts', () => { describe('useHostKpiCharts', () => { it('should return an array of charts with correct order', async () => { - const { result, waitForNextUpdate } = renderHook(() => useHostKpiCharts({ dataViewId })); - await waitForNextUpdate(); + const { result } = renderHook(() => useHostKpiCharts({ dataViewId })); + await waitFor(() => null); const expectedOrder = ['cpuUsage', 'normalizedLoad1m', 'memoryUsage', 'diskUsage']; @@ -140,10 +137,8 @@ describe('useHostKpiCharts', () => { getSubtitle: () => 'Custom Subtitle', }; - const { result, waitForNextUpdate } = renderHook(() => - useHostKpiCharts({ dataViewId, ...options }) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useHostKpiCharts({ dataViewId, ...options })); + await waitFor(() => null); expect(result.current).toHaveLength(4); diff --git a/x-pack/plugins/observability_solution/infra/public/hooks/use_alerts_count.test.ts b/x-pack/plugins/observability_solution/infra/public/hooks/use_alerts_count.test.ts index 2b2dc755c94c1..03c823914fa0d 100644 --- a/x-pack/plugins/observability_solution/infra/public/hooks/use_alerts_count.test.ts +++ b/x-pack/plugins/observability_solution/infra/public/hooks/use_alerts_count.test.ts @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { ALERT_STATUS, ValidFeatureId } from '@kbn/rule-data-utils'; import { useAlertsCount } from './use_alerts_count'; @@ -66,12 +67,12 @@ describe('useAlertsCount', () => { it('should return the mocked data from API', async () => { mockedPostAPI.mockResolvedValue(mockedAlertsCountResponse); - const { result, waitForNextUpdate } = renderHook(() => useAlertsCount({ featureIds })); + const { result } = renderHook(() => useAlertsCount({ featureIds })); expect(result.current.loading).toBe(true); expect(result.current.alertsCount).toEqual(undefined); - await waitForNextUpdate(); + await waitFor(() => null); const { alertsCount, loading, error } = result.current; expect(alertsCount).toEqual(expectedResult); @@ -88,14 +89,14 @@ describe('useAlertsCount', () => { }; mockedPostAPI.mockResolvedValue(mockedAlertsCountResponse); - const { waitForNextUpdate } = renderHook(() => + renderHook(() => useAlertsCount({ featureIds, query, }) ); - await waitForNextUpdate(); + await waitFor(() => null); const body = JSON.stringify({ aggs: { @@ -118,9 +119,9 @@ describe('useAlertsCount', () => { const error = new Error('Fetch Alerts Count Failed'); mockedPostAPI.mockRejectedValueOnce(error); - const { result, waitForNextUpdate } = renderHook(() => useAlertsCount({ featureIds })); + const { result } = renderHook(() => useAlertsCount({ featureIds })); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.error?.message).toMatch(error.message); }); diff --git a/x-pack/plugins/observability_solution/infra/public/hooks/use_lens_attributes.test.ts b/x-pack/plugins/observability_solution/infra/public/hooks/use_lens_attributes.test.ts index 0a619069c04a4..fab0b187baa61 100644 --- a/x-pack/plugins/observability_solution/infra/public/hooks/use_lens_attributes.test.ts +++ b/x-pack/plugins/observability_solution/infra/public/hooks/use_lens_attributes.test.ts @@ -7,6 +7,7 @@ import 'jest-canvas-mock'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useLensAttributes } from './use_lens_attributes'; import { coreMock } from '@kbn/core/public/mocks'; import { type KibanaReactContextValue, useKibana } from '@kbn/kibana-react-plugin/public'; @@ -72,15 +73,15 @@ describe('useLensAttributes hook', () => { }); it('should return the basic lens attributes', async () => { - const { waitForNextUpdate } = renderHook(() => useLensAttributes(params)); - await waitForNextUpdate(); + renderHook(() => useLensAttributes(params)); + await waitFor(() => null); expect(LensConfigBuilderMock.mock.instances[0].build).toHaveBeenCalledWith(params); }); it('should return extra actions', async () => { - const { result, waitForNextUpdate } = renderHook(() => useLensAttributes(params)); - await waitForNextUpdate(); + const { result } = renderHook(() => useLensAttributes(params)); + await waitFor(() => null); const extraActions = result.current.getExtraActions({ timeRange: { diff --git a/x-pack/plugins/observability_solution/infra/public/pages/link_to/use_host_ip_to_name.test.ts b/x-pack/plugins/observability_solution/infra/public/pages/link_to/use_host_ip_to_name.test.ts index 150416a204b05..41d41c128af5f 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/link_to/use_host_ip_to_name.test.ts +++ b/x-pack/plugins/observability_solution/infra/public/pages/link_to/use_host_ip_to_name.test.ts @@ -7,6 +7,7 @@ import { useHostIpToName } from './use_host_ip_to_name'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; const renderUseHostIpToNameHook = () => renderHook((props) => useHostIpToName(props.ipAddress, props.indexPattern), { @@ -32,10 +33,10 @@ jest.mock('@kbn/kibana-react-plugin/public', () => { describe('useHostIpToName Hook', () => { it('should basically work', async () => { mockedFetch.mockResolvedValue({ host: 'example-01' } as any); - const { result, waitForNextUpdate } = renderUseHostIpToNameHook(); + const { result } = renderUseHostIpToNameHook(); expect(result.current.name).toBe(null); expect(result.current.loading).toBe(true); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.name).toBe('example-01'); expect(result.current.loading).toBe(false); expect(result.current.error).toBe(null); @@ -44,10 +45,10 @@ describe('useHostIpToName Hook', () => { it('should handle errors', async () => { const error = new Error('Host not found'); mockedFetch.mockRejectedValue(error); - const { result, waitForNextUpdate } = renderUseHostIpToNameHook(); + const { result } = renderUseHostIpToNameHook(); expect(result.current.name).toBe(null); expect(result.current.loading).toBe(true); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.name).toBe(null); expect(result.current.loading).toBe(false); expect(result.current.error).toBe(error); @@ -56,16 +57,16 @@ describe('useHostIpToName Hook', () => { it('should reset errors', async () => { const error = new Error('Host not found'); mockedFetch.mockRejectedValue(error); - const { result, waitForNextUpdate, rerender } = renderUseHostIpToNameHook(); + const { result, rerender } = renderUseHostIpToNameHook(); expect(result.current.name).toBe(null); expect(result.current.loading).toBe(true); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.name).toBe(null); expect(result.current.loading).toBe(false); expect(result.current.error).toBe(error); mockedFetch.mockResolvedValue({ host: 'example-01' } as any); rerender({ ipAddress: '192.168.1.2', indexPattern: 'metricbeat-*' }); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.name).toBe('example-01'); expect(result.current.loading).toBe(false); expect(result.current.error).toBe(null); diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_metrics_charts.test.ts b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_metrics_charts.test.ts index b76d5938f0cb5..582d7c772e227 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_metrics_charts.test.ts +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_metrics_charts.test.ts @@ -7,15 +7,14 @@ import type { LensSeriesLayer } from '@kbn/lens-embeddable-utils/config_builder'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { PAGE_SIZE_OPTIONS } from '../constants'; import { useMetricsCharts } from './use_metrics_charts'; describe('useMetricsCharts', () => { it('should return an array of charts with breakdown config', async () => { - const { result, waitForNextUpdate } = renderHook(() => - useMetricsCharts({ dataViewId: 'dataViewId' }) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useMetricsCharts({ dataViewId: 'dataViewId' })); + await waitFor(() => null); expect(result.current).toHaveLength(11); @@ -29,10 +28,8 @@ describe('useMetricsCharts', () => { }); it('should return an array of charts with correct order', async () => { - const { result, waitForNextUpdate } = renderHook(() => - useMetricsCharts({ dataViewId: 'dataViewId' }) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useMetricsCharts({ dataViewId: 'dataViewId' })); + await waitFor(() => null); const expectedOrder = [ 'cpuUsage', diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.test.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.test.tsx index 202ae51990ad2..b14efc3f1bdb1 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.test.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.test.tsx @@ -10,6 +10,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useMetricsExplorerData } from './use_metrics_explorer_data'; import { DataView } from '@kbn/data-views-plugin/common'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor, act } from '@testing-library/react'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { @@ -108,12 +109,12 @@ describe('useMetricsExplorerData Hook', () => { it('should just work', async () => { mockedFetch.mockResolvedValue(resp); - const { result, waitForNextUpdate } = renderUseMetricsExplorerDataHook(); + const { result } = renderUseMetricsExplorerDataHook(); expect(result.current.data).toBeUndefined(); expect(result.current.isLoading).toBe(true); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.data!.pages[0]).toEqual(resp); expect(result.current.isLoading).toBe(false); @@ -124,10 +125,10 @@ describe('useMetricsExplorerData Hook', () => { it('should paginate', async () => { mockedFetch.mockResolvedValue(resp); - const { result, waitForNextUpdate } = renderUseMetricsExplorerDataHook(); + const { result } = renderUseMetricsExplorerDataHook(); expect(result.current.data).toBeUndefined(); expect(result.current.isLoading).toBe(true); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.data!.pages[0]).toEqual(resp); expect(result.current.isLoading).toBe(false); const { series } = result.current.data!.pages[0]; @@ -137,8 +138,10 @@ describe('useMetricsExplorerData Hook', () => { pageInfo: { total: 10, afterKey: 'host-06' }, series: [createSeries('host-04'), createSeries('host-05'), createSeries('host-06')], } as any); - result.current.fetchNextPage(); - await waitForNextUpdate(); + act(() => { + result.current.fetchNextPage(); + }); + await waitFor(() => null); expect(result.current.isLoading).toBe(false); const { series: nextSeries } = result.current.data!.pages[1]; expect(nextSeries).toBeDefined(); @@ -148,17 +151,19 @@ describe('useMetricsExplorerData Hook', () => { it('should reset error upon recovery', async () => { const error = new Error('Network Error'); mockedFetch.mockRejectedValue(error); - const { result, waitForNextUpdate } = renderUseMetricsExplorerDataHook(); + const { result } = renderUseMetricsExplorerDataHook(); expect(result.current.data).toBeUndefined(); expect(result.current.error).toEqual(null); expect(result.current.isLoading).toBe(true); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.data).toBeUndefined(); expect(result.current.error).toEqual(error); expect(result.current.isLoading).toBe(false); mockedFetch.mockResolvedValue(resp as any); - result.current.refetch(); - await waitForNextUpdate(); + act(() => { + result.current.refetch(); + }); + await waitFor(() => null); expect(result.current.data!.pages[0]).toEqual(resp); expect(result.current.isLoading).toBe(false); expect(result.current.error).toBe(null); @@ -166,10 +171,10 @@ describe('useMetricsExplorerData Hook', () => { it('should not paginate on option change', async () => { mockedFetch.mockResolvedValue(resp as any); - const { result, waitForNextUpdate, rerender } = renderUseMetricsExplorerDataHook(); + const { result, rerender } = renderUseMetricsExplorerDataHook(); expect(result.current.data).toBeUndefined(); expect(result.current.isLoading).toBe(true); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.data!.pages[0]).toEqual(resp); expect(result.current.isLoading).toBe(false); const { series } = result.current.data!.pages[0]; @@ -187,17 +192,17 @@ describe('useMetricsExplorerData Hook', () => { timestamps, }); expect(result.current.isLoading).toBe(true); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.data!.pages[0]).toEqual(resp); expect(result.current.isLoading).toBe(false); }); it('should not paginate on time change', async () => { mockedFetch.mockResolvedValue(resp as any); - const { result, waitForNextUpdate, rerender } = renderUseMetricsExplorerDataHook(); + const { result, rerender } = renderUseMetricsExplorerDataHook(); expect(result.current.data).toBeUndefined(); expect(result.current.isLoading).toBe(true); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.data!.pages[0]).toEqual(resp); expect(result.current.isLoading).toBe(false); const { series } = result.current.data!.pages[0]; @@ -211,7 +216,7 @@ describe('useMetricsExplorerData Hook', () => { timestamps: { fromTimestamp: 1678378092225, toTimestamp: 1678381693477, interval: '>=10s' }, }); expect(result.current.isLoading).toBe(true); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.data!.pages[0]).toEqual(resp); expect(result.current.isLoading).toBe(false); }); diff --git a/x-pack/plugins/observability_solution/logs_shared/public/containers/logs/log_summary/log_summary.test.tsx b/x-pack/plugins/observability_solution/logs_shared/public/containers/logs/log_summary/log_summary.test.tsx index 183950edf9777..c2ec82dda0b2d 100644 --- a/x-pack/plugins/observability_solution/logs_shared/public/containers/logs/log_summary/log_summary.test.tsx +++ b/x-pack/plugins/observability_solution/logs_shared/public/containers/logs/log_summary/log_summary.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; // We are using this inside a `jest.mock` call. Jest requires dynamic dependencies to be prefixed with `mock` import { coreMock as mockCoreMock } from '@kbn/core/public/mocks'; @@ -56,14 +57,14 @@ describe('useLogSummary hook', () => { .mockResolvedValueOnce(firstMockResponse) .mockResolvedValueOnce(secondMockResponse); - const { result, waitForNextUpdate, rerender } = renderHook( + const { result, rerender } = renderHook( ({ logViewReference }) => useLogSummary(logViewReference, startTimestamp, endTimestamp, null), { initialProps: { logViewReference: LOG_VIEW_REFERENCE }, } ); - await waitForNextUpdate(); + await waitFor(() => null); expect(fetchLogSummaryMock).toHaveBeenCalledTimes(1); expect(fetchLogSummaryMock).toHaveBeenLastCalledWith( @@ -75,7 +76,7 @@ describe('useLogSummary hook', () => { expect(result.current.buckets).toEqual(firstMockResponse.data.buckets); rerender({ logViewReference: CHANGED_LOG_VIEW_REFERENCE }); - await waitForNextUpdate(); + await waitFor(() => null); expect(fetchLogSummaryMock).toHaveBeenCalledTimes(2); expect(fetchLogSummaryMock).toHaveBeenLastCalledWith( @@ -101,7 +102,7 @@ describe('useLogSummary hook', () => { .mockResolvedValueOnce(firstMockResponse) .mockResolvedValueOnce(secondMockResponse); - const { result, waitForNextUpdate, rerender } = renderHook( + const { result, rerender } = renderHook( ({ filterQuery }) => useLogSummary(LOG_VIEW_REFERENCE, startTimestamp, endTimestamp, filterQuery), { @@ -109,7 +110,7 @@ describe('useLogSummary hook', () => { } ); - await waitForNextUpdate(); + await waitFor(() => null); expect(fetchLogSummaryMock).toHaveBeenCalledTimes(1); expect(fetchLogSummaryMock).toHaveBeenLastCalledWith( @@ -121,7 +122,7 @@ describe('useLogSummary hook', () => { expect(result.current.buckets).toEqual(firstMockResponse.data.buckets); rerender({ filterQuery: 'CHANGED_FILTER_QUERY' }); - await waitForNextUpdate(); + await waitFor(() => null); expect(fetchLogSummaryMock).toHaveBeenCalledTimes(2); expect(fetchLogSummaryMock).toHaveBeenLastCalledWith( @@ -139,7 +140,7 @@ describe('useLogSummary hook', () => { .mockResolvedValueOnce(createMockResponse([])); const firstRange = createMockDateRange(); - const { waitForNextUpdate, rerender } = renderHook( + const { rerender } = renderHook( ({ startTimestamp, endTimestamp }) => useLogSummary(LOG_VIEW_REFERENCE, startTimestamp, endTimestamp, null), { @@ -147,7 +148,7 @@ describe('useLogSummary hook', () => { } ); - await waitForNextUpdate(); + await waitFor(() => null); expect(fetchLogSummaryMock).toHaveBeenCalledTimes(1); expect(fetchLogSummaryMock).toHaveBeenLastCalledWith( expect.objectContaining({ @@ -160,7 +161,7 @@ describe('useLogSummary hook', () => { const secondRange = createMockDateRange('now-20s', 'now'); rerender(secondRange); - await waitForNextUpdate(); + await waitFor(() => null); expect(fetchLogSummaryMock).toHaveBeenCalledTimes(2); expect(fetchLogSummaryMock).toHaveBeenLastCalledWith( @@ -176,7 +177,7 @@ describe('useLogSummary hook', () => { fetchLogSummaryMock.mockResolvedValueOnce(createMockResponse([])); const firstRange = createMockDateRange(); - const { waitForNextUpdate, rerender } = renderHook( + const { rerender } = renderHook( ({ startTimestamp, endTimestamp }) => useLogSummary(LOG_VIEW_REFERENCE, startTimestamp, endTimestamp, null), { @@ -188,7 +189,7 @@ describe('useLogSummary hook', () => { // intentionally don't wait for an update to test the throttling rerender(secondRange); - await waitForNextUpdate(); + await waitFor(() => null); expect(fetchLogSummaryMock).toHaveBeenCalledTimes(1); expect(fetchLogSummaryMock).toHaveBeenLastCalledWith( 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..f43d7d28edd7e 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 @@ -7,6 +7,7 @@ import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } 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,7 +17,6 @@ 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; @@ -58,7 +58,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,9 +66,8 @@ describe('HasDataContextProvider', () => { forceUpdate: expect.any(String), onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); + + await waitFor(() => null); expect(result.current).toEqual({ hasDataMap: { @@ -112,7 +111,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,9 +123,7 @@ describe('HasDataContextProvider', () => { onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); + await waitFor(() => null); expect(result.current).toEqual({ hasDataMap: { @@ -178,7 +175,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,9 +184,7 @@ describe('HasDataContextProvider', () => { onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); + await waitFor(() => null); expect(result.current).toEqual({ hasDataMap: { @@ -243,7 +238,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,9 +247,7 @@ describe('HasDataContextProvider', () => { onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); + await waitFor(() => null); expect(result.current).toEqual({ hasDataMap: { @@ -297,7 +290,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,9 +301,7 @@ describe('HasDataContextProvider', () => { onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); + await waitFor(() => null); expect(result.current).toEqual({ hasDataMap: { @@ -343,7 +334,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,9 +345,7 @@ describe('HasDataContextProvider', () => { onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); + await waitFor(() => null); expect(result.current).toEqual({ hasDataMap: { @@ -412,7 +401,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,9 +410,7 @@ describe('HasDataContextProvider', () => { onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); + await waitFor(() => null); expect(result.current).toEqual({ hasDataMap: { @@ -491,7 +478,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,9 +487,7 @@ describe('HasDataContextProvider', () => { onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); + await waitFor(() => null); expect(result.current).toEqual({ hasDataMap: { @@ -538,7 +523,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,9 +532,7 @@ describe('HasDataContextProvider', () => { onRefreshTimeRange: expect.any(Function), }); - await act(async () => { - await waitForNextUpdate(); - }); + await waitFor(() => null); expect(result.current).toEqual({ hasDataMap: { 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..08a20b1bb4813 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,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { kibanaStartMock } from '../utils/kibana_react.mock'; import { useFetchAlertData } from './use_fetch_alert_data'; @@ -41,11 +42,11 @@ describe('useFetchAlertData', () => { it('initially is not loading and does not have data', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook]>( - () => useFetchAlertData(testIds) + const { result } = renderHook]>(() => + useFetchAlertData(testIds) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual([false, {}]); }); @@ -57,11 +58,11 @@ describe('useFetchAlertData', () => { }); await act(async () => { - const { result, waitForNextUpdate } = renderHook]>( - () => useFetchAlertData(testIds) + const { result } = renderHook]>(() => + useFetchAlertData(testIds) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual([false, {}]); }); @@ -69,12 +70,12 @@ describe('useFetchAlertData', () => { it('retrieves the alert data', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook]>( - () => useFetchAlertData(testIds) + const { result } = renderHook]>(() => + useFetchAlertData(testIds) ); - await waitForNextUpdate(); - await waitForNextUpdate(); + await waitFor(() => null); + await waitFor(() => null); expect(result.current).toEqual([ false, @@ -85,12 +86,11 @@ describe('useFetchAlertData', () => { 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(); + await waitFor(() => null); unmount(); expect(result.current).toEqual([false, {}]); 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..8f65f8d22ef15 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,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { kibanaStartMock } from '../utils/kibana_react.mock'; import * as pluginContext from './use_plugin_context'; import { createObservabilityRuleTypeRegistryMock } from '..'; @@ -64,15 +65,11 @@ describe('useFetchAlertDetail', () => { }); it('initially is not loading and does not have data', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useFetchAlertDetail(id) - ); - - await waitForNextUpdate(); + const { result } = renderHook(() => + useFetchAlertDetail(id) + ); - expect(result.current).toEqual([false, null]); - }); + expect(result.current).toEqual([true, null]); }); it('returns no data when an error occurs', async () => { @@ -80,73 +77,37 @@ describe('useFetchAlertDetail', () => { throw new Error('an http error'); }); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useFetchAlertDetail('123') - ); + const { result } = renderHook(() => + useFetchAlertDetail('123') + ); - await waitForNextUpdate(); + await waitFor(() => null); - expect(result.current).toEqual([false, null]); - }); + 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(); - - expect(result.current).toMatchInlineSnapshot(` - Array [ - false, - Object { - "formatted": Object { - "0": "a", - "1": " ", - "2": "r", - "3": "e", - "4": "a", - "5": "s", - "6": "o", - "7": "n", - "active": true, - "fields": Object { - "@timestamp": "2022-01-31T18:20:57.204Z", - "_index": "alert-index", - "event.action": "active", - "event.kind": "signal", - "kibana.alert.duration.us": 13793555000, - "kibana.alert.instance.id": "*", - "kibana.alert.reason": "Document count reported no data in the last 1 hour for all hosts", - "kibana.alert.rule.category": "Metric threshold", - "kibana.alert.rule.consumer": "infrastructure", - "kibana.alert.rule.execution.uuid": "e62c418d-734d-47e7-bbeb-e6f182f5fb45", - "kibana.alert.rule.name": "A super rule", - "kibana.alert.rule.producer": "infrastructure", - "kibana.alert.rule.revision": 0, - "kibana.alert.rule.rule_type_id": "metrics.alert.threshold", - "kibana.alert.rule.tags": Array [], - "kibana.alert.rule.uuid": "69411af0-82a2-11ec-8139-c1568734434e", - "kibana.alert.start": "2022-01-31T14:31:03.649Z", - "kibana.alert.status": "active", - "kibana.alert.uuid": "73c0d0cd-2df4-4550-862c-1d447e9c1db2", - "kibana.alert.workflow_status": "open", - "kibana.space_ids": Array [ - "default", - ], - "kibana.version": "8.1.0", - "tags": Array [], - }, - "lastUpdated": 1643653257204, - "link": undefined, - "reason": "Document count reported no data in the last 1 hour for all hosts", - "start": 1643639463649, - }, - "raw": Object { + const { result } = renderHook(() => + useFetchAlertDetail(id) + ); + + await waitFor(() => null); + + expect(result.current).toMatchInlineSnapshot(` + Array [ + false, + Object { + "formatted": Object { + "0": "a", + "1": " ", + "2": "r", + "3": "e", + "4": "a", + "5": "s", + "6": "o", + "7": "n", + "active": true, + "fields": Object { "@timestamp": "2022-01-31T18:20:57.204Z", "_index": "alert-index", "event.action": "active", @@ -173,23 +134,56 @@ describe('useFetchAlertDetail', () => { "kibana.version": "8.1.0", "tags": Array [], }, + "lastUpdated": 1643653257204, + "link": undefined, + "reason": "Document count reported no data in the last 1 hour for all hosts", + "start": 1643639463649, }, - ] - `); - }); + "raw": Object { + "@timestamp": "2022-01-31T18:20:57.204Z", + "_index": "alert-index", + "event.action": "active", + "event.kind": "signal", + "kibana.alert.duration.us": 13793555000, + "kibana.alert.instance.id": "*", + "kibana.alert.reason": "Document count reported no data in the last 1 hour for all hosts", + "kibana.alert.rule.category": "Metric threshold", + "kibana.alert.rule.consumer": "infrastructure", + "kibana.alert.rule.execution.uuid": "e62c418d-734d-47e7-bbeb-e6f182f5fb45", + "kibana.alert.rule.name": "A super rule", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.revision": 0, + "kibana.alert.rule.rule_type_id": "metrics.alert.threshold", + "kibana.alert.rule.tags": Array [], + "kibana.alert.rule.uuid": "69411af0-82a2-11ec-8139-c1568734434e", + "kibana.alert.start": "2022-01-31T14:31:03.649Z", + "kibana.alert.status": "active", + "kibana.alert.uuid": "73c0d0cd-2df4-4550-862c-1d447e9c1db2", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": Array [ + "default", + ], + "kibana.version": "8.1.0", + "tags": Array [], + }, + }, + ] + `); }); 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')); + // FIXME: this test cases doesn't do what the suite claims it does - await waitForNextUpdate(); - unmount(); + const { result, unmount } = renderHook(() => + useFetchAlertDetail('123') + ); - expect(result.current).toEqual([false, null]); + await waitFor(() => null); + + act(() => { + unmount(); }); + + expect(result.current).toEqual([false, 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..a4cac9612daa7 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,8 @@ */ import { useFetchBulkCases } from './use_fetch_bulk_cases'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { kibanaStartMock } from '../utils/kibana_react.mock'; const mockUseKibanaReturnValue = kibanaStartMock.startContract(); @@ -19,9 +20,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: [] })); + const { result } = renderHook(() => useFetchBulkCases({ ids: [] })); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.cases).toEqual([]); expect(result.current.error).toEqual(undefined); 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..b290057e32426 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 @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useGetIlmPolicies } from './use_get_ilm_policies'; import * as hookPolicyAPI from './api'; @@ -23,8 +24,8 @@ describe('useGetIlmPolicies', () => { }); it('returns the correct data', async () => { - const { result, waitForNextUpdate } = renderHook(() => useGetIlmPolicies()); - await waitForNextUpdate(); + const { result } = renderHook(() => useGetIlmPolicies()); + await waitFor(() => 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_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..1c23fdaaba200 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 @@ -6,6 +6,7 @@ */ import { renderHook, act } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { WrappedHelper } from '../../../../utils/testing'; import { getServiceLocations } from '../../../../state/service_locations'; import { setAddingNewPrivateLocation } from '../../../../state/private_locations'; @@ -42,7 +43,7 @@ describe('usePrivateLocationsAPI', () => { } as any, ]); it('returns expected results after data', async () => { - const { result, waitForNextUpdate } = renderHook(() => usePrivateLocationsAPI(), { + const { result } = renderHook(() => usePrivateLocationsAPI(), { wrapper: WrappedHelper, }); @@ -53,7 +54,7 @@ describe('usePrivateLocationsAPI', () => { }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual( expect.objectContaining({ @@ -64,11 +65,11 @@ describe('usePrivateLocationsAPI', () => { }); it('adds location on submit', async () => { - const { result, waitForNextUpdate } = renderHook(() => usePrivateLocationsAPI(), { + const { result } = renderHook(() => usePrivateLocationsAPI(), { wrapper: WrappedHelper, }); - await waitForNextUpdate(); + await waitFor(() => null); act(() => { result.current.onSubmit({ @@ -81,7 +82,7 @@ describe('usePrivateLocationsAPI', () => { }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(addAPI).toHaveBeenCalledWith({ geo: { @@ -96,17 +97,17 @@ describe('usePrivateLocationsAPI', () => { }); it('deletes location on delete', async () => { - const { result, waitForNextUpdate } = renderHook(() => usePrivateLocationsAPI(), { + const { result } = renderHook(() => usePrivateLocationsAPI(), { wrapper: WrappedHelper, }); - await waitForNextUpdate(); + await waitFor(() => null); act(() => { result.current.onDelete('Test'); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(deletedAPI).toHaveBeenLastCalledWith('Test'); expect(dispatch).toBeCalledWith(setAddingNewPrivateLocation(false)); diff --git a/x-pack/plugins/search_playground/public/hooks/use_load_connectors.test.ts b/x-pack/plugins/search_playground/public/hooks/use_load_connectors.test.ts index eb2f36eb62e5f..54b5a160b8761 100644 --- a/x-pack/plugins/search_playground/public/hooks/use_load_connectors.test.ts +++ b/x-pack/plugins/search_playground/public/hooks/use_load_connectors.test.ts @@ -8,7 +8,8 @@ import { loadAllActions as loadConnectors } from '@kbn/triggers-actions-ui-plugin/public/common/constants'; import { useLoadConnectors } from './use_load_connectors'; import { useKibana } from './use_kibana'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/common/openai/constants'; const mockedLoadConnectors = loadConnectors as jest.Mock; @@ -80,11 +81,9 @@ describe('useLoadConnectors', () => { ]; mockedLoadConnectors.mockResolvedValue(connectors); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useLoadConnectors()); - await waitForNextUpdate(); - - await expect(result.current).resolves.toStrictEqual([ + const { result } = renderHook(() => useLoadConnectors()); + await waitFor(() => + expect(result.current).resolves.toStrictEqual([ { actionTypeId: '.gen-ai', config: { @@ -122,8 +121,8 @@ describe('useLoadConnectors', () => { title: 'OpenAI Other', type: 'openai_other', }, - ]); - }); + ]) + ); }); it('handles pre-configured connectors', async () => { @@ -149,11 +148,9 @@ describe('useLoadConnectors', () => { ]; mockedLoadConnectors.mockResolvedValue(connectors); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useLoadConnectors()); - await waitForNextUpdate(); - - await expect(result.current).resolves.toStrictEqual([ + const { result } = renderHook(() => useLoadConnectors()); + await waitFor(() => + expect(result.current).resolves.toStrictEqual([ { actionTypeId: '.gen-ai', id: '1', @@ -171,22 +168,20 @@ describe('useLoadConnectors', () => { title: 'OpenAI Azure', type: 'openai_azure', }, - ]); - }); + ]) + ); }); it('handles errors correctly', async () => { const error = new Error('Test Error'); mockedLoadConnectors.mockRejectedValue(error); - await act(async () => { - const { waitForNextUpdate } = renderHook(() => useLoadConnectors()); - await waitForNextUpdate(); - + renderHook(() => useLoadConnectors()); + await waitFor(() => expect(mockedUseKibana().services.notifications.toasts.addError).toHaveBeenCalledWith( error, expect.any(Object) - ); - }); + ) + ); }); }); diff --git a/x-pack/plugins/search_playground/public/hooks/use_management_link.test.ts b/x-pack/plugins/search_playground/public/hooks/use_management_link.test.ts index ed566bbaee9f5..5e5b4782ed8ec 100644 --- a/x-pack/plugins/search_playground/public/hooks/use_management_link.test.ts +++ b/x-pack/plugins/search_playground/public/hooks/use_management_link.test.ts @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useManagementLink } from './use_management_link'; import { useKibana } from './use_kibana'; @@ -41,8 +42,8 @@ describe('useManagementLink Hook', () => { 'http://localhost:5601/app/management/insightsAndAlerting/triggersActionsConnectors'; mockGetUrl.mockResolvedValue(expectedUrl); const connectorId = 'test-connector-id'; - const { result, waitForNextUpdate } = renderHook(() => useManagementLink(connectorId)); - await waitForNextUpdate(); + const { result } = renderHook(() => useManagementLink(connectorId)); + await waitFor(() => null); expect(result.current).toBe(expectedUrl); expect(mockGetUrl).toHaveBeenCalledWith({ diff --git a/x-pack/plugins/search_playground/public/hooks/use_source_indices_fields.test.tsx b/x-pack/plugins/search_playground/public/hooks/use_source_indices_fields.test.tsx index b31512177d3cb..949220c394145 100644 --- a/x-pack/plugins/search_playground/public/hooks/use_source_indices_fields.test.tsx +++ b/x-pack/plugins/search_playground/public/hooks/use_source_indices_fields.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useKibana } from './use_kibana'; import { PlaygroundProvider } from '../providers/playground_provider'; import React from 'react'; @@ -76,7 +77,7 @@ describe.skip('useSourceIndicesFields Hook', () => { }); it('should handle addIndex correctly changing indices', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSourceIndicesFields(), { wrapper }); + const { result } = renderHook(() => useSourceIndicesFields(), { wrapper }); const { getValues } = formHookSpy.mock.results[0].value; act(() => { @@ -103,10 +104,8 @@ describe.skip('useSourceIndicesFields Hook', () => { result.current.addIndex('newIndex'); }); - await act(async () => { - await waitForNextUpdate(); - expect(result.current.indices).toEqual(['newIndex']); - }); + await waitFor(() => null); + expect(result.current.indices).toEqual(['newIndex']); expect(postMock).toHaveBeenCalled(); diff --git a/x-pack/plugins/security_solution/public/assistant/get_comments/stream/use_stream.test.tsx b/x-pack/plugins/security_solution/public/assistant/get_comments/stream/use_stream.test.tsx index 9aa3491218f88..b9a55ed511e9d 100644 --- a/x-pack/plugins/security_solution/public/assistant/get_comments/stream/use_stream.test.tsx +++ b/x-pack/plugins/security_solution/public/assistant/get_comments/stream/use_stream.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useStream } from './use_stream'; const refetchCurrentConversation = jest.fn(); @@ -49,7 +50,7 @@ describe.skip('useStream', () => { }); it('Should stream response. isLoading/isStreaming are true while streaming, isLoading/isStreaming are false when streaming completes', async () => { - const { result, waitFor } = renderHook(() => useStream(defaultProps)); + const { result } = renderHook(() => useStream(defaultProps)); expect(reader).toHaveBeenCalledTimes(1); await waitFor(() => { expect(result.current).toEqual({ @@ -107,7 +108,7 @@ describe.skip('useStream', () => { releaseLock: jest.fn(), closed: jest.fn().mockResolvedValue(true), } as unknown as ReadableStreamDefaultReader; - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useStream({ ...defaultProps, reader: errorReader, @@ -115,7 +116,7 @@ describe.skip('useStream', () => { ); expect(result.current.error).toBeUndefined(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.error).toBe(errorMessage); expect(result.current.isLoading).toBe(false); diff --git a/x-pack/plugins/security_solution/public/assistant/provider.test.tsx b/x-pack/plugins/security_solution/public/assistant/provider.test.tsx index a96623b8567a8..15f1f87f21f3a 100644 --- a/x-pack/plugins/security_solution/public/assistant/provider.test.tsx +++ b/x-pack/plugins/security_solution/public/assistant/provider.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { httpServiceMock, type HttpSetupMock } from '@kbn/core-http-browser-mocks'; import type { Storage } from '@kbn/kibana-utils-plugin/public'; import { createConversations } from './provider'; @@ -166,47 +167,43 @@ describe('createConversations', () => { }); it('should call bulk conversations with the transformed conversations from the local storage', async () => { - await act(async () => { - const { waitForNextUpdate } = renderHook(() => - createConversations( - coreMock.createStart().notifications, - http, - mockStorage as unknown as Storage - ) - ); - await waitForNextUpdate(); - expect(http.fetch.mock.calls[0][0]).toBe( - '/internal/elastic_assistant/current_user/conversations/_bulk_action' - ); - expect( - http.fetch.mock.calls[0].length > 1 - ? // eslint-disable-next-line @typescript-eslint/no-explicit-any - JSON.parse((http.fetch.mock.calls[0] as any[])[1]?.body).create.length - : 0 - ).toBe(2); - }); + renderHook(() => + createConversations( + coreMock.createStart().notifications, + http, + mockStorage as unknown as Storage + ) + ); + await waitFor(() => null); + expect(http.fetch.mock.calls[0][0]).toBe( + '/internal/elastic_assistant/current_user/conversations/_bulk_action' + ); + expect( + http.fetch.mock.calls[0].length > 1 + ? // eslint-disable-next-line @typescript-eslint/no-explicit-any + JSON.parse((http.fetch.mock.calls[0] as any[])[1]?.body).create.length + : 0 + ).toBe(2); }); it('should add missing actionTypeId to apiConfig', async () => { - await act(async () => { - const { waitForNextUpdate } = renderHook(() => - createConversations( - coreMock.createStart().notifications, - http, - mockStorage as unknown as Storage - ) - ); - await waitForNextUpdate(); - expect(http.fetch.mock.calls[0][0]).toBe( - '/internal/elastic_assistant/current_user/conversations/_bulk_action' - ); - const createdConversations = - http.fetch.mock.calls[0].length > 1 - ? // eslint-disable-next-line @typescript-eslint/no-explicit-any - JSON.parse((http.fetch.mock.calls[0] as any[])[1]?.body)?.create - : []; - expect(createdConversations[0].apiConfig.actionTypeId).toEqual('.bedrock'); - expect(createdConversations[1].apiConfig.actionTypeId).toEqual('.gen-ai'); - }); + renderHook(() => + createConversations( + coreMock.createStart().notifications, + http, + mockStorage as unknown as Storage + ) + ); + await waitFor(() => null); + expect(http.fetch.mock.calls[0][0]).toBe( + '/internal/elastic_assistant/current_user/conversations/_bulk_action' + ); + const createdConversations = + http.fetch.mock.calls[0].length > 1 + ? // eslint-disable-next-line @typescript-eslint/no-explicit-any + JSON.parse((http.fetch.mock.calls[0] as any[])[1]?.body)?.create + : []; + expect(createdConversations[0].apiConfig.actionTypeId).toEqual('.bedrock'); + expect(createdConversations[1].apiConfig.actionTypeId).toEqual('.gen-ai'); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/guided_onboarding_tour/tour.test.tsx b/x-pack/plugins/security_solution/public/common/components/guided_onboarding_tour/tour.test.tsx index cb99772343c7b..c9e7c667ddd73 100644 --- a/x-pack/plugins/security_solution/public/common/components/guided_onboarding_tour/tour.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/guided_onboarding_tour/tour.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor, act } from '@testing-library/react'; import { of } from 'rxjs'; import { siemGuideId } from '../../../../common/guided_onboarding/siem_guide_config'; import { TourContextProvider, useTourContext } from './tour'; @@ -67,10 +68,10 @@ describe('useTourContext', () => { }); it('endTourStep calls completeGuideStep with correct tourId', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useTourContext(), { + const { result } = renderHook(() => useTourContext(), { wrapper: TourContextProvider, }); - await waitForNextUpdate(); + await waitFor(() => null); result.current.endTourStep(tourId); expect(mockCompleteGuideStep).toHaveBeenCalledWith(siemGuideId, tourId); }); @@ -83,10 +84,10 @@ describe('useTourContext', () => { }); it('incrementStep properly increments for each tourId, and if attempted to increment beyond length of tour config steps resets activeStep to 1', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useTourContext(), { + const { result } = renderHook(() => useTourContext(), { wrapper: TourContextProvider, }); - await waitForNextUpdate(); + await waitFor(() => null); const stepCount = securityTourConfig[tourId].length; for (let i = 0; i < stepCount - 1; i++) { result.current.incrementStep(tourId); @@ -100,10 +101,10 @@ describe('useTourContext', () => { it('setStep sets activeStep to step number argument', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useTourContext(), { + const { result } = renderHook(() => useTourContext(), { wrapper: TourContextProvider, }); - await waitForNextUpdate(); + await waitFor(() => null); result.current.setStep(tourId, 7); expect(result.current.activeStep).toBe(7); }); @@ -111,10 +112,10 @@ describe('useTourContext', () => { it('does not setStep sets activeStep to non-existing step number', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useTourContext(), { + const { result } = renderHook(() => useTourContext(), { wrapper: TourContextProvider, }); - await waitForNextUpdate(); + await waitFor(() => null); // @ts-expect-error testing invalid step result.current.setStep(tourId, 88); expect(result.current.activeStep).toBe(1); diff --git a/x-pack/plugins/security_solution/public/common/components/ml/anomaly/use_anomalies_search.test.ts b/x-pack/plugins/security_solution/public/common/components/ml/anomaly/use_anomalies_search.test.ts index 4c828e918b187..d60ab5f35a383 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/anomaly/use_anomalies_search.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/ml/anomaly/use_anomalies_search.test.ts @@ -4,7 +4,9 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; + +import { act, waitFor } from '@testing-library/react'; import { TestProviders } from '../../../mock'; import { useAggregatedAnomaliesByJob, AnomalyEntity } from './use_anomalies_search'; @@ -70,16 +72,13 @@ describe('useAggregatedAnomaliesByJob', () => { }); it('refetch calls useSecurityJobs().refetch', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook( - () => useAggregatedAnomaliesByJob({ skip: false, from, to }), - { - wrapper: TestProviders, - } - ); + const { result } = renderHook(() => useAggregatedAnomaliesByJob({ skip: false, from, to }), { + wrapper: TestProviders, + }); - await waitForNextUpdate(); + await waitFor(() => null); + act(() => { result.current.refetch(); }); @@ -87,98 +86,82 @@ describe('useAggregatedAnomaliesByJob', () => { }); it('returns formated data', async () => { - await act(async () => { - const jobCount = { key: jobId, doc_count: 99 }; - mockAnomaliesSearch.mockResolvedValue({ - aggregations: { number_of_anomalies: { buckets: [jobCount] } }, - }); - const { result, waitForNextUpdate } = renderHook( - () => useAggregatedAnomaliesByJob({ skip: false, from, to }), - { - wrapper: TestProviders, - } - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - - expect(result.current.data).toEqual( - expect.arrayContaining([ - { - count: 99, - name: jobId, - job, - entity: AnomalyEntity.Host, - }, - ]) - ); + const jobCount = { key: jobId, doc_count: 99 }; + mockAnomaliesSearch.mockResolvedValue({ + aggregations: { number_of_anomalies: { buckets: [jobCount] } }, + }); + const { result } = renderHook(() => useAggregatedAnomaliesByJob({ skip: false, from, to }), { + wrapper: TestProviders, }); - }); - it('returns jobs sorted by name', async () => { - await act(async () => { - const firstJobId = 'v3_windows_anomalous_script'; - const secondJobId = 'auth_rare_source_ip_for_a_user'; - const fistJobCount = { key: firstJobId, doc_count: 99 }; - const secondJobCount = { key: secondJobId, doc_count: 99 }; - const firstJobSecurityName = '0000001'; - const secondJobSecurityName = '0000002'; - const firstJob = { - id: firstJobId, - jobState: 'started', - datafeedState: 'started', - customSettings: { - security_app_display_name: firstJobSecurityName, - }, - }; - const secondJob = { - id: secondJobId, - jobState: 'started', - datafeedState: 'started', - customSettings: { - security_app_display_name: secondJobSecurityName, + await waitFor(() => null); + + expect(result.current.data).toEqual( + expect.arrayContaining([ + { + count: 99, + name: jobId, + job, + entity: AnomalyEntity.Host, }, - }; + ]) + ); + }); - mockAnomaliesSearch.mockResolvedValue({ - aggregations: { number_of_anomalies: { buckets: [fistJobCount, secondJobCount] } }, - }); + it('returns jobs sorted by name', async () => { + const firstJobId = 'v3_windows_anomalous_script'; + const secondJobId = 'auth_rare_source_ip_for_a_user'; + const fistJobCount = { key: firstJobId, doc_count: 99 }; + const secondJobCount = { key: secondJobId, doc_count: 99 }; + const firstJobSecurityName = '0000001'; + const secondJobSecurityName = '0000002'; + const firstJob = { + id: firstJobId, + jobState: 'started', + datafeedState: 'started', + customSettings: { + security_app_display_name: firstJobSecurityName, + }, + }; + const secondJob = { + id: secondJobId, + jobState: 'started', + datafeedState: 'started', + customSettings: { + security_app_display_name: secondJobSecurityName, + }, + }; + + mockAnomaliesSearch.mockResolvedValue({ + aggregations: { number_of_anomalies: { buckets: [fistJobCount, secondJobCount] } }, + }); - mockUseSecurityJobs.mockReturnValue({ - loading: false, - isMlAdmin: true, - jobs: [firstJob, secondJob], - refetch: useSecurityJobsRefetch, - }); + mockUseSecurityJobs.mockReturnValue({ + loading: false, + isMlAdmin: true, + jobs: [firstJob, secondJob], + refetch: useSecurityJobsRefetch, + }); - const { result, waitForNextUpdate } = renderHook( - () => useAggregatedAnomaliesByJob({ skip: false, from, to }), - { - wrapper: TestProviders, - } - ); - await waitForNextUpdate(); - await waitForNextUpdate(); + const { result } = renderHook(() => useAggregatedAnomaliesByJob({ skip: false, from, to }), { + wrapper: TestProviders, + }); + await waitFor(() => null); - const names = result.current.data.map(({ name }) => name); + const names = result.current.data.map(({ name }) => name); - expect(names[0]).toEqual(firstJobSecurityName); - expect(names[1]).toEqual(secondJobSecurityName); - }); + expect(names[0]).toEqual(firstJobSecurityName); + expect(names[1]).toEqual(secondJobSecurityName); }); it('does not throw error when aggregations is undefined', async () => { - await act(async () => { - mockAnomaliesSearch.mockResolvedValue({}); - const { waitForNextUpdate } = renderHook( - () => useAggregatedAnomaliesByJob({ skip: false, from, to }), - { - wrapper: TestProviders, - } - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - - expect(mockAddToastError).not.toBeCalled(); + mockAnomaliesSearch.mockResolvedValue({}); + renderHook(() => useAggregatedAnomaliesByJob({ skip: false, from, to }), { + wrapper: TestProviders, }); + + await waitFor(() => null); + + expect(mockAddToastError).not.toBeCalled(); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/ml/hooks/use_installed_security_jobs.test.ts b/x-pack/plugins/security_solution/public/common/components/ml/hooks/use_installed_security_jobs.test.ts index 0ee5217babb1d..7e0643139158a 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/hooks/use_installed_security_jobs.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/ml/hooks/use_installed_security_jobs.test.ts @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { hasMlUserPermissions } from '../../../../../common/machine_learning/has_ml_user_permissions'; import { hasMlLicense } from '../../../../../common/machine_learning/has_ml_license'; @@ -38,10 +39,11 @@ describe('useInstalledSecurityJobs', () => { }); it('returns jobs and permissions', async () => { - const { result, waitForNextUpdate } = renderHook(() => useInstalledSecurityJobs(), { + const { result } = renderHook(() => useInstalledSecurityJobs(), { wrapper: TestProviders, }); - await waitForNextUpdate(); + + await waitFor(() => null); expect(result.current.jobs).toHaveLength(3); expect(result.current.jobs).toEqual( @@ -71,10 +73,10 @@ describe('useInstalledSecurityJobs', () => { }); it('filters out non-security jobs', async () => { - const { result, waitForNextUpdate } = renderHook(() => useInstalledSecurityJobs(), { + const { result } = renderHook(() => useInstalledSecurityJobs(), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.jobs.length).toBeGreaterThan(0); expect(result.current.jobs.every(isSecurityJob)).toEqual(true); @@ -82,10 +84,12 @@ describe('useInstalledSecurityJobs', () => { it('renders a toast error if the ML call fails', async () => { (getJobsSummary as jest.Mock).mockRejectedValue('whoops'); - const { waitForNextUpdate } = renderHook(() => useInstalledSecurityJobs(), { + + renderHook(() => useInstalledSecurityJobs(), { wrapper: TestProviders, }); - await waitForNextUpdate(); + + await waitFor(() => null); expect(appToastsMock.addError).toHaveBeenCalledWith('whoops', { title: 'Security job fetch failure', diff --git a/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_enable_data_feed.test.tsx b/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_enable_data_feed.test.tsx index 0801ec37f6ae6..172be61d587fb 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_enable_data_feed.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_enable_data_feed.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ import React from 'react'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useEnableDataFeed } from './use_enable_data_feed'; import { TestProviders } from '../../../mock'; @@ -78,21 +79,19 @@ describe('useSecurityJobsHelpers', () => { resolvePromiseCb = resolve; }) ); - const { result, waitForNextUpdate } = renderHook(() => useEnableDataFeed(), { + const { result } = renderHook(() => useEnableDataFeed(), { wrapper, }); expect(result.current.isLoading).toBe(false); await act(async () => { const enableDataFeedPromise = result.current.enableDatafeed(JOB, TIMESTAMP); - - await waitForNextUpdate(); - expect(result.current.isLoading).toBe(true); - resolvePromiseCb({}); await enableDataFeedPromise; - expect(result.current.isLoading).toBe(false); }); + + await waitFor(() => null); + expect(result.current.isLoading).toBe(false); }); it('does not call setupMlJob if job is already installed', async () => { diff --git a/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_security_jobs.test.ts b/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_security_jobs.test.ts index 1451054fb882f..5d2f87911b3a6 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_security_jobs.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_security_jobs.test.ts @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { hasMlAdminPermissions } from '../../../../../common/machine_learning/has_ml_admin_permissions'; import { hasMlLicense } from '../../../../../common/machine_learning/has_ml_license'; import { useAppToasts } from '../../../hooks/use_app_toasts'; @@ -71,20 +72,20 @@ describe('useSecurityJobs', () => { bucketSpanSeconds: 900, }; - const { result, waitForNextUpdate } = renderHook(() => useSecurityJobs(), { + const { result } = renderHook(() => useSecurityJobs(), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.jobs).toHaveLength(6); expect(result.current.jobs).toEqual(expect.arrayContaining([expectedSecurityJob])); }); it('returns those permissions', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSecurityJobs(), { + const { result } = renderHook(() => useSecurityJobs(), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.isMlAdmin).toEqual(true); expect(result.current.isLicensed).toEqual(true); @@ -92,12 +93,12 @@ describe('useSecurityJobs', () => { it('renders a toast error if an ML call fails', async () => { (getModules as jest.Mock).mockRejectedValue('whoops'); - const { waitFor } = renderHook(() => useSecurityJobs(), { + renderHook(() => useSecurityJobs(), { wrapper: TestProviders, }); // addError might be called after an arbitrary number of renders, so we - // need to use waitFor here instead of waitForNextUpdate + // need to use waitFor here instead of waitFor await waitFor(() => { expect(appToastsMock.addError).toHaveBeenCalledWith('whoops', { title: 'Security job fetch failure', diff --git a/x-pack/plugins/security_solution/public/common/components/user_profiles/use_bulk_get_user_profiles.test.tsx b/x-pack/plugins/security_solution/public/common/components/user_profiles/use_bulk_get_user_profiles.test.tsx index 3861e6a6c8a67..eff56069c3724 100644 --- a/x-pack/plugins/security_solution/public/common/components/user_profiles/use_bulk_get_user_profiles.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/user_profiles/use_bulk_get_user_profiles.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { securityMock } from '@kbn/security-plugin/public/mocks'; import { mockUserProfiles } from './mock'; @@ -39,13 +40,10 @@ describe('useBulkGetUserProfiles hook', () => { const userProfiles = useKibana().services.security.userProfiles; const spyOnUserProfiles = jest.spyOn(userProfiles, 'bulkGet'); const assigneesIds = new Set(['user1']); - const { result, waitForNextUpdate } = renderHook( - () => useBulkGetUserProfiles({ uids: assigneesIds }), - { - wrapper: TestProviders, - } - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useBulkGetUserProfiles({ uids: assigneesIds }), { + wrapper: TestProviders, + }); + await waitFor(() => null); expect(spyOnUserProfiles).toHaveBeenCalledTimes(1); expect(result.current.isLoading).toEqual(false); diff --git a/x-pack/plugins/security_solution/public/common/components/user_profiles/use_get_current_user_profile.test.tsx b/x-pack/plugins/security_solution/public/common/components/user_profiles/use_get_current_user_profile.test.tsx index 84beb0a8b135b..c95bb2643fc60 100644 --- a/x-pack/plugins/security_solution/public/common/components/user_profiles/use_get_current_user_profile.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/user_profiles/use_get_current_user_profile.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { securityMock } from '@kbn/security-plugin/public/mocks'; import { mockCurrentUserProfile } from './mock'; @@ -38,10 +39,10 @@ describe('useGetCurrentUserProfile hook', () => { it('returns current user', async () => { const userProfiles = useKibana().services.security.userProfiles; const spyOnUserProfiles = jest.spyOn(userProfiles, 'getCurrent'); - const { result, waitForNextUpdate } = renderHook(() => useGetCurrentUserProfile(), { + const { result } = renderHook(() => useGetCurrentUserProfile(), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spyOnUserProfiles).toHaveBeenCalledTimes(1); expect(result.current.isLoading).toEqual(false); diff --git a/x-pack/plugins/security_solution/public/common/components/user_profiles/use_suggest_users.test.tsx b/x-pack/plugins/security_solution/public/common/components/user_profiles/use_suggest_users.test.tsx index 2cb727942ed57..fb0ca98052527 100644 --- a/x-pack/plugins/security_solution/public/common/components/user_profiles/use_suggest_users.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/user_profiles/use_suggest_users.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useSuggestUsers } from './use_suggest_users'; import * as api from './api'; @@ -27,10 +28,10 @@ describe('useSuggestUsers hook', () => { it('returns an array of userProfiles', async () => { const spyOnUserProfiles = jest.spyOn(api, 'suggestUsers'); - const { result, waitForNextUpdate } = renderHook(() => useSuggestUsers({ searchTerm: '' }), { + const { result } = renderHook(() => useSuggestUsers({ searchTerm: '' }), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spyOnUserProfiles).toHaveBeenCalledTimes(1); expect(result.current.isLoading).toEqual(false); expect(result.current.data).toEqual(mockUserProfiles); diff --git a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.test.ts b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.test.ts index 6fb6a2bcedbd8..1ed7edc6f7531 100644 --- a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.test.ts +++ b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { noop } from 'lodash/fp'; import type { UseTimelineLastEventTimeArgs } from '.'; import { useTimelineLastEventTime } from '.'; @@ -59,61 +60,46 @@ describe('useTimelineLastEventTime', () => { }); it('should init', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - string, - [boolean, UseTimelineLastEventTimeArgs] - >(() => - useTimelineLastEventTime({ - indexKey: LastEventIndexKey.hostDetails, - details: {}, - indexNames: [], - }) - ); - await waitForNextUpdate(); - expect(result.current).toEqual([ - false, - { errorMessage: undefined, lastSeen: null, refetch: noop }, - ]); - }); + const { result } = renderHook(() => + useTimelineLastEventTime({ + indexKey: LastEventIndexKey.hostDetails, + details: {}, + indexNames: [], + }) + ); + + expect(result.current).toEqual([ + false, + { errorMessage: undefined, lastSeen: null, refetch: noop }, + ]); }); it('should call search strategy', async () => { - await act(async () => { - const { waitForNextUpdate } = renderHook( - () => - useTimelineLastEventTime({ - indexKey: LastEventIndexKey.hostDetails, - details: {}, - indexNames: [], - }) - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(mockSearchStrategy.mock.calls[0][0]).toEqual({ - defaultIndex: [], + renderHook(() => + useTimelineLastEventTime({ + indexKey: LastEventIndexKey.hostDetails, details: {}, - factoryQueryType: 'eventsLastEventTime', - indexKey: 'hostDetails', - }); + indexNames: [], + }) + ); + await waitFor(() => null); + expect(mockSearchStrategy.mock.calls[0][0]).toEqual({ + defaultIndex: [], + details: {}, + factoryQueryType: 'eventsLastEventTime', + indexKey: 'hostDetails', }); }); it('should set response', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - string, - [boolean, UseTimelineLastEventTimeArgs] - >(() => - useTimelineLastEventTime({ - indexKey: LastEventIndexKey.hostDetails, - details: {}, - indexNames: [], - }) - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current[1].lastSeen).toEqual('1 minute ago'); - }); + const { result } = renderHook(() => + useTimelineLastEventTime({ + indexKey: LastEventIndexKey.hostDetails, + details: {}, + indexNames: [], + }) + ); + await waitFor(() => null); + expect(result.current[1].lastSeen).toEqual('1 minute ago'); }); }); diff --git a/x-pack/plugins/security_solution/public/common/containers/local_storage/use_messages_storage.test.tsx b/x-pack/plugins/security_solution/public/common/containers/local_storage/use_messages_storage.test.tsx index b80356b65cb5c..2c57dc8fde52a 100644 --- a/x-pack/plugins/security_solution/public/common/containers/local_storage/use_messages_storage.test.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/local_storage/use_messages_storage.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useKibana } from '../../lib/kibana'; import type { UseMessagesStorage } from './use_messages_storage'; import { useMessagesStorage } from './use_messages_storage'; @@ -18,35 +19,30 @@ describe('useLocalStorage', () => { }); it('should return an empty array when there is no messages', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useMessagesStorage() - ); - await waitForNextUpdate(); - const { getMessages } = result.current; + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); + const { getMessages } = result.current; + act(() => { expect(getMessages('case')).toEqual([]); }); }); it('should add a message', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useMessagesStorage() - ); - await waitForNextUpdate(); - const { getMessages, addMessage } = result.current; + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); + const { getMessages, addMessage } = result.current; + act(() => { addMessage('case', 'id-1'); expect(getMessages('case')).toEqual(['id-1']); }); }); it('should add multiple messages', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useMessagesStorage() - ); - await waitForNextUpdate(); - const { getMessages, addMessage } = result.current; + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); + const { getMessages, addMessage } = result.current; + + act(() => { addMessage('case', 'id-1'); addMessage('case', 'id-2'); expect(getMessages('case')).toEqual(['id-1', 'id-2']); @@ -54,12 +50,11 @@ describe('useLocalStorage', () => { }); it('should remove a message', async () => { + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); + const { getMessages, addMessage, removeMessage } = result.current; + await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useMessagesStorage() - ); - await waitForNextUpdate(); - const { getMessages, addMessage, removeMessage } = result.current; addMessage('case', 'id-1'); addMessage('case', 'id-2'); removeMessage('case', 'id-2'); @@ -68,12 +63,10 @@ describe('useLocalStorage', () => { }); it('should return presence of a message', async () => { + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); + const { hasMessage, addMessage, removeMessage } = result.current; await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useMessagesStorage() - ); - await waitForNextUpdate(); - const { hasMessage, addMessage, removeMessage } = result.current; addMessage('case', 'id-1'); addMessage('case', 'id-2'); removeMessage('case', 'id-2'); @@ -83,12 +76,10 @@ describe('useLocalStorage', () => { }); it('should clear all messages', async () => { + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); + const { getMessages, addMessage, clearAllMessages } = result.current; await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useMessagesStorage() - ); - await waitForNextUpdate(); - const { getMessages, addMessage, clearAllMessages } = result.current; addMessage('case', 'id-1'); addMessage('case', 'id-2'); clearAllMessages('case'); diff --git a/x-pack/plugins/security_solution/public/common/containers/source/index.test.tsx b/x-pack/plugins/security_solution/public/common/containers/source/index.test.tsx index 189e04a5c1d64..bda66608d6c5e 100644 --- a/x-pack/plugins/security_solution/public/common/containers/source/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/source/index.test.tsx @@ -5,12 +5,12 @@ * 2.0. */ -import type { PropsWithChildren } from 'react'; import type { IndexFieldSearch } from './use_data_view'; import { useDataView } from './use_data_view'; import { mocksSource } from './mock'; import { mockGlobalState, TestProviders } from '../../mock'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useKibana } from '../../lib/kibana'; const mockDispatch = jest.fn(); @@ -84,14 +84,16 @@ describe('source/index.tsx', () => { }); }); it('sets field data for data view', async () => { - await act(async () => { - const { waitForNextUpdate, result } = renderHook< - PropsWithChildren<{}>, - { indexFieldsSearch: IndexFieldSearch } - >(() => useDataView(), { + const { result } = renderHook<{ indexFieldsSearch: IndexFieldSearch }, string>( + () => useDataView(), + { wrapper: TestProviders, - }); - await waitForNextUpdate(); + } + ); + + await waitFor(() => null); + + await act(async () => { await result.current.indexFieldsSearch({ dataViewId: 'neato' }); }); expect(mockDispatch.mock.calls[0][0]).toEqual({ @@ -105,14 +107,17 @@ describe('source/index.tsx', () => { it('should reuse the result for dataView info when cleanCache not passed', async () => { let indexFieldsSearch: IndexFieldSearch; - await act(async () => { - const { waitForNextUpdate, result } = renderHook< - PropsWithChildren<{}>, - { indexFieldsSearch: IndexFieldSearch } - >(() => useDataView(), { + + const { result } = renderHook<{ indexFieldsSearch: IndexFieldSearch }, string>( + () => useDataView(), + { wrapper: TestProviders, - }); - await waitForNextUpdate(); + } + ); + + await waitFor(() => null); + + await act(async () => { indexFieldsSearch = result.current.indexFieldsSearch; }); @@ -134,14 +139,14 @@ describe('source/index.tsx', () => { it('should not reuse the result for dataView info when cleanCache passed', async () => { let indexFieldsSearch: IndexFieldSearch; - await act(async () => { - const { waitForNextUpdate, result } = renderHook< - PropsWithChildren<{}>, - { indexFieldsSearch: IndexFieldSearch } - >(() => useDataView(), { + const { result } = renderHook<{ indexFieldsSearch: IndexFieldSearch }, string>( + () => useDataView(), + { wrapper: TestProviders, - }); - await waitForNextUpdate(); + } + ); + await waitFor(() => null); + await act(async () => { indexFieldsSearch = result.current.indexFieldsSearch; }); diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.test.tsx b/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.test.tsx index 75f4972b0f11f..6178caee1b0ad 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.test.tsx +++ b/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import type { RequestName } from './request_names'; import type { OptionsParam, RequestFnParam, Result } from './use_fetch'; import { useFetch } from './use_fetch'; @@ -55,7 +56,7 @@ describe('useFetch', () => { }); it('should call fetch', async () => { - const { result, waitForNextUpdate } = renderUseFetch(); + const { result } = renderUseFetch(); expect(result.current.data).toEqual(undefined); expect(result.current.isLoading).toEqual(false); @@ -63,9 +64,10 @@ describe('useFetch', () => { await act(async () => { result.current.fetch(parameters); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(result.current.data).toEqual(response); expect(result.current.isLoading).toEqual(false); expect(result.current.error).toEqual(undefined); @@ -73,7 +75,7 @@ describe('useFetch', () => { }); it('should call fetch if initialParameters option defined', async () => { - const { result, waitForNextUpdate } = renderUseFetch({ initialParameters: parameters }); + const { result } = renderUseFetch({ initialParameters: parameters }); expect(result.current.data).toEqual(undefined); expect(result.current.isLoading).toEqual(true); @@ -81,9 +83,7 @@ describe('useFetch', () => { expect(mockFetchFn).toHaveBeenCalledWith(parameters, abortController.signal); - await act(async () => { - await waitForNextUpdate(); - }); + await waitFor(() => null); expect(result.current.data).toEqual(response); expect(result.current.isLoading).toEqual(false); @@ -91,22 +91,23 @@ describe('useFetch', () => { }); it('should refetch with same parameters', async () => { - const { result, waitForNextUpdate } = renderUseFetch({ initialParameters: parameters }); + const { result } = renderUseFetch({ initialParameters: parameters }); expect(mockFetchFn).toHaveBeenCalledTimes(1); expect(mockFetchFn).toHaveBeenCalledWith(parameters, abortController.signal); await act(async () => { result.current.refetch(); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(mockFetchFn).toHaveBeenCalledTimes(1); expect(mockFetchFn).toHaveBeenCalledWith(parameters, abortController.signal); }); it('should not call fetch if disabled option defined', async () => { - const { result, waitForNextUpdate } = renderUseFetch({ + const { result } = renderUseFetch({ initialParameters: parameters, disabled: true, }); @@ -119,8 +120,8 @@ describe('useFetch', () => { await act(async () => { result.current.fetch(parameters); - await waitForNextUpdate(); }); + await waitFor(() => null); expect(result.current.data).toEqual(undefined); expect(result.current.isLoading).toEqual(true); @@ -134,15 +135,16 @@ describe('useFetch', () => { return response; }); - const { result, waitForNextUpdate, unmount } = renderUseFetch(); + const { result, unmount } = renderUseFetch(); expect(result.current.data).toEqual(undefined); await act(async () => { result.current.fetch(parameters); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(result.current.data).toEqual(undefined); }); @@ -152,15 +154,16 @@ describe('useFetch', () => { throw new Error(); }); - const { result, waitForNextUpdate, unmount } = renderUseFetch(); + const { result, unmount } = renderUseFetch(); expect(result.current.error).toEqual(undefined); await act(async () => { result.current.fetch(parameters); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(result.current.error).toEqual(undefined); }); @@ -168,16 +171,14 @@ describe('useFetch', () => { const firstAbortCtrl = new AbortController(); const abortSpy = jest.spyOn(window, 'AbortController').mockReturnValueOnce(firstAbortCtrl); - const { result, waitForNextUpdate } = renderUseFetch({ initialParameters: parameters }); + const { result } = renderUseFetch({ initialParameters: parameters }); mockFetchFn.mockImplementationOnce(async () => { result.current.fetch(parameters); return response; }); - await act(async () => { - await waitForNextUpdate(); - }); + await waitFor(() => null); expect(firstAbortCtrl.signal.aborted).toEqual(true); @@ -188,7 +189,7 @@ describe('useFetch', () => { const firstAbortCtrl = new AbortController(); const abortSpy = jest.spyOn(window, 'AbortController').mockReturnValueOnce(firstAbortCtrl); - const { result, waitForNextUpdate } = renderUseFetch(); + const { result } = renderUseFetch(); mockFetchFn.mockImplementationOnce(async () => { result.current.fetch(parameters); @@ -197,9 +198,10 @@ describe('useFetch', () => { await act(async () => { result.current.fetch(parameters); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(firstAbortCtrl.signal.aborted).toEqual(true); abortSpy.mockRestore(); @@ -207,25 +209,24 @@ describe('useFetch', () => { describe('APM tracking', () => { it('should track with request name', async () => { - const { result, waitForNextUpdate } = renderUseFetch(); + const { result } = renderUseFetch(); await act(async () => { result.current.fetch(parameters); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(mockStartTracking).toHaveBeenCalledTimes(1); expect(mockStartTracking).toHaveBeenCalledWith({ name: requestName }); }); it('should track each request', async () => { - const { result, waitForNextUpdate } = renderUseFetch({ + const { result } = renderUseFetch({ initialParameters: parameters, }); - await act(async () => { - await waitForNextUpdate(); - }); + await waitFor(() => null); expect(mockFetchFn).toHaveBeenCalledTimes(1); expect(mockStartTracking).toHaveBeenCalledTimes(1); @@ -234,22 +235,24 @@ describe('useFetch', () => { await act(async () => { result.current.fetch(parameters); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(mockFetchFn).toHaveBeenCalledTimes(2); expect(mockStartTracking).toHaveBeenCalledTimes(2); expect(mockEndTracking).toHaveBeenCalledTimes(2); }); it('should end success', async () => { - const { result, waitForNextUpdate } = renderUseFetch(); + const { result } = renderUseFetch(); await act(async () => { result.current.fetch(parameters); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(mockEndTracking).toHaveBeenCalledTimes(1); expect(mockEndTracking).toHaveBeenCalledWith('success'); }); @@ -263,13 +266,14 @@ describe('useFetch', () => { throw Error('request aborted'); }); - const { result, waitForNextUpdate } = renderUseFetch(); + const { result } = renderUseFetch(); await act(async () => { result.current.fetch(parameters); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(mockEndTracking).toHaveBeenCalledTimes(1); expect(mockEndTracking).toHaveBeenCalledWith('aborted'); @@ -281,13 +285,14 @@ describe('useFetch', () => { throw Error('request error'); }); - const { result, waitForNextUpdate } = renderUseFetch(); + const { result } = renderUseFetch(); await act(async () => { result.current.fetch(parameters); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(mockEndTracking).toHaveBeenCalledTimes(1); expect(mockEndTracking).toHaveBeenCalledWith('error'); }); diff --git a/x-pack/plugins/security_solution/public/common/links/links.test.tsx b/x-pack/plugins/security_solution/public/common/links/links.test.tsx index c0f8c8cc48da4..0b47bc49bdd0c 100644 --- a/x-pack/plugins/security_solution/public/common/links/links.test.tsx +++ b/x-pack/plugins/security_solution/public/common/links/links.test.tsx @@ -10,7 +10,8 @@ import type { Capabilities } from '@kbn/core/types'; import { mockGlobalState, TestProviders } from '../mock'; import type { ILicense, LicenseType } from '@kbn/licensing-plugin/common/types'; import type { AppLinkItems, LinkItem, LinksPermissions } from './types'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useAppLinks, getAncestorLinksInfo, @@ -110,7 +111,7 @@ describe('Security links', () => { }); it('should filter not allowed links', async () => { - const { result, waitForNextUpdate } = renderUseAppLinks(); + const { result } = renderUseAppLinks(); // this link should not be excluded, the test checks all conditions are passed const networkLinkItem = { id: SecurityPageName.network, @@ -182,9 +183,10 @@ describe('Security links', () => { uiSettingsClient: mockUiSettingsClient, } ); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(result.current).toStrictEqual([networkLinkItem]); }); @@ -192,7 +194,7 @@ describe('Security links', () => { const upselling = new UpsellingService(); upselling.setPages({ [SecurityPageName.network]: () => }); - const { result, waitForNextUpdate } = renderUseAppLinks(); + const { result } = renderUseAppLinks(); const networkLinkItem = { id: SecurityPageName.network, title: 'Network', @@ -249,16 +251,17 @@ describe('Security links', () => { uiSettingsClient: mockUiSettingsClient, } ); - await waitForNextUpdate(); }); + await waitFor(() => null); + expect(result.current).toStrictEqual([{ ...networkLinkItem, unauthorized: true }]); }); it('should return unauthorized page when page has upselling (ESS)', async () => { const upselling = new UpsellingService(); upselling.setPages({ [SecurityPageName.network]: () => }); - const { result, waitForNextUpdate } = renderUseAppLinks(); + const { result } = renderUseAppLinks(); const hostLinkItem = { id: SecurityPageName.hosts, title: 'Hosts', @@ -278,8 +281,10 @@ describe('Security links', () => { upselling: mockUpselling, uiSettingsClient: mockUiSettingsClient, }); - await waitForNextUpdate(); }); + + await waitFor(() => null); + expect(result.current).toStrictEqual([{ ...hostLinkItem, unauthorized: true }]); // cleanup @@ -289,7 +294,7 @@ describe('Security links', () => { it('should filter out experimental page even if it has upselling', async () => { const upselling = new UpsellingService(); upselling.setPages({ [SecurityPageName.network]: () => }); - const { result, waitForNextUpdate } = renderUseAppLinks(); + const { result } = renderUseAppLinks(); const hostLinkItem = { id: SecurityPageName.hosts, title: 'Hosts', @@ -310,8 +315,9 @@ describe('Security links', () => { upselling: mockUpselling, uiSettingsClient: mockUiSettingsClient, }); - await waitForNextUpdate(); }); + + await waitFor(() => null); expect(result.current).toStrictEqual([]); // cleanup @@ -331,7 +337,7 @@ describe('Security links', () => { }); it('should update if the links are removed', async () => { - const { result, waitForNextUpdate } = renderUseLinkExists(SecurityPageName.hostsEvents); + const { result } = renderUseLinkExists(SecurityPageName.hostsEvents); expect(result.current).toBe(true); await act(async () => { updateAppLinks( @@ -350,13 +356,14 @@ describe('Security links', () => { uiSettingsClient: mockUiSettingsClient, } ); - await waitForNextUpdate(); }); + + await waitFor(() => null); expect(result.current).toBe(false); }); it('should update if the links are added', async () => { - const { result, waitForNextUpdate } = renderUseLinkExists(SecurityPageName.rules); + const { result } = renderUseLinkExists(SecurityPageName.rules); expect(result.current).toBe(false); await act(async () => { updateAppLinks( @@ -382,8 +389,9 @@ describe('Security links', () => { uiSettingsClient: mockUiSettingsClient, } ); - await waitForNextUpdate(); }); + + await waitFor(() => null); expect(result.current).toBe(true); }); }); diff --git a/x-pack/plugins/security_solution/public/common/utils/global_query_string/index.test.tsx b/x-pack/plugins/security_solution/public/common/utils/global_query_string/index.test.tsx index 6905b5abca118..0bc3f652c3e1c 100644 --- a/x-pack/plugins/security_solution/public/common/utils/global_query_string/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/utils/global_query_string/index.test.tsx @@ -6,7 +6,8 @@ */ import React from 'react'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useInitializeUrlParam, useGlobalQueryString, @@ -306,7 +307,7 @@ describe('global query string', () => { }; const store = makeStore(globalUrlParam); - const { waitForNextUpdate } = renderHook(() => useSyncGlobalQueryString(), { + renderHook(() => useSyncGlobalQueryString(), { wrapper: ({ children }: { children: React.ReactElement }) => ( {children} ), @@ -318,7 +319,7 @@ describe('global query string', () => { store.dispatch(globalUrlParamActions.deregisterUrlParam({ key: urlParamKey })); }); - waitForNextUpdate(); + waitFor(() => null); expect(mockHistory.replace).toHaveBeenCalledWith({ search: ``, diff --git a/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.test.tsx b/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.test.tsx index dec72d0f938b0..4df1456631ee4 100644 --- a/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.test.tsx +++ b/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { allowedExperimentalValues } from '../../../../common/experimental_features'; import { UpsellingService } from '@kbn/security-solution-upselling/service'; import { updateAppLinks } from '../../links'; @@ -77,40 +78,34 @@ describe('use show timeline', () => { }); it('shows timeline for routes on default', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useShowTimeline()); - await waitForNextUpdate(); - const showTimeline = result.current; - expect(showTimeline).toEqual([true]); - }); + const { result } = renderHook(() => useShowTimeline()); + await waitFor(() => null); + const showTimeline = result.current; + expect(showTimeline).toEqual([true]); }); it('hides timeline for blacklist routes', async () => { mockUseLocation.mockReturnValueOnce({ pathname: '/rules/add_rules' }); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useShowTimeline()); - await waitForNextUpdate(); - const showTimeline = result.current; - expect(showTimeline).toEqual([false]); - }); + const { result } = renderHook(() => useShowTimeline()); + await waitFor(() => null); + const showTimeline = result.current; + expect(showTimeline).toEqual([false]); }); + it('shows timeline for partial blacklist routes', async () => { mockUseLocation.mockReturnValueOnce({ pathname: '/rules' }); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useShowTimeline()); - await waitForNextUpdate(); - const showTimeline = result.current; - expect(showTimeline).toEqual([true]); - }); + const { result } = renderHook(() => useShowTimeline()); + await waitFor(() => null); + const showTimeline = result.current; + expect(showTimeline).toEqual([true]); }); + it('hides timeline for sub blacklist routes', async () => { mockUseLocation.mockReturnValueOnce({ pathname: '/administration/policy' }); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useShowTimeline()); - await waitForNextUpdate(); - const showTimeline = result.current; - expect(showTimeline).toEqual([false]); - }); + const { result } = renderHook(() => useShowTimeline()); + await waitFor(() => null); + const showTimeline = result.current; + expect(showTimeline).toEqual([false]); }); }); diff --git a/x-pack/plugins/security_solution/public/dashboards/containers/use_fetch_security_dashboards.test.ts b/x-pack/plugins/security_solution/public/dashboards/containers/use_fetch_security_dashboards.test.ts index ced91801747c8..6884d99b968b9 100644 --- a/x-pack/plugins/security_solution/public/dashboards/containers/use_fetch_security_dashboards.test.ts +++ b/x-pack/plugins/security_solution/public/dashboards/containers/use_fetch_security_dashboards.test.ts @@ -5,7 +5,8 @@ * 2.0. */ import type { HttpStart } from '@kbn/core/public'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { DashboardContextProvider } from '../context/dashboard_context'; import { useFetchSecurityDashboards } from './use_fetch_security_dashboards'; import { getTagsByName } from '../../common/containers/tags/api'; @@ -28,9 +29,9 @@ const renderUseFetchSecurityDashboards = () => const asyncRenderUseFetchSecurityDashboards = async () => { const renderedHook = renderUseFetchSecurityDashboards(); - await act(async () => { - await renderedHook.waitForNextUpdate(); - }); + + await waitFor(() => null); + return renderedHook; }; diff --git a/x-pack/plugins/security_solution/public/dashboards/containers/use_fetch_security_tags.test.ts b/x-pack/plugins/security_solution/public/dashboards/containers/use_fetch_security_tags.test.ts index 3dadc008a9efa..def1e26ed03aa 100644 --- a/x-pack/plugins/security_solution/public/dashboards/containers/use_fetch_security_tags.test.ts +++ b/x-pack/plugins/security_solution/public/dashboards/containers/use_fetch_security_tags.test.ts @@ -6,7 +6,8 @@ */ import type { HttpStart } from '@kbn/core/public'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { INTERNAL_TAGS_URL, SECURITY_TAG_DESCRIPTION, @@ -30,9 +31,7 @@ const renderUseCreateSecurityDashboardLink = () => renderHook(() => useFetchSecu const asyncRenderUseCreateSecurityDashboardLink = async () => { const renderedHook = renderUseCreateSecurityDashboardLink(); - await act(async () => { - await renderedHook.waitForNextUpdate(); - }); + await waitFor(() => null); return renderedHook; }; diff --git a/x-pack/plugins/security_solution/public/dashboards/hooks/use_create_security_dashboard_link.test.tsx b/x-pack/plugins/security_solution/public/dashboards/hooks/use_create_security_dashboard_link.test.tsx index 36aa70bc5678c..5ecd89d5a57fb 100644 --- a/x-pack/plugins/security_solution/public/dashboards/hooks/use_create_security_dashboard_link.test.tsx +++ b/x-pack/plugins/security_solution/public/dashboards/hooks/use_create_security_dashboard_link.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useKibana } from '../../common/lib/kibana'; import { useCreateSecurityDashboardLink } from './use_create_security_dashboard_link'; import { DashboardContextProvider } from '../context/dashboard_context'; @@ -37,9 +38,8 @@ const renderUseCreateSecurityDashboardLink = () => const asyncRenderUseCreateSecurityDashboard = async () => { const renderedHook = renderUseCreateSecurityDashboardLink(); - await act(async () => { - await renderedHook.waitForNextUpdate(); - }); + waitFor(() => null); + return renderedHook; }; @@ -84,14 +84,12 @@ describe('useCreateSecurityDashboardLink', () => { }); it('should return isLoading while requesting', async () => { - const { result, waitForNextUpdate } = renderUseCreateSecurityDashboardLink(); + const { result } = renderUseCreateSecurityDashboardLink(); expect(result.current.isLoading).toEqual(true); expect(result.current.url).toEqual('/app/security/dashboards/create'); - await act(async () => { - await waitForNextUpdate(); - }); + await waitFor(() => null); expect(result.current.isLoading).toEqual(false); expect(result.current.url).toEqual('/app/security/dashboards/create'); diff --git a/x-pack/plugins/security_solution/public/dashboards/hooks/use_security_dashboards_table.test.tsx b/x-pack/plugins/security_solution/public/dashboards/hooks/use_security_dashboards_table.test.tsx index 1026c69da8d8e..9f387550937b2 100644 --- a/x-pack/plugins/security_solution/public/dashboards/hooks/use_security_dashboards_table.test.tsx +++ b/x-pack/plugins/security_solution/public/dashboards/hooks/use_security_dashboards_table.test.tsx @@ -6,8 +6,8 @@ */ import React from 'react'; -import { renderHook, act } from '@testing-library/react-hooks'; -import { render } from '@testing-library/react'; +import { renderHook } from '@testing-library/react-hooks'; +import { render, act, waitFor } from '@testing-library/react'; import type { DashboardStart } from '@kbn/dashboard-plugin/public'; import { EuiBasicTable } from '@elastic/eui'; import { useKibana } from '../../common/lib/kibana'; @@ -38,10 +38,9 @@ const renderUseSecurityDashboardsTableItems = async () => { const renderedHook = renderHook(() => useSecurityDashboardsTableItems(), { wrapper: DashboardContextProvider, }); - await act(async () => { - // needed to let dashboard items to be updated from saved objects response - await renderedHook.waitForNextUpdate(); - }); + // needed to let dashboard items to be updated from saved objects response + await waitFor(() => null); + return renderedHook; }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_fetch_or_create_rule_exception_list.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_fetch_or_create_rule_exception_list.test.tsx index 6cca3e02e3223..2c25b24a8e65e 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_fetch_or_create_rule_exception_list.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_fetch_or_create_rule_exception_list.test.tsx @@ -6,7 +6,8 @@ */ import type { RenderHookResult } from '@testing-library/react-hooks'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { coreMock } from '@kbn/core/public/mocks'; import * as rulesApi from '../../rule_management/api/api'; @@ -94,7 +95,7 @@ describe('useFetchOrCreateRuleExceptionList', () => { .mockResolvedValue(detectionExceptionList); render = (listType = detectionListType) => - renderHook( + renderHook( () => useFetchOrCreateRuleExceptionList({ http: mockKibanaHttpService, @@ -111,25 +112,22 @@ describe('useFetchOrCreateRuleExceptionList', () => { }); it('initializes hook', async () => { - const { result, waitForNextUpdate } = render(); + const { result } = render(); // Should set isLoading to true while fetching expect(result.current).toEqual([true, null]); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual([false, detectionExceptionList]); }); it('fetches the rule with the given ruleId', async () => { - await act(async () => { - const { waitForNextUpdate } = render(); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(fetchRuleById).toHaveBeenCalledTimes(1); - expect(fetchRuleById).toHaveBeenCalledWith({ - id: ruleId, - signal: abortCtrl.signal, - }); + render(); + await waitFor(() => null); + expect(fetchRuleById).toHaveBeenCalledTimes(1); + expect(fetchRuleById).toHaveBeenCalledWith({ + id: ruleId, + signal: abortCtrl.signal, }); }); @@ -141,78 +139,57 @@ describe('useFetchOrCreateRuleExceptionList', () => { }); it('does not fetch the exceptions lists', async () => { - await act(async () => { - const { waitForNextUpdate } = render(); - await waitForNextUpdate(); - expect(fetchExceptionListById).not.toHaveBeenCalled(); - }); + render(); + await waitFor(() => null); + expect(fetchExceptionListById).not.toHaveBeenCalled(); }); + it('should create a new exception list', async () => { - await act(async () => { - const { waitForNextUpdate } = render(); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(addExceptionList).toHaveBeenCalledTimes(1); - }); + render(); + await waitFor(() => null); + expect(addExceptionList).toHaveBeenCalledTimes(1); }); it('should update the rule', async () => { - await act(async () => { - const { waitForNextUpdate } = render(); - await waitForNextUpdate(); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(patchRule).toHaveBeenCalledTimes(1); - }); + render(); + await waitFor(() => null); + expect(patchRule).toHaveBeenCalledTimes(1); }); it('invokes onSuccess', async () => { - await act(async () => { - const { waitForNextUpdate } = render(); - await waitForNextUpdate(); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(onSuccess).toHaveBeenCalledWith(false); - }); + render(); + await waitFor(() => null); + expect(onSuccess).toHaveBeenCalledWith(false); }); }); describe("when the rule has exception list references and 'detection' is passed in", () => { it('fetches the exceptions lists', async () => { - await act(async () => { - const { waitForNextUpdate } = render(); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(fetchExceptionListById).toHaveBeenCalledTimes(2); - }); + render(); + await waitFor(() => null); + expect(fetchExceptionListById).toHaveBeenCalledTimes(2); }); + it('does not create a new exception list', async () => { - await act(async () => { - const { waitForNextUpdate } = render(); - await waitForNextUpdate(); - expect(addExceptionList).not.toHaveBeenCalled(); - }); + render(); + await waitFor(() => null); + expect(addExceptionList).not.toHaveBeenCalled(); }); + it('does not update the rule', async () => { - await act(async () => { - const { waitForNextUpdate } = render(); - await waitForNextUpdate(); - expect(patchRule).not.toHaveBeenCalled(); - }); + render(); + await waitFor(() => null); + expect(patchRule).not.toHaveBeenCalled(); }); + it('should set the exception list to be the fetched list', async () => { - await act(async () => { - const { result, waitForNextUpdate } = render(); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current[1]).toEqual(detectionExceptionList); - }); + const { result } = render(); + await waitFor(() => null); + expect(result.current[1]).toEqual(detectionExceptionList); }); + it('invokes onSuccess indicating', async () => { - await act(async () => { - const { waitForNextUpdate } = render(); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(onSuccess).toHaveBeenCalledWith(false); - }); + render(); + await waitFor(() => null); + expect(onSuccess).toHaveBeenCalledWith(false); }); describe("but the rule does not have a reference to 'detection' type exception list", () => { @@ -223,30 +200,19 @@ describe('useFetchOrCreateRuleExceptionList', () => { }); it('should create a new exception list', async () => { - await act(async () => { - const { waitForNextUpdate } = render(); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(addExceptionList).toHaveBeenCalledTimes(1); - }); + render(); + await waitFor(() => null); + expect(addExceptionList).toHaveBeenCalledTimes(1); }); it('should update the rule', async () => { - await act(async () => { - const { waitForNextUpdate } = render(); - await waitForNextUpdate(); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(patchRule).toHaveBeenCalledTimes(1); - }); + render(); + await waitFor(() => null); + expect(patchRule).toHaveBeenCalledTimes(1); }); it('should set the exception list to be the newly created list', async () => { - await act(async () => { - const { result, waitForNextUpdate } = render(); - await waitForNextUpdate(); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current[1]).toEqual(newDetectionExceptionList); - }); + const { result } = render(); + await waitFor(() => null); + expect(result.current[1]).toEqual(newDetectionExceptionList); }); }); }); @@ -263,34 +229,24 @@ describe('useFetchOrCreateRuleExceptionList', () => { }); it('fetches the exceptions lists', async () => { - await act(async () => { - const { waitForNextUpdate } = render(endpointListType); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(fetchExceptionListById).toHaveBeenCalledTimes(2); - }); + render(endpointListType); + await waitFor(() => null); + expect(fetchExceptionListById).toHaveBeenCalledTimes(2); }); it('does not create a new exception list', async () => { - await act(async () => { - const { waitForNextUpdate } = render(endpointListType); - await waitForNextUpdate(); - expect(addExceptionList).not.toHaveBeenCalled(); - }); + render(endpointListType); + await waitFor(() => null); + expect(addExceptionList).not.toHaveBeenCalled(); }); it('does not update the rule', async () => { - await act(async () => { - const { waitForNextUpdate } = render(endpointListType); - await waitForNextUpdate(); - expect(patchRule).not.toHaveBeenCalled(); - }); + render(endpointListType); + await waitFor(() => null); + expect(patchRule).not.toHaveBeenCalled(); }); it('should set the exception list to be the fetched list', async () => { - await act(async () => { - const { result, waitForNextUpdate } = render(endpointListType); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current[1]).toEqual(endpointExceptionList); - }); + const { result } = render(endpointListType); + await waitFor(() => null); + expect(result.current[1]).toEqual(endpointExceptionList); }); describe("but the rule does not have a reference to 'endpoint' type exception list", () => { @@ -301,30 +257,19 @@ describe('useFetchOrCreateRuleExceptionList', () => { }); it('should create a new exception list', async () => { - await act(async () => { - const { waitForNextUpdate } = render(endpointListType); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(addEndpointExceptionList).toHaveBeenCalledTimes(1); - }); + render(endpointListType); + await waitFor(() => null); + expect(addEndpointExceptionList).toHaveBeenCalledTimes(1); }); it('should update the rule', async () => { - await act(async () => { - const { waitForNextUpdate } = render(endpointListType); - await waitForNextUpdate(); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(patchRule).toHaveBeenCalledTimes(1); - }); + render(endpointListType); + await waitFor(() => null); + expect(patchRule).toHaveBeenCalledTimes(1); }); it('should set the exception list to be the newly created list', async () => { - await act(async () => { - const { result, waitForNextUpdate } = render(endpointListType); - await waitForNextUpdate(); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current[1]).toEqual(newEndpointExceptionList); - }); + const { result } = render(endpointListType); + await waitFor(() => null); + expect(result.current[1]).toEqual(newEndpointExceptionList); }); }); }); @@ -335,37 +280,28 @@ describe('useFetchOrCreateRuleExceptionList', () => { }); it('exception list should be null', async () => { - await act(async () => { - const { result, waitForNextUpdate } = render(); - await waitForNextUpdate(); - expect(result.current[1]).toBeNull(); - }); + const { result } = render(); + await waitFor(() => null); + expect(result.current[1]).toBeNull(); }); it('isLoading should be false', async () => { - await act(async () => { - const { result, waitForNextUpdate } = render(); - await waitForNextUpdate(); - expect(result.current[0]).toEqual(false); - }); + const { result } = render(); + await waitFor(() => null); + expect(result.current[0]).toEqual(false); }); it('should call error callback', async () => { - await act(async () => { - const { waitForNextUpdate } = render(); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(onError).toHaveBeenCalledTimes(1); - expect(onError).toHaveBeenCalledWith(error, null, null); - }); + render(); + await waitFor(() => null); + expect(onError).toHaveBeenCalledTimes(1); + expect(onError).toHaveBeenCalledWith(error, null, null); }); it('does not call onSuccess', async () => { - await act(async () => { - const { waitForNextUpdate } = render(); - await waitForNextUpdate(); - expect(onSuccess).not.toHaveBeenCalled(); - }); + render(); + await waitFor(() => null); + expect(onSuccess).not.toHaveBeenCalled(); }); }); }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/use_dissasociate_exception_list.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/use_dissasociate_exception_list.test.ts index 553f8734b4540..a783ce6d80d81 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/use_dissasociate_exception_list.test.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/use_dissasociate_exception_list.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { coreMock } from '@kbn/core/public/mocks'; @@ -33,7 +34,7 @@ describe('useDisassociateExceptionList', () => { test('initializes hook', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook< + const { result } = renderHook< UseDisassociateExceptionListProps, ReturnUseDisassociateExceptionList >(() => @@ -45,7 +46,7 @@ describe('useDisassociateExceptionList', () => { }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual([false, null]); }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring/components/execution_events_table/use_execution_events.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring/components/execution_events_table/use_execution_events.test.tsx index f0480cbef8f3b..f53f104c13738 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring/components/execution_events_table/use_execution_events.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring/components/execution_events_table/use_execution_events.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, cleanup } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { cleanup, waitFor } from '@testing-library/react'; import { LogLevelEnum, @@ -39,9 +40,9 @@ describe('useExecutionEvents', () => { it('calls the API via fetchRuleExecutionEvents', async () => { const fetchRuleExecutionEvents = jest.spyOn(api, 'fetchRuleExecutionEvents'); - const { waitForNextUpdate } = render(); + render(); - await waitForNextUpdate(); + await waitFor(() => null); expect(fetchRuleExecutionEvents).toHaveBeenCalledTimes(1); expect(fetchRuleExecutionEvents).toHaveBeenLastCalledWith( @@ -50,7 +51,7 @@ describe('useExecutionEvents', () => { }); it('fetches data from the API', async () => { - const { result, waitForNextUpdate } = render(); + const { result } = render(); // It starts from a loading state expect(result.current.isLoading).toEqual(true); @@ -58,7 +59,7 @@ describe('useExecutionEvents', () => { expect(result.current.isError).toEqual(false); // When fetchRuleExecutionEvents returns - await waitForNextUpdate(); + await waitFor(() => null); // It switches to a success state expect(result.current.isLoading).toEqual(false); @@ -87,7 +88,7 @@ describe('useExecutionEvents', () => { const exception = new Error('Boom!'); jest.spyOn(api, 'fetchRuleExecutionEvents').mockRejectedValue(exception); - const { result, waitForNextUpdate } = render(); + const { result } = render(); // It starts from a loading state expect(result.current.isLoading).toEqual(true); @@ -95,7 +96,7 @@ describe('useExecutionEvents', () => { expect(result.current.isError).toEqual(false); // When fetchRuleExecutionEvents throws - await waitForNextUpdate(); + await waitFor(() => null); // It switches to an error state expect(result.current.isLoading).toEqual(false); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring/components/execution_results_table/use_execution_results.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring/components/execution_results_table/use_execution_results.test.tsx index d5d2e2409e2a3..07010105cdb25 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring/components/execution_results_table/use_execution_results.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring/components/execution_results_table/use_execution_results.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, cleanup } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { cleanup, waitFor } from '@testing-library/react'; import { useExecutionResults } from './use_execution_results'; import { useToasts } from '../../../../common/lib/kibana'; @@ -48,9 +49,9 @@ describe('useExecutionResults', () => { it('calls the API via fetchRuleExecutionResults', async () => { const fetchRuleExecutionResults = jest.spyOn(api, 'fetchRuleExecutionResults'); - const { waitForNextUpdate } = render(); + render(); - await waitForNextUpdate(); + await waitFor(() => null); expect(fetchRuleExecutionResults).toHaveBeenCalledTimes(1); expect(fetchRuleExecutionResults).toHaveBeenLastCalledWith( @@ -59,7 +60,7 @@ describe('useExecutionResults', () => { }); it('fetches data from the API', async () => { - const { result, waitForNextUpdate } = render(); + const { result } = render(); // It starts from a loading state expect(result.current.isLoading).toEqual(true); @@ -67,7 +68,7 @@ describe('useExecutionResults', () => { expect(result.current.isError).toEqual(false); // When fetchRuleExecutionEvents returns - await waitForNextUpdate(); + await waitFor(() => null); // It switches to a success state expect(result.current.isLoading).toEqual(false); @@ -107,7 +108,7 @@ describe('useExecutionResults', () => { const exception = new Error('Boom!'); jest.spyOn(api, 'fetchRuleExecutionResults').mockRejectedValue(exception); - const { result, waitForNextUpdate } = render(); + const { result } = render(); // It starts from a loading state expect(result.current.isLoading).toEqual(true); @@ -115,7 +116,7 @@ describe('useExecutionResults', () => { expect(result.current.isError).toEqual(false); // When fetchRuleExecutionEvents throws - await waitForNextUpdate(); + await waitFor(() => null); // It switches to an error state expect(result.current.isLoading).toEqual(false); diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouping_settings/group_take_action_items.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouping_settings/group_take_action_items.test.tsx index 5518926f4ab61..e0d26599ad0dc 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouping_settings/group_take_action_items.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouping_settings/group_take_action_items.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import React from 'react'; import { TestProviders } from '../../../../common/mock'; import { useGroupTakeActionsItems } from '.'; @@ -20,143 +21,129 @@ describe('useGroupTakeActionsItems', () => { selectedGroup: 'test', }; it('returns all take actions items if showAlertStatusActions is true and currentStatus is undefined', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook( - () => - useGroupTakeActionsItems({ - showAlertStatusActions: true, - }), - { - wrapper: wrapperContainer, - } - ); - await waitForNextUpdate(); - expect(result.current(getActionItemsParams).length).toEqual(3); - }); + const { result } = renderHook( + () => + useGroupTakeActionsItems({ + showAlertStatusActions: true, + }), + { + wrapper: wrapperContainer, + } + ); + await waitFor(() => null); + expect(result.current(getActionItemsParams).length).toEqual(3); }); it('returns all take actions items if currentStatus is []', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook( - () => - useGroupTakeActionsItems({ - currentStatus: [], - showAlertStatusActions: true, - }), - { - wrapper: wrapperContainer, - } - ); - await waitForNextUpdate(); - expect(result.current(getActionItemsParams).length).toEqual(3); - }); + const { result } = renderHook( + () => + useGroupTakeActionsItems({ + currentStatus: [], + showAlertStatusActions: true, + }), + { + wrapper: wrapperContainer, + } + ); + await waitFor(() => null); + expect(result.current(getActionItemsParams).length).toEqual(3); }); it('returns all take actions items if currentStatus.length > 1', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook( - () => - useGroupTakeActionsItems({ - currentStatus: ['open', 'closed'], - showAlertStatusActions: true, - }), - { - wrapper: wrapperContainer, - } - ); - await waitForNextUpdate(); - expect(result.current(getActionItemsParams).length).toEqual(3); - }); + const { result } = renderHook( + () => + useGroupTakeActionsItems({ + currentStatus: ['open', 'closed'], + showAlertStatusActions: true, + }), + { + wrapper: wrapperContainer, + } + ); + await waitFor(() => null); + expect(result.current(getActionItemsParams).length).toEqual(3); }); it('returns acknowledged & closed take actions items if currentStatus === ["open"]', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook( - () => - useGroupTakeActionsItems({ - currentStatus: ['open'], - showAlertStatusActions: true, - }), - { - wrapper: wrapperContainer, - } - ); - await waitForNextUpdate(); - const currentParams = result.current(getActionItemsParams); - expect(currentParams.length).toEqual(2); - expect(currentParams[0].key).toEqual('acknowledge'); - expect(currentParams[1].key).toEqual('close'); - }); + const { result } = renderHook( + () => + useGroupTakeActionsItems({ + currentStatus: ['open'], + showAlertStatusActions: true, + }), + { + wrapper: wrapperContainer, + } + ); + await waitFor(() => null); + const currentParams = result.current(getActionItemsParams); + expect(currentParams.length).toEqual(2); + expect(currentParams[0].key).toEqual('acknowledge'); + expect(currentParams[1].key).toEqual('close'); }); it('returns open & acknowledged take actions items if currentStatus === ["closed"]', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook( - () => - useGroupTakeActionsItems({ - currentStatus: ['closed'], - showAlertStatusActions: true, - }), - { - wrapper: wrapperContainer, - } - ); - await waitForNextUpdate(); - const currentParams = result.current(getActionItemsParams); - expect(currentParams.length).toEqual(2); - expect(currentParams[0].key).toEqual('open'); - expect(currentParams[1].key).toEqual('acknowledge'); - }); + const { result } = renderHook( + () => + useGroupTakeActionsItems({ + currentStatus: ['closed'], + showAlertStatusActions: true, + }), + { + wrapper: wrapperContainer, + } + ); + await waitFor(() => null); + const currentParams = result.current(getActionItemsParams); + expect(currentParams.length).toEqual(2); + expect(currentParams[0].key).toEqual('open'); + expect(currentParams[1].key).toEqual('acknowledge'); }); it('returns open & closed take actions items if currentStatus === ["acknowledged"]', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook( - () => - useGroupTakeActionsItems({ - currentStatus: ['acknowledged'], - showAlertStatusActions: true, - }), - { - wrapper: wrapperContainer, - } - ); - await waitForNextUpdate(); - const currentParams = result.current(getActionItemsParams); - expect(currentParams.length).toEqual(2); - expect(currentParams[0].key).toEqual('open'); - expect(currentParams[1].key).toEqual('close'); - }); + const { result } = renderHook( + () => + useGroupTakeActionsItems({ + currentStatus: ['acknowledged'], + showAlertStatusActions: true, + }), + { + wrapper: wrapperContainer, + } + ); + await waitFor(() => null); + + const currentParams = result.current(getActionItemsParams); + expect(currentParams.length).toEqual(2); + expect(currentParams[0].key).toEqual('open'); + expect(currentParams[1].key).toEqual('close'); }); it('returns empty take actions items if showAlertStatusActions is false', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook( - () => - useGroupTakeActionsItems({ - showAlertStatusActions: false, - }), - { - wrapper: wrapperContainer, - } - ); - await waitForNextUpdate(); - expect(result.current(getActionItemsParams).length).toEqual(0); - }); + const { result } = renderHook( + () => + useGroupTakeActionsItems({ + showAlertStatusActions: false, + }), + { + wrapper: wrapperContainer, + } + ); + await waitFor(() => null); + expect(result.current(getActionItemsParams).length).toEqual(0); }); + it('returns array take actions items if showAlertStatusActions is true', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook( - () => - useGroupTakeActionsItems({ - showAlertStatusActions: true, - }), - { - wrapper: wrapperContainer, - } - ); - await waitForNextUpdate(); - expect(result.current(getActionItemsParams).length).toEqual(3); - }); + const { result } = renderHook( + () => + useGroupTakeActionsItems({ + showAlertStatusActions: true, + }), + { + wrapper: wrapperContainer, + } + ); + await waitFor(() => null); + expect(result.current(getActionItemsParams).length).toEqual(3); }); }); diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/related_integrations/use_integrations.test.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/related_integrations/use_integrations.test.tsx index eba2248f82a4d..6da6c4fe0f775 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/related_integrations/use_integrations.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/related_integrations/use_integrations.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, cleanup } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { cleanup, waitFor } from '@testing-library/react'; import { useIntegrations } from './use_integrations'; @@ -39,9 +40,9 @@ describe('useIntegrations', () => { it('calls the API via fetchAllIntegrations', async () => { const fetchAllIntegrations = jest.spyOn(fleetIntegrationsApi, 'fetchAllIntegrations'); - const { waitForNextUpdate } = render(); + render(); - await waitForNextUpdate(); + await waitFor(() => null); expect(fetchAllIntegrations).toHaveBeenCalledTimes(1); }); @@ -55,7 +56,7 @@ describe('useIntegrations', () => { }); it('fetches data from the API', async () => { - const { result, waitForNextUpdate } = render(); + const { result } = render(); // It starts from a loading state expect(result.current.isLoading).toEqual(true); @@ -63,7 +64,7 @@ describe('useIntegrations', () => { expect(result.current.isError).toEqual(false); // When fetchRuleExecutionEvents returns - await waitForNextUpdate(); + await waitFor(() => null); // It switches to a success state expect(result.current.isLoading).toEqual(false); @@ -105,7 +106,7 @@ describe('useIntegrations', () => { const exception = new Error('Boom!'); jest.spyOn(fleetIntegrationsApi, 'fetchAllIntegrations').mockRejectedValue(exception); - const { result, waitForNextUpdate } = render(); + const { result } = render(); // It starts from a loading state expect(result.current.isLoading).toEqual(true); @@ -113,7 +114,7 @@ describe('useIntegrations', () => { expect(result.current.isError).toEqual(false); // When fetchRuleExecutionEvents throws - await waitForNextUpdate(); + await waitFor(() => null); // It switches to an error state expect(result.current.isLoading).toEqual(false); diff --git a/x-pack/plugins/security_solution/public/detections/components/user_info/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/user_info/index.test.tsx index af0aacc7025ae..080aad1dd2700 100644 --- a/x-pack/plugins/security_solution/public/detections/components/user_info/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/user_info/index.test.tsx @@ -6,7 +6,8 @@ */ import React from 'react'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useUserInfo, ManageUserInfo } from '.'; import type { Capabilities } from '@kbn/core/public'; @@ -38,30 +39,27 @@ describe('useUserInfo', () => { jest.spyOn(sourcererSelectors, 'signalIndexMappingOutdated').mockReturnValue(null); }); it('returns default state', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useUserInfo(), { - wrapper: TestProviders, - }); - await waitForNextUpdate(); + const { result } = renderHook(() => useUserInfo(), { + wrapper: TestProviders, + }); + await waitFor(() => null); - expect(result.all).toHaveLength(1); - expect(result.current).toEqual({ - canUserCRUD: null, - canUserREAD: null, - hasEncryptionKey: null, - hasIndexManage: null, - hasIndexMaintenance: null, - hasIndexWrite: null, - hasIndexRead: null, - hasIndexUpdateDelete: null, - isAuthenticated: null, - isSignalIndexExists: null, - loading: true, - signalIndexName: null, - signalIndexMappingOutdated: null, - }); - expect(result.error).toBeUndefined(); + expect(result.current).toEqual({ + canUserCRUD: null, + canUserREAD: null, + hasEncryptionKey: null, + hasIndexManage: null, + hasIndexMaintenance: null, + hasIndexWrite: null, + hasIndexRead: null, + hasIndexUpdateDelete: null, + isAuthenticated: null, + isSignalIndexExists: null, + loading: true, + signalIndexName: null, + signalIndexMappingOutdated: null, }); + expect(result.error).toBeUndefined(); }); it('calls createSignalIndex if signal index template is outdated', async () => { @@ -79,11 +77,10 @@ describe('useUserInfo', () => { ); - await act(async () => { - const { waitForNextUpdate } = renderHook(() => useUserInfo(), { wrapper }); - await waitForNextUpdate(); - await waitForNextUpdate(); - }); + + renderHook(() => useUserInfo(), { wrapper }); + await waitFor(() => null); + expect(spyOnGetSignalIndex).toHaveBeenCalledTimes(2); expect(spyOnCreateSignalIndex).toHaveBeenCalledTimes(1); }); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_alerts_privileges.test.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_alerts_privileges.test.tsx index 5411cada8dd64..d81f691ca11e8 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_alerts_privileges.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_alerts_privileges.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import produce from 'immer'; import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; import { useAppToastsMock } from '../../../../common/hooks/use_app_toasts.mock'; @@ -90,23 +91,19 @@ describe('useAlertsPrivileges', () => { }); test('init', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useAlertsPrivileges() - ); - await waitForNextUpdate(); - expect(result.current).toEqual({ - hasEncryptionKey: null, - hasIndexManage: null, - hasIndexRead: null, - hasIndexMaintenance: null, - hasIndexWrite: null, - hasIndexUpdateDelete: null, - hasKibanaCRUD: false, - hasKibanaREAD: false, - isAuthenticated: null, - loading: false, - }); + const { result } = renderHook(() => useAlertsPrivileges()); + await waitFor(() => null); + expect(result.current).toEqual({ + hasEncryptionKey: null, + hasIndexManage: null, + hasIndexRead: null, + hasIndexMaintenance: null, + hasIndexWrite: null, + hasIndexUpdateDelete: null, + hasKibanaCRUD: false, + hasKibanaREAD: false, + isAuthenticated: null, + loading: false, }); }); @@ -115,24 +112,19 @@ describe('useAlertsPrivileges', () => { draft.detectionEnginePrivileges.error = new Error('Something went wrong'); }); useUserPrivilegesMock.mockReturnValue(userPrivileges); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useAlertsPrivileges() - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - hasEncryptionKey: false, - hasIndexManage: false, - hasIndexMaintenance: false, - hasIndexRead: false, - hasIndexWrite: false, - hasIndexUpdateDelete: false, - hasKibanaCRUD: true, - hasKibanaREAD: true, - isAuthenticated: false, - loading: false, - }); + const { result } = renderHook(() => useAlertsPrivileges()); + await waitFor(() => null); + expect(result.current).toEqual({ + hasEncryptionKey: false, + hasIndexManage: false, + hasIndexMaintenance: false, + hasIndexRead: false, + hasIndexWrite: false, + hasIndexUpdateDelete: false, + hasKibanaCRUD: true, + hasKibanaREAD: true, + isAuthenticated: false, + loading: false, }); }); @@ -145,24 +137,19 @@ describe('useAlertsPrivileges', () => { }); useUserPrivilegesMock.mockReturnValue(userPrivileges); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useAlertsPrivileges() - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - hasEncryptionKey: true, - hasIndexManage: false, - hasIndexMaintenance: true, - hasIndexRead: true, - hasIndexWrite: true, - hasIndexUpdateDelete: true, - hasKibanaCRUD: true, - hasKibanaREAD: true, - isAuthenticated: true, - loading: false, - }); + const { result } = renderHook(() => useAlertsPrivileges()); + await waitFor(() => null); + expect(result.current).toEqual({ + hasEncryptionKey: true, + hasIndexManage: false, + hasIndexMaintenance: true, + hasIndexRead: true, + hasIndexWrite: true, + hasIndexUpdateDelete: true, + hasKibanaCRUD: true, + hasKibanaREAD: true, + isAuthenticated: true, + loading: false, }); }); @@ -172,24 +159,19 @@ describe('useAlertsPrivileges', () => { }); useUserPrivilegesMock.mockReturnValue(userPrivileges); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useAlertsPrivileges() - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - hasEncryptionKey: true, - hasIndexManage: true, - hasIndexMaintenance: true, - hasIndexRead: true, - hasIndexWrite: true, - hasIndexUpdateDelete: true, - hasKibanaCRUD: true, - hasKibanaREAD: true, - isAuthenticated: true, - loading: false, - }); + const { result } = renderHook(() => useAlertsPrivileges()); + await waitFor(() => null); + expect(result.current).toEqual({ + hasEncryptionKey: true, + hasIndexManage: true, + hasIndexMaintenance: true, + hasIndexRead: true, + hasIndexWrite: true, + hasIndexUpdateDelete: true, + hasKibanaCRUD: true, + hasKibanaREAD: true, + isAuthenticated: true, + loading: false, }); }); @@ -200,24 +182,19 @@ describe('useAlertsPrivileges', () => { }); useUserPrivilegesMock.mockReturnValue(userPrivileges); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useAlertsPrivileges() - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - hasEncryptionKey: true, - hasIndexManage: true, - hasIndexMaintenance: true, - hasIndexRead: true, - hasIndexWrite: true, - hasIndexUpdateDelete: true, - hasKibanaCRUD: false, - hasKibanaREAD: true, - isAuthenticated: true, - loading: false, - }); + const { result } = renderHook(() => useAlertsPrivileges()); + await waitFor(() => null); + expect(result.current).toEqual({ + hasEncryptionKey: true, + hasIndexManage: true, + hasIndexMaintenance: true, + hasIndexRead: true, + hasIndexWrite: true, + hasIndexUpdateDelete: true, + hasKibanaCRUD: false, + hasKibanaREAD: true, + isAuthenticated: true, + loading: false, }); }); @@ -228,24 +205,19 @@ describe('useAlertsPrivileges', () => { }); useUserPrivilegesMock.mockReturnValue(userPrivileges); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useAlertsPrivileges() - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - hasEncryptionKey: true, - hasIndexManage: true, - hasIndexMaintenance: true, - hasIndexRead: true, - hasIndexWrite: true, - hasIndexUpdateDelete: true, - hasKibanaCRUD: false, - hasKibanaREAD: false, - isAuthenticated: true, - loading: false, - }); + const { result } = renderHook(() => useAlertsPrivileges()); + await waitFor(() => null); + expect(result.current).toEqual({ + hasEncryptionKey: true, + hasIndexManage: true, + hasIndexMaintenance: true, + hasIndexRead: true, + hasIndexWrite: true, + hasIndexUpdateDelete: true, + hasKibanaCRUD: false, + hasKibanaREAD: false, + isAuthenticated: true, + loading: false, }); }); }); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_cases_from_alerts.test.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_cases_from_alerts.test.tsx index 01bbe8c807ec2..2da1af836e479 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_cases_from_alerts.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_cases_from_alerts.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useCasesFromAlerts } from './use_cases_from_alerts'; import * as api from './api'; import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; @@ -25,10 +26,8 @@ describe('useCasesFromAlerts hook', () => { it('returns an array of caseIds', async () => { const spyOnCases = jest.spyOn(api, 'getCaseIdsFromAlertId'); - const { result, waitForNextUpdate } = renderHook(() => - useCasesFromAlerts({ alertId: 'anAlertId' }) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useCasesFromAlerts({ alertId: 'anAlertId' })); + await waitFor(() => null); expect(spyOnCases).toHaveBeenCalledTimes(1); expect(result.current).toEqual({ loading: false, diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_query.test.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_query.test.tsx index 0e78f11a69a3e..98cc307e7488c 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_query.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_query.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import type { ReturnQueryAlerts } from './use_query'; import { useQueryAlerts } from './use_query'; import { ALERTS_QUERY_NAMES } from './constants'; @@ -28,93 +29,75 @@ describe('useQueryAlerts', () => { }); test('init', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - [object, string], - ReturnQueryAlerts - >(() => useQueryAlerts(defaultProps)); - await waitForNextUpdate(); - expect(result.current).toEqual({ - loading: false, - data: null, - response: '', - request: '', - setQuery: result.current.setQuery, - refetch: null, - }); + const { result } = renderHook, [object, string]>(() => + useQueryAlerts(defaultProps) + ); + expect(result.current).toEqual({ + loading: true, + data: null, + response: '', + request: '', + setQuery: result.current.setQuery, + refetch: null, }); }); test('fetch alerts data', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - [object, string], - ReturnQueryAlerts - >(() => useQueryAlerts(defaultProps)); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - loading: false, - data: alertsMock, - response: JSON.stringify(alertsMock, null, 2), - request: JSON.stringify({ index: [indexName] ?? [''], body: mockAlertsQuery }, null, 2), - setQuery: result.current.setQuery, - refetch: result.current.refetch, - }); + const { result } = renderHook, [object, string]>(() => + useQueryAlerts(defaultProps) + ); + await waitFor(() => null); + expect(result.current).toEqual({ + loading: false, + data: alertsMock, + response: JSON.stringify(alertsMock, null, 2), + request: JSON.stringify({ index: [indexName] ?? [''], body: mockAlertsQuery }, null, 2), + setQuery: result.current.setQuery, + refetch: result.current.refetch, }); }); test('re-fetch alerts data', async () => { const spyOnfetchQueryAlerts = jest.spyOn(api, 'fetchQueryAlerts'); - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - [object, string], - ReturnQueryAlerts - >(() => useQueryAlerts(defaultProps)); - await waitForNextUpdate(); - await waitForNextUpdate(); - if (result.current.refetch) { - result.current.refetch(); - } - await waitForNextUpdate(); - expect(spyOnfetchQueryAlerts).toHaveBeenCalledTimes(2); - }); + const { result } = renderHook, [object, string]>(() => + useQueryAlerts(defaultProps) + ); + await waitFor(() => null); + if (result.current.refetch) { + result.current.refetch(); + } + await waitFor(() => null); + expect(spyOnfetchQueryAlerts).toHaveBeenCalledTimes(2); }); test('fetch alert when index name changed', async () => { const spyOnfetchRules = jest.spyOn(api, 'fetchQueryAlerts'); - await act(async () => { - const { rerender, waitForNextUpdate } = renderHook< - [object, string], - ReturnQueryAlerts - >((args) => useQueryAlerts({ ...defaultProps, query: args[0], indexName: args[1] }), { + const { rerender } = renderHook, [object, string]>( + (args) => useQueryAlerts({ ...defaultProps, query: args[0], indexName: args[1] }), + { initialProps: [mockAlertsQuery, indexName], - }); - await waitForNextUpdate(); - await waitForNextUpdate(); - rerender([mockAlertsQuery, 'new-mock-index-name']); - await waitForNextUpdate(); - expect(spyOnfetchRules).toHaveBeenCalledTimes(2); - }); + } + ); + await waitFor(() => null); + rerender([mockAlertsQuery, 'new-mock-index-name']); + await waitFor(() => null); + expect(spyOnfetchRules).toHaveBeenCalledTimes(2); }); test('fetch alert when query object changed', async () => { const spyOnfetchRules = jest.spyOn(api, 'fetchQueryAlerts'); - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - [object, string], - ReturnQueryAlerts - >((args) => useQueryAlerts({ ...defaultProps, query: args[0], indexName: args[1] }), { + const { result } = renderHook, [object, string]>( + (args) => useQueryAlerts({ ...defaultProps, query: args[0], indexName: args[1] }), + { initialProps: [mockAlertsQuery, indexName], - }); - await waitForNextUpdate(); - await waitForNextUpdate(); - if (result.current.setQuery) { - result.current.setQuery({ ...mockAlertsQuery }); } - await waitForNextUpdate(); - expect(spyOnfetchRules).toHaveBeenCalledTimes(2); - }); + ); + await waitFor(() => null); + if (result.current.setQuery) { + result.current.setQuery({ ...mockAlertsQuery }); + } + await waitFor(() => null); + expect(spyOnfetchRules).toHaveBeenCalledTimes(2); }); test('if there is an error when fetching data, we should get back the init value for every properties', async () => { @@ -122,38 +105,31 @@ describe('useQueryAlerts', () => { spyOnGetUserPrivilege.mockImplementation(() => { throw new Error('Something went wrong, let see what happen'); }); - await act(async () => { - const { result, waitForNextUpdate } = renderHook>( - () => useQueryAlerts(defaultProps) - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - loading: false, - data: null, - response: '', - request: '', - setQuery: result.current.setQuery, - refetch: result.current.refetch, - }); + const { result } = renderHook, void>(() => + useQueryAlerts(defaultProps) + ); + await waitFor(() => null); + expect(result.current).toEqual({ + loading: false, + data: null, + response: '', + request: '', + setQuery: result.current.setQuery, + refetch: result.current.refetch, }); }); test('skip', async () => { const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); - await act(async () => { - const localProps = { ...defaultProps, skip: false }; - const { rerender, waitForNextUpdate } = renderHook< - [object, string], - ReturnQueryAlerts - >(() => useQueryAlerts(localProps)); - await waitForNextUpdate(); - await waitForNextUpdate(); + const localProps = { ...defaultProps, skip: false }; + const { rerender } = renderHook, [object, string]>(() => + useQueryAlerts(localProps) + ); + await waitFor(() => null); - localProps.skip = true; - act(() => rerender()); - act(() => rerender()); - expect(abortSpy).toHaveBeenCalledTimes(2); - }); + localProps.skip = true; + rerender(); + rerender(); + expect(abortSpy).toHaveBeenCalledTimes(2); }); }); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.test.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.test.ts index 7d44864681f0e..566af0c99fa23 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.test.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useRuleFromTimeline } from './use_rule_from_timeline'; import { useGetInitialUrlParamValue } from '../../../../common/utils/global_query_string/helpers'; @@ -116,9 +117,9 @@ describe('useRuleFromTimeline', () => { }); it('does not reset timeline sourcerer if it originally had same data view as the timeline used in the rule', async () => { - const { result, waitForNextUpdate } = renderHook(() => useRuleFromTimeline(setRuleQuery)); + const { result } = renderHook(() => useRuleFromTimeline(setRuleQuery)); expect(result.current.loading).toEqual(true); - await waitForNextUpdate(); + await waitFor(() => null); expect(setRuleQuery).toHaveBeenCalled(); expect(mockDispatch).toHaveBeenCalledTimes(2); }); @@ -147,9 +148,9 @@ describe('useRuleFromTimeline', () => { }); it('if timeline id in URL, set active timeline data view to from timeline data view', async () => { - const { result, waitForNextUpdate } = renderHook(() => useRuleFromTimeline(setRuleQuery)); + const { result } = renderHook(() => useRuleFromTimeline(setRuleQuery)); expect(result.current.loading).toEqual(true); - await waitForNextUpdate(); + await waitFor(() => null); expect(setRuleQuery).toHaveBeenCalled(); expect(mockDispatch).toHaveBeenCalledTimes(4); @@ -182,9 +183,9 @@ describe('useRuleFromTimeline', () => { (useGetInitialUrlParamValue as jest.Mock) .mockReturnValueOnce(() => timelineId) .mockReturnValue(() => undefined); - const { result, waitForNextUpdate } = renderHook(() => useRuleFromTimeline(setRuleQuery)); + const { result } = renderHook(() => useRuleFromTimeline(setRuleQuery)); expect(result.current.loading).toEqual(true); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.loading).toEqual(false); expect(setRuleQuery).toHaveBeenCalledWith({ index: ['awesome-*'], @@ -251,9 +252,9 @@ describe('useRuleFromTimeline', () => { (useGetInitialUrlParamValue as jest.Mock) .mockReturnValueOnce(() => undefined) .mockReturnValue(() => timelineId); - const { result, waitForNextUpdate } = renderHook(() => useRuleFromTimeline(setRuleQuery)); + const { result } = renderHook(() => useRuleFromTimeline(setRuleQuery)); expect(result.current.loading).toEqual(true); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.loading).toEqual(false); expect(setRuleQuery).toHaveBeenCalledWith({ index: ['awesome-*'], @@ -343,8 +344,8 @@ describe('useRuleFromTimeline', () => { }); it('resets timeline sourcerer if it originally had different data view from the timeline used in the rule', async () => { - const { waitForNextUpdate } = renderHook(() => useRuleFromTimeline(setRuleQuery)); - await waitForNextUpdate(); + renderHook(() => useRuleFromTimeline(setRuleQuery)); + await waitFor(() => null); expect(setRuleQuery).toHaveBeenCalled(); expect(mockDispatch).toHaveBeenNthCalledWith(4, { type: 'x-pack/security_solution/local/sourcerer/SET_SELECTED_DATA_VIEW', diff --git a/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_cell_actions.test.tsx b/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_cell_actions.test.tsx index c1600c73caa6a..04f8246ea33ca 100644 --- a/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_cell_actions.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_cell_actions.test.tsx @@ -17,7 +17,7 @@ import type { EuiDataGridRefProps, } from '@elastic/eui'; import { EuiButtonEmpty } from '@elastic/eui'; -import { render, screen } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; import type { ComponentProps, JSXElementConstructor, PropsWithChildren } from 'react'; import React from 'react'; import { makeAction } from '../../../common/components/cell_actions/mocks'; @@ -86,7 +86,7 @@ const TestProviderWithCustomStateAndActions = withCustomPropsAndCellActions({ describe('getUseCellActionsHook', () => { it('should render cell actions correctly for gridView view', async () => { - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => useCellActions({ columns: mockColumns as unknown as EuiDataGridColumn[], @@ -101,7 +101,7 @@ describe('getUseCellActionsHook', () => { } ); - await waitForNextUpdate(); + await waitFor(() => null); const cellAction = result.current.getCellActions('host.name', 0)[0]; @@ -111,7 +111,7 @@ describe('getUseCellActionsHook', () => { }); it('should not render cell actions correctly for eventRendered view', async () => { - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => useCellActions({ columns: mockColumns as unknown as EuiDataGridColumn[], @@ -128,7 +128,7 @@ describe('getUseCellActionsHook', () => { const cellAction = result.current.getCellActions('host.name', 0); - await waitForNextUpdate(); + await waitFor(() => null); expect(cellAction).toHaveLength(0); }); diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/use_case_items.test.ts b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/use_case_items.test.ts index 9076c0daa7da6..fa9940b8051c7 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/use_case_items.test.ts +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/use_case_items.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { mockCasesResult, parsedCasesItems } from './mock_data'; import { useCaseItems } from './use_case_items'; @@ -32,6 +33,7 @@ const mockKibana = { }, }, }; + jest.mock('../../../../common/lib/kibana', () => ({ useKibana: () => mockKibana, })); @@ -63,9 +65,9 @@ describe('useCaseItems', () => { }); it('should return default values', async () => { - const { result, waitForNextUpdate } = renderUseCaseItems(); + const { result } = renderUseCaseItems(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual({ items: [], @@ -86,9 +88,9 @@ describe('useCaseItems', () => { it('should return parsed items', async () => { mockCasesApi.mockReturnValue(mockCasesResult); - const { result, waitForNextUpdate } = renderUseCaseItems(); + const { result } = renderUseCaseItems(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual({ items: parsedCasesItems, @@ -99,17 +101,17 @@ describe('useCaseItems', () => { test('it should call setQuery when fetching', async () => { mockCasesApi.mockReturnValue(mockCasesResult); - const { waitForNextUpdate } = renderUseCaseItems(); + renderUseCaseItems(); - await waitForNextUpdate(); + await waitFor(() => null); expect(mockSetQuery).toHaveBeenCalled(); }); test('it should call deleteQuery when unmounting', async () => { - const { waitForNextUpdate, unmount } = renderUseCaseItems(); + const { unmount } = renderUseCaseItems(); - await waitForNextUpdate(); + await waitFor(() => null); act(() => { unmount(); @@ -124,9 +126,9 @@ describe('useCaseItems', () => { mockDateNow.mockReturnValueOnce(dateNow); mockCasesApi.mockReturnValue(mockCasesResult); - const { result, waitForNextUpdate } = renderUseCaseItems(); + const { result } = renderUseCaseItems(); - await waitForNextUpdate(); + await waitFor(() => null); expect(mockDateNow).toHaveBeenCalled(); expect(result.current).toEqual({ diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_cases_mttr.test.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_cases_mttr.test.tsx index 8658571d03901..5aee9906607ed 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_cases_mttr.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_cases_mttr.test.tsx @@ -8,7 +8,8 @@ import React from 'react'; import type { UseCasesMttr } from './use_cases_mttr'; import { useCasesMttr } from './use_cases_mttr'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { TestProviders } from '../../../../../common/mock'; import { useKibana as useKibanaMock } from '../../../../../common/lib/kibana/__mocks__'; import * as i18n from '../translations'; @@ -53,142 +54,127 @@ describe('useCasesMttr', () => { afterEach(() => { jest.clearAllMocks(); }); + it('loads initial state', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useCasesMttr(props), { - wrapper: wrapperContainer, - }); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '-', - isLoading: true, - percentage: { - percent: null, - color: 'hollow', - note: i18n.NO_DATA('case'), - }, - ...basicData, - }); + const { result } = renderHook(() => useCasesMttr(props), { + wrapper: wrapperContainer, + }); + + expect(result.current).toEqual({ + stat: '-', + isLoading: true, + percentage: { + percent: null, + color: 'hollow', + note: i18n.NO_DATA('case'), + }, + ...basicData, }); }); + it('finds positive percentage change', async () => { useKibanaMock().services.cases.api.cases.getCasesMetrics = mockGetCasesMetrics .mockReturnValueOnce({ mttr: 10000 }) .mockReturnValue({ mttr: 5000 }); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useCasesMttr(props), { - wrapper: wrapperContainer, - }); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '2h', - isLoading: false, - percentage: { - percent: '+100.0%', - color: 'danger', - note: i18n.STAT_DIFFERENCE({ - upOrDown: 'up', - percentageChange: '100.0%', - stat: '1h', - statType: 'case resolution time', - }), - }, - ...basicData, - }); + const { result } = renderHook(() => useCasesMttr(props), { + wrapper: wrapperContainer, + }); + await waitFor(() => null); + expect(result.current).toEqual({ + stat: '2h', + isLoading: false, + percentage: { + percent: '+100.0%', + color: 'danger', + note: i18n.STAT_DIFFERENCE({ + upOrDown: 'up', + percentageChange: '100.0%', + stat: '1h', + statType: 'case resolution time', + }), + }, + ...basicData, }); }); it('finds negative percentage change', async () => { useKibanaMock().services.cases.api.cases.getCasesMetrics = mockGetCasesMetrics .mockReturnValueOnce({ mttr: 5000 }) .mockReturnValue({ mttr: 10000 }); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useCasesMttr(props), { - wrapper: wrapperContainer, - }); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '1h', - isLoading: false, - percentage: { - percent: '-50.0%', - color: 'success', - note: i18n.STAT_DIFFERENCE({ - upOrDown: 'down', - percentageChange: '50.0%', - stat: '2h', - statType: 'case resolution time', - }), - }, - ...basicData, - }); + const { result } = renderHook(() => useCasesMttr(props), { + wrapper: wrapperContainer, + }); + await waitFor(() => null); + expect(result.current).toEqual({ + stat: '1h', + isLoading: false, + percentage: { + percent: '-50.0%', + color: 'success', + note: i18n.STAT_DIFFERENCE({ + upOrDown: 'down', + percentageChange: '50.0%', + stat: '2h', + statType: 'case resolution time', + }), + }, + ...basicData, }); }); it('finds zero percentage change', async () => { useKibanaMock().services.cases.api.cases.getCasesMetrics = mockGetCasesMetrics.mockReturnValue({ mttr: 10000, }); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useCasesMttr(props), { - wrapper: wrapperContainer, - }); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '2h', - isLoading: false, - percentage: { - percent: '0.0%', - color: 'hollow', - note: i18n.NO_CHANGE('case resolution time'), - }, - ...basicData, - }); + const { result } = renderHook(() => useCasesMttr(props), { + wrapper: wrapperContainer, + }); + await waitFor(() => null); + expect(result.current).toEqual({ + stat: '2h', + isLoading: false, + percentage: { + percent: '0.0%', + color: 'hollow', + note: i18n.NO_CHANGE('case resolution time'), + }, + ...basicData, }); }); it('handles null mttr - current time range', async () => { useKibanaMock().services.cases.api.cases.getCasesMetrics = mockGetCasesMetrics .mockReturnValueOnce({ mttr: null }) .mockReturnValue({ mttr: 10000 }); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useCasesMttr(props), { - wrapper: wrapperContainer, - }); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '-', - isLoading: false, - percentage: { - percent: null, - color: 'hollow', - note: i18n.NO_DATA_CURRENT('case'), - }, - ...basicData, - }); + const { result } = renderHook(() => useCasesMttr(props), { + wrapper: wrapperContainer, + }); + await waitFor(() => null); + expect(result.current).toEqual({ + stat: '-', + isLoading: false, + percentage: { + percent: null, + color: 'hollow', + note: i18n.NO_DATA_CURRENT('case'), + }, + ...basicData, }); }); it('handles null mttr - compare time range', async () => { useKibanaMock().services.cases.api.cases.getCasesMetrics = mockGetCasesMetrics .mockReturnValueOnce({ mttr: 10000 }) .mockReturnValue({ mttr: null }); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useCasesMttr(props), { - wrapper: wrapperContainer, - }); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '2h', - isLoading: false, - percentage: { - percent: null, - color: 'hollow', - note: i18n.NO_DATA_COMPARE('case'), - }, - ...basicData, - }); + const { result } = renderHook(() => useCasesMttr(props), { + wrapper: wrapperContainer, + }); + await waitFor(() => null); + expect(result.current).toEqual({ + stat: '2h', + isLoading: false, + percentage: { + percent: null, + color: 'hollow', + note: i18n.NO_DATA_COMPARE('case'), + }, + ...basicData, }); }); it('handles null mttr - current & compare time range', async () => { @@ -198,40 +184,37 @@ describe('useCasesMttr', () => { .mockReturnValue({ mttr: null, }); - await act(async () => { - let ourProps = props; - const { result, rerender, waitForNextUpdate } = renderHook(() => useCasesMttr(ourProps), { - wrapper: wrapperContainer, - }); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '2h', - isLoading: false, - percentage: { - percent: '0.0%', - color: 'hollow', - note: i18n.NO_CHANGE('case resolution time'), - }, - ...basicData, - }); - ourProps = { - ...props, - from: '2020-07-08T08:20:18.966Z', - to: '2020-07-09T08:20:18.966Z', - }; - rerender(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '-', - isLoading: false, - percentage: { - percent: null, - color: 'hollow', - note: i18n.NO_DATA('case'), - }, - ...basicData, - }); + let ourProps = props; + const { result, rerender } = renderHook(() => useCasesMttr(ourProps), { + wrapper: wrapperContainer, + }); + await waitFor(() => null); + expect(result.current).toEqual({ + stat: '2h', + isLoading: false, + percentage: { + percent: '0.0%', + color: 'hollow', + note: i18n.NO_CHANGE('case resolution time'), + }, + ...basicData, + }); + ourProps = { + ...props, + from: '2020-07-08T08:20:18.966Z', + to: '2020-07-09T08:20:18.966Z', + }; + rerender(); + await waitFor(() => null); + expect(result.current).toEqual({ + stat: '-', + isLoading: false, + percentage: { + percent: null, + color: 'hollow', + note: i18n.NO_DATA('case'), + }, + ...basicData, }); }); it('handles undefined mttr - current & compare time range', async () => { @@ -241,41 +224,45 @@ describe('useCasesMttr', () => { .mockReturnValue({ mttr: undefined, }); - await act(async () => { - let ourProps = props; - const { result, rerender, waitForNextUpdate } = renderHook(() => useCasesMttr(ourProps), { - wrapper: wrapperContainer, - }); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '2h', - isLoading: false, - percentage: { - percent: '0.0%', - color: 'hollow', - note: i18n.NO_CHANGE('case resolution time'), - }, - ...basicData, - }); - ourProps = { - ...props, - from: '2020-07-08T08:20:18.966Z', - to: '2020-07-09T08:20:18.966Z', - }; + let ourProps = props; + const { result, rerender } = renderHook(() => useCasesMttr(ourProps), { + wrapper: wrapperContainer, + }); + + await waitFor(() => null); + + expect(result.current).toEqual({ + stat: '2h', + isLoading: false, + percentage: { + percent: '0.0%', + color: 'hollow', + note: i18n.NO_CHANGE('case resolution time'), + }, + ...basicData, + }); + + ourProps = { + ...props, + from: '2020-07-08T08:20:18.966Z', + to: '2020-07-09T08:20:18.966Z', + }; + + act(() => { rerender(); rerender(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '-', - isLoading: false, - percentage: { - percent: null, - color: 'hollow', - note: i18n.NO_DATA('case'), - }, - ...basicData, - }); + }); + + await waitFor(() => null); + expect(result.current).toEqual({ + stat: '-', + isLoading: false, + percentage: { + percent: null, + color: 'hollow', + note: i18n.NO_DATA('case'), + }, + ...basicData, }); }); }); diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_critical_alerts.test.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_critical_alerts.test.tsx index 7a63e93e6c765..0576891c32d1a 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_critical_alerts.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_critical_alerts.test.tsx @@ -8,7 +8,8 @@ import React from 'react'; import type { UseCriticalAlerts } from './use_critical_alerts'; import { useCriticalAlerts } from './use_critical_alerts'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { TestProviders } from '../../../../../common/mock'; import * as i18n from '../translations'; import { useQueryAlerts } from '../../../../../detections/containers/detection_engine/alerts/use_query'; @@ -66,21 +67,19 @@ describe('useCriticalAlerts', () => { jest.clearAllMocks(); }); it('loads initial state', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useCriticalAlerts(props), { - wrapper: wrapperContainer, - }); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '-', - isLoading: true, - percentage: { - percent: null, - color: 'hollow', - note: i18n.NO_DATA('alerts'), - }, - ...basicData, - }); + const { result } = renderHook(() => useCriticalAlerts(props), { + wrapper: wrapperContainer, + }); + + expect(result.current).toEqual({ + stat: '-', + isLoading: true, + percentage: { + percent: null, + color: 'hollow', + note: i18n.NO_DATA('alerts'), + }, + ...basicData, }); }); it('finds positive percentage change', async () => { @@ -95,27 +94,24 @@ describe('useCriticalAlerts', () => { ...basicReturn, } ); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useCriticalAlerts(props), { - wrapper: wrapperContainer, - }); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '100', - isLoading: false, - percentage: { - percent: '+100.0%', - color: 'danger', - note: i18n.STAT_DIFFERENCE({ - upOrDown: 'up', - percentageChange: '100.0%', - stat: '50', - statType: 'open critical alert count', - }), - }, - ...basicData, - }); + const { result } = renderHook(() => useCriticalAlerts(props), { + wrapper: wrapperContainer, + }); + await waitFor(() => null); + expect(result.current).toEqual({ + stat: '100', + isLoading: false, + percentage: { + percent: '+100.0%', + color: 'danger', + note: i18n.STAT_DIFFERENCE({ + upOrDown: 'up', + percentageChange: '100.0%', + stat: '50', + statType: 'open critical alert count', + }), + }, + ...basicData, }); }); it('finds negative percentage change', async () => { @@ -130,27 +126,24 @@ describe('useCriticalAlerts', () => { ...basicReturn, } ); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useCriticalAlerts(props), { - wrapper: wrapperContainer, - }); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '50', - isLoading: false, - percentage: { - percent: '-50.0%', - color: 'success', - note: i18n.STAT_DIFFERENCE({ - upOrDown: 'down', - percentageChange: '50.0%', - stat: '100', - statType: 'open critical alert count', - }), - }, - ...basicData, - }); + const { result } = renderHook(() => useCriticalAlerts(props), { + wrapper: wrapperContainer, + }); + await waitFor(() => null); + expect(result.current).toEqual({ + stat: '50', + isLoading: false, + percentage: { + percent: '-50.0%', + color: 'success', + note: i18n.STAT_DIFFERENCE({ + upOrDown: 'down', + percentageChange: '50.0%', + stat: '100', + statType: 'open critical alert count', + }), + }, + ...basicData, }); }); it('finds zero percentage change', async () => { @@ -158,22 +151,19 @@ describe('useCriticalAlerts', () => { data: { aggregations: { open: { critical: { doc_count: 100 } } } }, ...basicReturn, })); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useCriticalAlerts(props), { - wrapper: wrapperContainer, - }); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '100', - isLoading: false, - percentage: { - percent: '0.0%', - color: 'hollow', - note: i18n.NO_CHANGE('open critical alert count'), - }, - ...basicData, - }); + const { result } = renderHook(() => useCriticalAlerts(props), { + wrapper: wrapperContainer, + }); + await waitFor(() => null); + expect(result.current).toEqual({ + stat: '100', + isLoading: false, + percentage: { + percent: '0.0%', + color: 'hollow', + note: i18n.NO_CHANGE('open critical alert count'), + }, + ...basicData, }); }); it('handles null data - current time range', async () => { @@ -188,22 +178,19 @@ describe('useCriticalAlerts', () => { ...basicReturn, } ); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useCriticalAlerts(props), { - wrapper: wrapperContainer, - }); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '-', - isLoading: false, - percentage: { - percent: null, - color: 'hollow', - note: i18n.NO_DATA_CURRENT('alerts'), - }, - ...basicData, - }); + const { result } = renderHook(() => useCriticalAlerts(props), { + wrapper: wrapperContainer, + }); + await waitFor(() => null); + expect(result.current).toEqual({ + stat: '-', + isLoading: false, + percentage: { + percent: null, + color: 'hollow', + note: i18n.NO_DATA_CURRENT('alerts'), + }, + ...basicData, }); }); it('handles null data - compare time range', async () => { @@ -218,22 +205,19 @@ describe('useCriticalAlerts', () => { ...basicReturn, } ); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useCriticalAlerts(props), { - wrapper: wrapperContainer, - }); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '100', - isLoading: false, - percentage: { - percent: null, - color: 'hollow', - note: i18n.NO_DATA_COMPARE('alerts'), - }, - ...basicData, - }); + const { result } = renderHook(() => useCriticalAlerts(props), { + wrapper: wrapperContainer, + }); + await waitFor(() => null); + expect(result.current).toEqual({ + stat: '100', + isLoading: false, + percentage: { + percent: null, + color: 'hollow', + note: i18n.NO_DATA_COMPARE('alerts'), + }, + ...basicData, }); }); it('handles null data - current & compare time range', async () => { @@ -249,45 +233,40 @@ describe('useCriticalAlerts', () => { ...basicReturn, } ); - await act(async () => { - let ourProps = props; - const { result, rerender, waitForNextUpdate } = renderHook( - () => useCriticalAlerts(ourProps), - { - wrapper: wrapperContainer, - } - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '100', - isLoading: false, - percentage: { - percent: '0.0%', - color: 'hollow', - note: i18n.NO_CHANGE('open critical alert count'), - }, - ...basicData, - }); - ourProps = { - ...props, - from: '2020-09-08T08:20:18.966Z', - to: '2020-09-09T08:20:18.966Z', - fromCompare: '2020-09-07T08:20:18.966Z', - toCompare: '2020-09-08T08:20:18.966Z', - }; - rerender(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '-', - isLoading: false, - percentage: { - percent: null, - color: 'hollow', - note: i18n.NO_DATA('alerts'), - }, - ...basicData, - }); + let ourProps = props; + const { result, rerender } = renderHook(() => useCriticalAlerts(ourProps), { + wrapper: wrapperContainer, + }); + await waitFor(() => null); + await waitFor(() => null); + expect(result.current).toEqual({ + stat: '100', + isLoading: false, + percentage: { + percent: '0.0%', + color: 'hollow', + note: i18n.NO_CHANGE('open critical alert count'), + }, + ...basicData, + }); + ourProps = { + ...props, + from: '2020-09-08T08:20:18.966Z', + to: '2020-09-09T08:20:18.966Z', + fromCompare: '2020-09-07T08:20:18.966Z', + toCompare: '2020-09-08T08:20:18.966Z', + }; + rerender(); + await waitFor(() => null); + expect(result.current).toEqual({ + stat: '-', + isLoading: false, + percentage: { + percent: null, + color: 'hollow', + note: i18n.NO_DATA('alerts'), + }, + ...basicData, }); }); it('handles undefined data - current & compare time range', async () => { @@ -303,45 +282,39 @@ describe('useCriticalAlerts', () => { ...basicReturn, } ); - await act(async () => { - let ourProps = props; - const { result, rerender, waitForNextUpdate } = renderHook( - () => useCriticalAlerts(ourProps), - { - wrapper: wrapperContainer, - } - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '100', - isLoading: false, - percentage: { - percent: '0.0%', - color: 'hollow', - note: i18n.NO_CHANGE('open critical alert count'), - }, - ...basicData, - }); - ourProps = { - ...props, - from: '2020-09-08T08:20:18.966Z', - to: '2020-09-09T08:20:18.966Z', - fromCompare: '2020-09-07T08:20:18.966Z', - toCompare: '2020-09-08T08:20:18.966Z', - }; - rerender(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stat: '-', - isLoading: false, - percentage: { - percent: null, - color: 'hollow', - note: i18n.NO_DATA('alerts'), - }, - ...basicData, - }); + let ourProps = props; + const { result, rerender } = renderHook(() => useCriticalAlerts(ourProps), { + wrapper: wrapperContainer, + }); + await waitFor(() => null); + expect(result.current).toEqual({ + stat: '100', + isLoading: false, + percentage: { + percent: '0.0%', + color: 'hollow', + note: i18n.NO_CHANGE('open critical alert count'), + }, + ...basicData, + }); + ourProps = { + ...props, + from: '2020-09-08T08:20:18.966Z', + to: '2020-09-09T08:20:18.966Z', + fromCompare: '2020-09-07T08:20:18.966Z', + toCompare: '2020-09-08T08:20:18.966Z', + }; + rerender(); + await waitFor(() => null); + expect(result.current).toEqual({ + stat: '-', + isLoading: false, + percentage: { + percent: null, + color: 'hollow', + note: i18n.NO_DATA('alerts'), + }, + ...basicData, }); }); }); diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_soc_trends.test.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_soc_trends.test.tsx index b008668f9865a..5eb7512e4ad30 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_soc_trends.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_soc_trends.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { useSocTrends } from './use_soc_trends'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; import { TestProviders } from '../../../../../common/mock'; import { useGlobalTime } from '../../../../../common/containers/use_global_time'; import * as i18n from '../translations'; @@ -42,46 +42,43 @@ describe('useSocTrends', () => { jest.clearAllMocks(); }); it('loads initial state', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook( - () => useSocTrends({ skip: false, signalIndexName: '.alerts-default' }), + const { result } = renderHook( + () => useSocTrends({ skip: false, signalIndexName: '.alerts-default' }), + { + wrapper: wrapperContainer, + } + ); + expect(result.current).toEqual({ + stats: [ { - wrapper: wrapperContainer, - } - ); - await waitForNextUpdate(); - expect(result.current).toEqual({ - stats: [ - { - stat: '-', - isLoading: true, - percentage: { - percent: null, - color: 'hollow', - note: i18n.NO_DATA('case'), - }, - testRef: 'casesMttr', - title: i18n.CASES_MTTR_STAT, - description: i18n.CASES_MTTR_DESCRIPTION, - updatedAt: dateNow, + stat: '-', + isLoading: true, + percentage: { + percent: null, + color: 'hollow', + note: i18n.NO_DATA('case'), }, - { - stat: '-', - isLoading: true, - percentage: { - percent: null, - color: 'hollow', - note: i18n.NO_DATA('alerts'), - }, - testRef: 'criticalAlerts', - title: i18n.CRITICAL_ALERTS_STAT, - description: i18n.CRITICAL_ALERTS_DESCRIPTION, - updatedAt: dateNow, + testRef: 'casesMttr', + title: i18n.CASES_MTTR_STAT, + description: i18n.CASES_MTTR_DESCRIPTION, + updatedAt: dateNow, + }, + { + stat: '-', + isLoading: true, + percentage: { + percent: null, + color: 'hollow', + note: i18n.NO_DATA('alerts'), }, - ], - isUpdating: true, - latestUpdate: dateNow, - }); + testRef: 'criticalAlerts', + title: i18n.CRITICAL_ALERTS_STAT, + description: i18n.CRITICAL_ALERTS_DESCRIPTION, + updatedAt: dateNow, + }, + ], + isUpdating: true, + latestUpdate: dateNow, }); }); }); diff --git a/x-pack/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx b/x-pack/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx index 8b0150efa6126..214426fe20d4d 100644 --- a/x-pack/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx +++ b/x-pack/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx @@ -159,28 +159,23 @@ describe('Sourcerer Hooks', () => { mockUseUserInfo.mockImplementation(() => userInfoState); }); it('initializes loading default and timeline index patterns', async () => { - await act(async () => { - const { rerender, waitForNextUpdate } = renderHook, void>( - () => useInitSourcerer(), - { - wrapper: ({ children }) => {children}, - } - ); - await waitForNextUpdate(); - rerender(); - expect(mockDispatch).toBeCalledTimes(3); - expect(mockDispatch.mock.calls[0][0]).toEqual({ - type: 'x-pack/security_solution/local/sourcerer/SET_DATA_VIEW_LOADING', - payload: { id: 'security-solution', loading: true }, - }); - expect(mockDispatch.mock.calls[1][0]).toEqual({ - type: 'x-pack/security_solution/local/sourcerer/SET_SELECTED_DATA_VIEW', - payload: { - id: 'timeline', - selectedDataViewId: 'security-solution', - selectedPatterns: ['.siem-signals-spacename', ...DEFAULT_INDEX_PATTERN], - }, - }); + const { rerender } = renderHook(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, + }); + await waitFor(() => null); + rerender(); + expect(mockDispatch).toBeCalledTimes(3); + expect(mockDispatch.mock.calls[0][0]).toEqual({ + type: 'x-pack/security_solution/local/sourcerer/SET_DATA_VIEW_LOADING', + payload: { id: 'security-solution', loading: true }, + }); + expect(mockDispatch.mock.calls[1][0]).toEqual({ + type: 'x-pack/security_solution/local/sourcerer/SET_SELECTED_DATA_VIEW', + payload: { + id: 'timeline', + selectedDataViewId: 'security-solution', + selectedPatterns: ['.siem-signals-spacename', ...DEFAULT_INDEX_PATTERN], + }, }); }); it('sets signal index name', async () => { @@ -202,47 +197,42 @@ describe('Sourcerer Hooks', () => { }, }, }); - await act(async () => { - mockUseUserInfo.mockImplementation(() => ({ - ...userInfoState, - loading: false, - signalIndexName: mockSourcererState.signalIndexName, - })); - const { rerender, waitForNextUpdate } = renderHook, void>( - () => useInitSourcerer(), - { - wrapper: ({ children }) => {children}, - } - ); - await waitForNextUpdate(); - rerender(); - await waitFor(() => { - expect(mockDispatch.mock.calls[3][0]).toEqual({ - type: 'x-pack/security_solution/local/sourcerer/SET_SOURCERER_SCOPE_LOADING', - payload: { loading: true }, - }); - expect(mockDispatch.mock.calls[4][0]).toEqual({ - type: 'x-pack/security_solution/local/sourcerer/SET_SIGNAL_INDEX_NAME', - payload: { signalIndexName: mockSourcererState.signalIndexName }, - }); - expect(mockDispatch.mock.calls[5][0]).toEqual({ - type: 'x-pack/security_solution/local/sourcerer/SET_DATA_VIEW_LOADING', - payload: { - id: mockSourcererState.defaultDataView.id, - loading: true, - }, - }); - expect(mockDispatch.mock.calls[6][0]).toEqual({ - type: 'x-pack/security_solution/local/sourcerer/SET_SOURCERER_DATA_VIEWS', - payload: mockNewDataViews, - }); - expect(mockDispatch.mock.calls[7][0]).toEqual({ - type: 'x-pack/security_solution/local/sourcerer/SET_SOURCERER_SCOPE_LOADING', - payload: { loading: false }, - }); - expect(mockDispatch).toHaveBeenCalledTimes(8); - expect(mockSearch).toHaveBeenCalledTimes(2); + mockUseUserInfo.mockImplementation(() => ({ + ...userInfoState, + loading: false, + signalIndexName: mockSourcererState.signalIndexName, + })); + const { rerender } = renderHook(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, + }); + await waitFor(() => null); + rerender(); + await waitFor(() => { + expect(mockDispatch.mock.calls[3][0]).toEqual({ + type: 'x-pack/security_solution/local/sourcerer/SET_SOURCERER_SCOPE_LOADING', + payload: { loading: true }, + }); + expect(mockDispatch.mock.calls[4][0]).toEqual({ + type: 'x-pack/security_solution/local/sourcerer/SET_SIGNAL_INDEX_NAME', + payload: { signalIndexName: mockSourcererState.signalIndexName }, + }); + expect(mockDispatch.mock.calls[5][0]).toEqual({ + type: 'x-pack/security_solution/local/sourcerer/SET_DATA_VIEW_LOADING', + payload: { + id: mockSourcererState.defaultDataView.id, + loading: true, + }, + }); + expect(mockDispatch.mock.calls[6][0]).toEqual({ + type: 'x-pack/security_solution/local/sourcerer/SET_SOURCERER_DATA_VIEWS', + payload: mockNewDataViews, + }); + expect(mockDispatch.mock.calls[7][0]).toEqual({ + type: 'x-pack/security_solution/local/sourcerer/SET_SOURCERER_SCOPE_LOADING', + payload: { loading: false }, }); + expect(mockDispatch).toHaveBeenCalledTimes(8); + expect(mockSearch).toHaveBeenCalledTimes(2); }); }); @@ -258,7 +248,7 @@ describe('Sourcerer Hooks', () => { }) ); - renderHook, void>(() => useInitSourcerer(), { + renderHook>(() => useInitSourcerer(), { wrapper: ({ children }) => {children}, }); @@ -278,7 +268,7 @@ describe('Sourcerer Hooks', () => { onInitialize(null) ); - renderHook, void>(() => useInitSourcerer(), { + renderHook>(() => useInitSourcerer(), { wrapper: ({ children }) => {children}, }); @@ -302,16 +292,14 @@ describe('Sourcerer Hooks', () => { }, }, }); - await act(async () => { - renderHook, void>(() => useInitSourcerer(), { - wrapper: ({ children }) => {children}, - }); + renderHook>(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, + }); - await waitFor(() => { - expect(mockAddWarning).toHaveBeenNthCalledWith(1, { - text: 'Users with write permission need to access the Elastic Security app to initialize the app source data.', - title: 'Write role required to generate data', - }); + await waitFor(() => { + expect(mockAddWarning).toHaveBeenNthCalledWith(1, { + text: 'Users with write permission need to access the Elastic Security app to initialize the app source data.', + title: 'Write role required to generate data', }); }); }); @@ -333,27 +321,25 @@ describe('Sourcerer Hooks', () => { }, }, }); - await act(async () => { - mockUseUserInfo.mockImplementation(() => ({ - ...userInfoState, - loading: false, - signalIndexName: mockSourcererState.signalIndexName, - })); - const { rerender, waitForNextUpdate } = renderHook, void>( - () => useInitSourcerer(), - { - wrapper: ({ children }) => {children}, - } - ); - await waitForNextUpdate(); - rerender(); + mockUseUserInfo.mockImplementation(() => ({ + ...userInfoState, + loading: false, + signalIndexName: mockSourcererState.signalIndexName, + })); - await waitFor(() => { - expect(mockCreateSourcererDataView).toHaveBeenCalled(); - expect(mockAddError).not.toHaveBeenCalled(); - }); + const { rerender } = renderHook(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, }); + + await waitFor(() => null); + + rerender(); + + await waitFor(() => null); + + expect(mockCreateSourcererDataView).toHaveBeenCalled(); + expect(mockAddError).not.toHaveBeenCalled(); }); it('does call addError if updateSourcererDataView receives a non-abort error', async () => { @@ -375,66 +361,54 @@ describe('Sourcerer Hooks', () => { }, }, }); - await act(async () => { - mockUseUserInfo.mockImplementation(() => ({ - ...userInfoState, - loading: false, - signalIndexName: mockSourcererState.signalIndexName, - })); - const { rerender, waitForNextUpdate } = renderHook, void>( - () => useInitSourcerer(), - { - wrapper: ({ children }) => {children}, - } - ); + mockUseUserInfo.mockImplementation(() => ({ + ...userInfoState, + loading: false, + signalIndexName: mockSourcererState.signalIndexName, + })); + const { rerender } = renderHook(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, + }); - await waitForNextUpdate(); - rerender(); + await waitFor(() => null); + rerender(); - await waitFor(() => { - expect(mockAddError).toHaveBeenCalled(); - }); + await waitFor(() => { + expect(mockAddError).toHaveBeenCalled(); }); }); it('handles detections page', async () => { - await act(async () => { - mockUseUserInfo.mockImplementation(() => ({ - ...userInfoState, - signalIndexName: mockSourcererState.signalIndexName, - isSignalIndexExists: true, - })); - const { rerender, waitForNextUpdate } = renderHook, void>( - () => useInitSourcerer(SourcererScopeName.detections), - { - wrapper: ({ children }) => {children}, - } - ); - await waitForNextUpdate(); - rerender(); - expect(mockDispatch.mock.calls[3][0]).toEqual({ - type: 'x-pack/security_solution/local/sourcerer/SET_SELECTED_DATA_VIEW', - payload: { - id: 'detections', - selectedDataViewId: mockSourcererState.defaultDataView.id, - selectedPatterns: [mockSourcererState.signalIndexName], - }, - }); + mockUseUserInfo.mockImplementation(() => ({ + ...userInfoState, + signalIndexName: mockSourcererState.signalIndexName, + isSignalIndexExists: true, + })); + const { rerender } = renderHook( + () => useInitSourcerer(SourcererScopeName.detections), + { + wrapper: ({ children }) => {children}, + } + ); + await waitFor(() => null); + rerender(); + expect(mockDispatch.mock.calls[3][0]).toEqual({ + type: 'x-pack/security_solution/local/sourcerer/SET_SELECTED_DATA_VIEW', + payload: { + id: 'detections', + selectedDataViewId: mockSourcererState.defaultDataView.id, + selectedPatterns: [mockSourcererState.signalIndexName], + }, }); }); it('index field search is not repeated when default and timeline have same dataViewId', async () => { - await act(async () => { - const { rerender, waitForNextUpdate } = renderHook, void>( - () => useInitSourcerer(), - { - wrapper: ({ children }) => {children}, - } - ); - await waitForNextUpdate(); - rerender(); - await waitFor(() => { - expect(mockSearch).toHaveBeenCalledTimes(1); - }); + const { rerender } = renderHook(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, + }); + await waitFor(() => null); + rerender(); + await waitFor(() => { + expect(mockSearch).toHaveBeenCalledTimes(1); }); }); it('index field search called twice when default and timeline have different dataViewId', async () => { @@ -451,18 +425,13 @@ describe('Sourcerer Hooks', () => { }, }, }); - await act(async () => { - const { rerender, waitForNextUpdate } = renderHook, void>( - () => useInitSourcerer(), - { - wrapper: ({ children }) => {children}, - } - ); - await waitForNextUpdate(); - rerender(); - await waitFor(() => { - expect(mockSearch).toHaveBeenCalledTimes(2); - }); + const { rerender } = renderHook(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, + }); + await waitFor(() => null); + rerender(); + await waitFor(() => { + expect(mockSearch).toHaveBeenCalledTimes(2); }); }); describe('initialization settings', () => { @@ -476,21 +445,16 @@ describe('Sourcerer Hooks', () => { })); }); it('does not needToBeInit if scope is default and selectedPatterns/missingPatterns have values', async () => { - await act(async () => { - const { rerender, waitForNextUpdate } = renderHook, void>( - () => useInitSourcerer(), - { - wrapper: ({ children }) => {children}, - } - ); - await waitForNextUpdate(); - rerender(); - await waitFor(() => { - expect(mockIndexFieldsSearch).toHaveBeenCalledWith({ - dataViewId: mockSourcererState.defaultDataView.id, - needToBeInit: false, - scopeId: SourcererScopeName.default, - }); + const { rerender } = renderHook(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, + }); + await waitFor(() => null); + rerender(); + await waitFor(() => { + expect(mockIndexFieldsSearch).toHaveBeenCalledWith({ + dataViewId: mockSourcererState.defaultDataView.id, + needToBeInit: false, + scopeId: SourcererScopeName.default, }); }); }); @@ -510,21 +474,16 @@ describe('Sourcerer Hooks', () => { }, }, }); - await act(async () => { - const { rerender, waitForNextUpdate } = renderHook, void>( - () => useInitSourcerer(), - { - wrapper: ({ children }) => {children}, - } - ); - await waitForNextUpdate(); - rerender(); - await waitFor(() => { - expect(mockIndexFieldsSearch).toHaveBeenCalledWith({ - dataViewId: mockSourcererState.defaultDataView.id, - needToBeInit: true, - scopeId: SourcererScopeName.default, - }); + const { rerender } = renderHook(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, + }); + await waitFor(() => null); + rerender(); + await waitFor(() => { + expect(mockIndexFieldsSearch).toHaveBeenCalledWith({ + dataViewId: mockSourcererState.defaultDataView.id, + needToBeInit: true, + scopeId: SourcererScopeName.default, }); }); }); @@ -549,22 +508,17 @@ describe('Sourcerer Hooks', () => { }, }, }); - await act(async () => { - const { rerender, waitForNextUpdate } = renderHook, void>( - () => useInitSourcerer(), - { - wrapper: ({ children }) => {children}, - } - ); - await waitForNextUpdate(); - rerender(); - await waitFor(() => { - expect(mockIndexFieldsSearch).toHaveBeenNthCalledWith(2, { - dataViewId: 'something-weird', - needToBeInit: true, - scopeId: SourcererScopeName.timeline, - skipScopeUpdate: false, - }); + const { rerender } = renderHook(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, + }); + await waitFor(() => null); + rerender(); + await waitFor(() => { + expect(mockIndexFieldsSearch).toHaveBeenNthCalledWith(2, { + dataViewId: 'something-weird', + needToBeInit: true, + scopeId: SourcererScopeName.timeline, + skipScopeUpdate: false, }); }); }); @@ -589,22 +543,17 @@ describe('Sourcerer Hooks', () => { }, }, }); - await act(async () => { - const { rerender, waitForNextUpdate } = renderHook, void>( - () => useInitSourcerer(), - { - wrapper: ({ children }) => {children}, - } - ); - await waitForNextUpdate(); - rerender(); - await waitFor(() => { - expect(mockIndexFieldsSearch).toHaveBeenNthCalledWith(2, { - dataViewId: 'something-weird', - needToBeInit: true, - scopeId: SourcererScopeName.timeline, - skipScopeUpdate: true, - }); + const { rerender } = renderHook(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, + }); + await waitFor(() => null); + rerender(); + await waitFor(() => { + expect(mockIndexFieldsSearch).toHaveBeenNthCalledWith(2, { + dataViewId: 'something-weird', + needToBeInit: true, + scopeId: SourcererScopeName.timeline, + skipScopeUpdate: true, }); }); }); @@ -633,21 +582,16 @@ describe('Sourcerer Hooks', () => { }, }, }); - await act(async () => { - const { rerender, waitForNextUpdate } = renderHook, void>( - () => useInitSourcerer(), - { - wrapper: ({ children }) => {children}, - } - ); - await waitForNextUpdate(); - rerender(); - await waitFor(() => { - expect(mockIndexFieldsSearch).toHaveBeenNthCalledWith(2, { - dataViewId: 'something-weird', - needToBeInit: false, - scopeId: SourcererScopeName.timeline, - }); + const { rerender } = renderHook(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, + }); + await waitFor(() => null); + rerender(); + await waitFor(() => { + expect(mockIndexFieldsSearch).toHaveBeenNthCalledWith(2, { + dataViewId: 'something-weird', + needToBeInit: false, + scopeId: SourcererScopeName.timeline, }); }); }); @@ -655,55 +599,53 @@ describe('Sourcerer Hooks', () => { describe('useSourcererDataView', () => { it('Should put any excludes in the index pattern at the end of the pattern list, and sort both the includes and excludes', async () => { - await act(async () => { - store = createMockStore({ - ...mockGlobalState, - sourcerer: { - ...mockGlobalState.sourcerer, - sourcererScopes: { - ...mockGlobalState.sourcerer.sourcererScopes, - [SourcererScopeName.default]: { - ...mockGlobalState.sourcerer.sourcererScopes[SourcererScopeName.default], - selectedPatterns: [ - '-packetbeat-*', - 'endgame-*', - 'auditbeat-*', - 'filebeat-*', - 'winlogbeat-*', - '-filebeat-*', - 'packetbeat-*', - 'traces-apm*', - 'apm-*-transaction*', - ], - }, + store = createMockStore({ + ...mockGlobalState, + sourcerer: { + ...mockGlobalState.sourcerer, + sourcererScopes: { + ...mockGlobalState.sourcerer.sourcererScopes, + [SourcererScopeName.default]: { + ...mockGlobalState.sourcerer.sourcererScopes[SourcererScopeName.default], + selectedPatterns: [ + '-packetbeat-*', + 'endgame-*', + 'auditbeat-*', + 'filebeat-*', + 'winlogbeat-*', + '-filebeat-*', + 'packetbeat-*', + 'traces-apm*', + 'apm-*-transaction*', + ], }, }, - }); - const { result, rerender, waitForNextUpdate } = renderHook< - React.PropsWithChildren<{}>, - SelectedDataView - >(() => useSourcererDataView(), { - wrapper: ({ children }) => {children}, - }); - await waitForNextUpdate(); - rerender(); - expect(result.current.selectedPatterns).toEqual([ - 'apm-*-transaction*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'packetbeat-*', - 'traces-apm*', - 'winlogbeat-*', - '-filebeat-*', - '-packetbeat-*', - ]); - expect(result.current.indexPattern).toHaveProperty('getName'); + }, }); + const { result, rerender } = renderHook( + () => useSourcererDataView(), + { + wrapper: ({ children }) => {children}, + } + ); + await waitFor(() => null); + rerender(); + expect(result.current.selectedPatterns).toEqual([ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'packetbeat-*', + 'traces-apm*', + 'winlogbeat-*', + '-filebeat-*', + '-packetbeat-*', + ]); + expect(result.current.indexPattern).toHaveProperty('getName'); }); it('should update the title and name of the data view according to the selected patterns', async () => { - const { result, rerender } = renderHook, SelectedDataView>( + const { result, rerender } = renderHook>( () => useSourcererDataView(), { wrapper: ({ children }) => {children}, diff --git a/x-pack/plugins/security_solution/public/sourcerer/containers/use_signal_helpers.test.tsx b/x-pack/plugins/security_solution/public/sourcerer/containers/use_signal_helpers.test.tsx index 5bb0cc11ebffb..59fe6f38bdf7f 100644 --- a/x-pack/plugins/security_solution/public/sourcerer/containers/use_signal_helpers.test.tsx +++ b/x-pack/plugins/security_solution/public/sourcerer/containers/use_signal_helpers.test.tsx @@ -7,7 +7,8 @@ import React from 'react'; import { createMockStore, mockGlobalState, TestProviders } from '../../common/mock'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useSignalHelpers } from './use_signal_helpers'; import type { State } from '../../common/store'; import { createSourcererDataView } from './create_sourcerer_data_view'; @@ -41,14 +42,12 @@ describe('useSignalHelpers', () => { ); test('Default state, does not need init and does not need poll', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useSignalHelpers(), { - wrapper: wrapperContainer, - }); - await waitForNextUpdate(); - expect(result.current.signalIndexNeedsInit).toEqual(false); - expect(result.current.pollForSignalIndex).toEqual(undefined); + const { result } = renderHook(() => useSignalHelpers(), { + wrapper: wrapperContainer, }); + await waitFor(() => null); + expect(result.current.signalIndexNeedsInit).toEqual(false); + expect(result.current.pollForSignalIndex).toEqual(undefined); }); test('Needs init and does not need poll when signal index is not yet in default data view', async () => { const state: State = { @@ -70,16 +69,12 @@ describe('useSignalHelpers', () => { }, }; const store = createMockStore(state); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useSignalHelpers(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( - {children} - ), - }); - await waitForNextUpdate(); - expect(result.current.signalIndexNeedsInit).toEqual(true); - expect(result.current.pollForSignalIndex).toEqual(undefined); + const { result } = renderHook(() => useSignalHelpers(), { + wrapper: ({ children }) => {children}, }); + await waitFor(() => null); + expect(result.current.signalIndexNeedsInit).toEqual(true); + expect(result.current.pollForSignalIndex).toEqual(undefined); }); test('Init happened and signal index does not have data yet, poll function becomes available', async () => { const state: State = { @@ -101,16 +96,12 @@ describe('useSignalHelpers', () => { }, }; const store = createMockStore(state); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useSignalHelpers(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( - {children} - ), - }); - await waitForNextUpdate(); - expect(result.current.signalIndexNeedsInit).toEqual(false); - expect(result.current.pollForSignalIndex).not.toEqual(undefined); + const { result } = renderHook(() => useSignalHelpers(), { + wrapper: ({ children }) => {children}, }); + await waitFor(() => null); + expect(result.current.signalIndexNeedsInit).toEqual(false); + expect(result.current.pollForSignalIndex).not.toEqual(undefined); }); test('Init happened and signal index does not have data yet, poll function becomes available but createSourcererDataView throws an abort error', async () => { @@ -134,17 +125,13 @@ describe('useSignalHelpers', () => { }, }; const store = createMockStore(state); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useSignalHelpers(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( - {children} - ), - }); - await waitForNextUpdate(); - expect(result.current.signalIndexNeedsInit).toEqual(false); - expect(result.current.pollForSignalIndex).not.toEqual(undefined); - expect(mockAddError).not.toHaveBeenCalled(); + const { result } = renderHook(() => useSignalHelpers(), { + wrapper: ({ children }) => {children}, }); + await waitFor(() => null); + expect(result.current.signalIndexNeedsInit).toEqual(false); + expect(result.current.pollForSignalIndex).not.toEqual(undefined); + expect(mockAddError).not.toHaveBeenCalled(); }); test('Init happened and signal index does not have data yet, poll function becomes available but createSourcererDataView throws a non-abort error', async () => { @@ -170,17 +157,13 @@ describe('useSignalHelpers', () => { }, }; const store = createMockStore(state); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useSignalHelpers(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( - {children} - ), - }); - await waitForNextUpdate(); - expect(result.current.signalIndexNeedsInit).toEqual(false); - expect(result.current.pollForSignalIndex).not.toEqual(undefined); - result.current.pollForSignalIndex?.(); - expect(mockAddError).toHaveBeenCalled(); + const { result } = renderHook(() => useSignalHelpers(), { + wrapper: ({ children }) => {children}, }); + await waitFor(() => null); + expect(result.current.signalIndexNeedsInit).toEqual(false); + expect(result.current.pollForSignalIndex).not.toEqual(undefined); + result.current.pollForSignalIndex?.(); + expect(mockAddError).toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx index 66d3a41bc0d48..05eb29c666360 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx @@ -6,8 +6,8 @@ */ import React from 'react'; -import { fireEvent, render } from '@testing-library/react'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { fireEvent, render, act, waitFor } from '@testing-library/react'; import type { UseTimelineTypesArgs, UseTimelineTypesResult } from './use_timeline_types'; import { useTimelineTypes } from './use_timeline_types'; import { TestProviders } from '../../../common/mock'; @@ -49,55 +49,51 @@ jest.mock('@kbn/kibana-react-plugin/public', () => { describe('useTimelineTypes', () => { it('init', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - React.PropsWithChildren, - UseTimelineTypesResult - >(() => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { + const { result } = renderHook( + () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), + { wrapper: TestProviders, - }); - await waitForNextUpdate(); - expect(result.current).toEqual({ - timelineType: 'default', - timelineTabs: result.current.timelineTabs, - timelineFilters: result.current.timelineFilters, - }); + } + ); + await waitFor(() => null); + expect(result.current).toEqual({ + timelineType: 'default', + timelineTabs: result.current.timelineTabs, + timelineFilters: result.current.timelineFilters, }); }); describe('timelineTabs', () => { it('render timelineTabs', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - React.PropsWithChildren, - UseTimelineTypesResult - >(() => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { + const { result } = renderHook( + () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), + { wrapper: TestProviders, - }); - await waitForNextUpdate(); - - const { container } = render(result.current.timelineTabs); - expect( - container.querySelector('[data-test-subj="timeline-tab-default"]') - ).toHaveTextContent('Timelines'); - expect( - container.querySelector('[data-test-subj="timeline-tab-template"]') - ).toHaveTextContent('Templates'); - }); + } + ); + await waitFor(() => null); + + const { container } = render(result.current.timelineTabs); + expect(container.querySelector('[data-test-subj="timeline-tab-default"]')).toHaveTextContent( + 'Timelines' + ); + expect(container.querySelector('[data-test-subj="timeline-tab-template"]')).toHaveTextContent( + 'Templates' + ); }); it('set timelineTypes correctly', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - React.PropsWithChildren, - UseTimelineTypesResult - >(() => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { + const { result } = renderHook( + () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), + { wrapper: TestProviders, - }); - await waitForNextUpdate(); + } + ); + await waitFor(() => null); - const { container } = render(result.current.timelineTabs); + const { container } = render(result.current.timelineTabs); + act(() => { fireEvent( container.querySelector('[data-test-subj="timeline-tab-template"]')!, new MouseEvent('click', { @@ -105,27 +101,29 @@ describe('useTimelineTypes', () => { cancelable: true, }) ); + }); - expect(result.current).toEqual({ - timelineType: 'template', - timelineTabs: result.current.timelineTabs, - timelineFilters: result.current.timelineFilters, - }); + await waitFor(() => null); + + expect(result.current).toEqual({ + timelineType: 'template', + timelineTabs: result.current.timelineTabs, + timelineFilters: result.current.timelineFilters, }); }); it('stays in the same tab if clicking again on current tab', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - React.PropsWithChildren, - UseTimelineTypesResult - >(() => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { + const { result } = renderHook( + () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), + { wrapper: TestProviders, - }); - await waitForNextUpdate(); + } + ); + await waitFor(() => null); - const { container } = render(result.current.timelineTabs); + const { container } = render(result.current.timelineTabs); + act(() => { fireEvent( container.querySelector('[data-test-subj="timeline-tab-default"]')!, new MouseEvent('click', { @@ -133,49 +131,50 @@ describe('useTimelineTypes', () => { cancelable: true, }) ); + }); + + waitFor(() => null); - expect(result.current).toEqual({ - timelineType: 'default', - timelineTabs: result.current.timelineTabs, - timelineFilters: result.current.timelineFilters, - }); + expect(result.current).toEqual({ + timelineType: 'default', + timelineTabs: result.current.timelineTabs, + timelineFilters: result.current.timelineFilters, }); }); }); describe('timelineFilters', () => { it('render timelineFilters', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - React.PropsWithChildren, - UseTimelineTypesResult - >(() => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { + const { result } = renderHook( + () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), + { wrapper: TestProviders, - }); - await waitForNextUpdate(); - - const { container } = render(<>{result.current.timelineFilters}); - expect( - container.querySelector('[data-test-subj="open-timeline-modal-body-filter-default"]') - ).toHaveTextContent('Timelines'); - expect( - container.querySelector('[data-test-subj="open-timeline-modal-body-filter-template"]') - ).toHaveTextContent('Templates'); - }); + } + ); + await waitFor(() => null); + + const { container } = render(<>{result.current.timelineFilters}); + + expect( + container.querySelector('[data-test-subj="open-timeline-modal-body-filter-default"]') + ).toHaveTextContent('Timelines'); + expect( + container.querySelector('[data-test-subj="open-timeline-modal-body-filter-template"]') + ).toHaveTextContent('Templates'); }); it('set timelineTypes correctly', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - React.PropsWithChildren, - UseTimelineTypesResult - >(() => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { + const { result } = renderHook( + () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), + { wrapper: TestProviders, - }); - await waitForNextUpdate(); + } + ); + await waitFor(() => null); - const { container } = render(<>{result.current.timelineFilters}); + const { container } = render(<>{result.current.timelineFilters}); + act(() => { fireEvent( container.querySelector('[data-test-subj="open-timeline-modal-body-filter-template"]')!, new MouseEvent('click', { @@ -183,27 +182,30 @@ describe('useTimelineTypes', () => { cancelable: true, }) ); + }); - expect(result.current).toEqual({ - timelineType: 'template', - timelineTabs: result.current.timelineTabs, - timelineFilters: result.current.timelineFilters, - }); + await waitFor(() => null); + + expect(result.current).toEqual({ + timelineType: 'template', + timelineTabs: result.current.timelineTabs, + timelineFilters: result.current.timelineFilters, }); }); it('stays in the same tab if clicking again on current tab', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - React.PropsWithChildren, - UseTimelineTypesResult - >(() => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { + const { result } = renderHook( + () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), + { wrapper: TestProviders, - }); - await waitForNextUpdate(); + } + ); - const { container } = render(<>{result.current.timelineFilters}); + await waitFor(() => null); + const { container } = render(<>{result.current.timelineFilters}); + + act(() => { fireEvent( container.querySelector('[data-test-subj="open-timeline-modal-body-filter-default"]')!, new MouseEvent('click', { @@ -211,12 +213,14 @@ describe('useTimelineTypes', () => { cancelable: true, }) ); + }); - expect(result.current).toEqual({ - timelineType: 'default', - timelineTabs: result.current.timelineTabs, - timelineFilters: result.current.timelineFilters, - }); + await waitFor(() => null); + + expect(result.current).toEqual({ + timelineType: 'default', + timelineTabs: result.current.timelineTabs, + timelineFilters: result.current.timelineFilters, }); }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_update_timeline.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_update_timeline.test.tsx index 10088446c045c..18469f957333c 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_update_timeline.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_update_timeline.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { mockTimelineModel, TestProviders } from '../../../common/mock'; import { setTimelineRangeDatePicker as dispatchSetTimelineRangeDatePicker } from '../../../common/store/inputs/actions'; import { @@ -88,10 +89,10 @@ describe('dispatchUpdateTimeline', () => { it('it invokes date range picker dispatch', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useUpdateTimeline(), { + const { result } = renderHook(() => useUpdateTimeline(), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => null); result.current(defaultArgs); expect(dispatchSetTimelineRangeDatePicker).toHaveBeenCalledWith({ @@ -103,10 +104,10 @@ describe('dispatchUpdateTimeline', () => { it('it invokes add timeline dispatch', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useUpdateTimeline(), { + const { result } = renderHook(() => useUpdateTimeline(), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => null); result.current(defaultArgs); expect(dispatchAddTimeline).toHaveBeenCalledWith({ @@ -124,10 +125,10 @@ describe('dispatchUpdateTimeline', () => { it('it does not invoke kql filter query dispatches if timeline.kqlQuery.filterQuery is null', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useUpdateTimeline(), { + const { result } = renderHook(() => useUpdateTimeline(), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => null); result.current(defaultArgs); expect(dispatchApplyKqlFilterQuery).not.toHaveBeenCalled(); @@ -136,10 +137,10 @@ describe('dispatchUpdateTimeline', () => { it('it does not invoke notes dispatch if duplicate is true', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useUpdateTimeline(), { + const { result } = renderHook(() => useUpdateTimeline(), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => null); result.current(defaultArgs); expect(dispatchAddNotes).not.toHaveBeenCalled(); @@ -148,10 +149,10 @@ describe('dispatchUpdateTimeline', () => { it('it does not invoke kql filter query dispatches if timeline.kqlQuery.kuery is null', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useUpdateTimeline(), { + const { result } = renderHook(() => useUpdateTimeline(), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => null); const mockTimeline = { ...mockTimelineModel, kqlQuery: { @@ -172,10 +173,10 @@ describe('dispatchUpdateTimeline', () => { it('it invokes kql filter query dispatches if timeline.kqlQuery.filterQuery.kuery is not null', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useUpdateTimeline(), { + const { result } = renderHook(() => useUpdateTimeline(), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => null); const mockTimeline = { ...mockTimelineModel, kqlQuery: { @@ -205,10 +206,10 @@ describe('dispatchUpdateTimeline', () => { it('it invokes dispatchAddNotes if duplicate is false', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useUpdateTimeline(), { + const { result } = renderHook(() => useUpdateTimeline(), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => null); result.current({ ...defaultArgs, duplicate: false, @@ -246,10 +247,10 @@ describe('dispatchUpdateTimeline', () => { it('it invokes dispatch to create a timeline note if duplicate is true and ruleNote exists', async () => { await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => useUpdateTimeline(), { + const { result } = renderHook(() => useUpdateTimeline(), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => null); result.current({ ...defaultArgs, ruleNote: '# this would be some markdown', diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_notes_in_flyout.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_notes_in_flyout.test.tsx index 32b5b8bc3c129..81c9f1febdeb5 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_notes_in_flyout.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_notes_in_flyout.test.tsx @@ -7,11 +7,10 @@ import React from 'react'; import { TimelineId, TimelineTabs } from '../../../../../common/types'; -import { renderHook, act } from '@testing-library/react-hooks/dom'; +import { renderHook, act, waitFor } from '@testing-library/react'; import { createMockStore, mockGlobalState, TestProviders } from '../../../../common/mock'; import type { UseNotesInFlyoutArgs } from './use_notes_in_flyout'; import { useNotesInFlyout } from './use_notes_in_flyout'; -import { waitFor } from '@testing-library/react'; import { useDispatch } from 'react-redux'; jest.mock('react-redux', () => ({ @@ -203,7 +202,7 @@ describe('useNotesInFlyout', () => { }); it('should close the flyout when activeTab is changed', () => { - const { result, rerender, waitForNextUpdate } = renderTestHook(); + const { result, rerender } = renderTestHook(); act(() => { result.current.setNotesEventId('event-1'); @@ -226,7 +225,7 @@ describe('useNotesInFlyout', () => { rerender({ activeTab: TimelineTabs.eql }); }); - waitForNextUpdate(); + waitFor(() => null); expect(result.current.isNotesFlyoutVisible).toBe(false); }); diff --git a/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx index 68846de0fed37..7c27b6b0ad0c4 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx @@ -6,7 +6,8 @@ */ import { DataLoadingState } from '@kbn/unified-data-table'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import type { TimelineArgs, UseTimelineEventsProps } from '.'; import { initSortDefault, useTimelineEvents } from '.'; import { SecurityPageName } from '../../../common/constants'; @@ -135,132 +136,106 @@ describe('useTimelineEvents', () => { }; test('init', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - UseTimelineEventsProps, - [DataLoadingState, TimelineArgs] - >((args) => useTimelineEvents(args), { + const { result } = renderHook( + (args) => useTimelineEvents(args), + { initialProps: { ...props }, - }); - - // useEffect on params request - await waitForNextUpdate(); - expect(result.current).toEqual([ - DataLoadingState.loaded, - { - events: [], - id: TimelineId.active, - inspect: result.current[1].inspect, - loadPage: result.current[1].loadPage, - pageInfo: result.current[1].pageInfo, - refetch: result.current[1].refetch, - totalCount: -1, - refreshedAt: 0, - }, - ]); - }); + } + ); + + expect(result.current).toEqual([ + DataLoadingState.loaded, + { + events: [], + id: TimelineId.active, + inspect: result.current[1].inspect, + loadPage: result.current[1].loadPage, + pageInfo: result.current[1].pageInfo, + refetch: result.current[1].refetch, + totalCount: -1, + refreshedAt: 0, + }, + ]); }); test('happy path query', async () => { - await act(async () => { - const { result, waitForNextUpdate, rerender } = renderHook< - UseTimelineEventsProps, - [DataLoadingState, TimelineArgs] - >((args) => useTimelineEvents(args), { - initialProps: { ...props }, - }); - - // useEffect on params request - await waitForNextUpdate(); - rerender({ ...props, startDate, endDate }); - // useEffect on params request - await waitForNextUpdate(); - - expect(mockSearch).toHaveBeenCalledTimes(2); - expect(result.current).toEqual([ - DataLoadingState.loaded, - { - events: mockEvents, - id: TimelineId.active, - inspect: result.current[1].inspect, - loadPage: result.current[1].loadPage, - pageInfo: result.current[1].pageInfo, - refetch: result.current[1].refetch, - totalCount: 32, - refreshedAt: result.current[1].refreshedAt, - }, - ]); + const { result, rerender } = renderHook< + UseTimelineEventsProps, + [DataLoadingState, TimelineArgs] + >((args) => useTimelineEvents(args), { + initialProps: { ...props }, }); + + // useEffect on params request + await waitFor(() => null); + rerender({ ...props, startDate, endDate }); + // useEffect on params request + await waitFor(() => null); + + expect(mockSearch).toHaveBeenCalledTimes(2); + expect(result.current).toEqual([ + DataLoadingState.loaded, + { + events: mockEvents, + id: TimelineId.active, + inspect: result.current[1].inspect, + loadPage: result.current[1].loadPage, + pageInfo: result.current[1].pageInfo, + refetch: result.current[1].refetch, + totalCount: 32, + refreshedAt: result.current[1].refreshedAt, + }, + ]); }); test('Mock cache for active timeline when switching page', async () => { - await act(async () => { - const { result, waitForNextUpdate, rerender } = renderHook< - UseTimelineEventsProps, - [DataLoadingState, TimelineArgs] - >((args) => useTimelineEvents(args), { - initialProps: { ...props }, - }); - - // useEffect on params request - await waitForNextUpdate(); - rerender({ ...props, startDate, endDate }); - // useEffect on params request - await waitForNextUpdate(); - - mockUseRouteSpy.mockReturnValue([ - { - pageName: SecurityPageName.timelines, - detailName: undefined, - tabName: undefined, - search: '', - pathName: '/timelines', - }, - ]); - - expect(mockSearch).toHaveBeenCalledTimes(2); - - expect(result.current).toEqual([ - DataLoadingState.loaded, - { - events: mockEvents, - id: TimelineId.active, - inspect: result.current[1].inspect, - loadPage: result.current[1].loadPage, - pageInfo: result.current[1].pageInfo, - refetch: result.current[1].refetch, - totalCount: 32, - refreshedAt: result.current[1].refreshedAt, - }, - ]); + const { result, rerender } = renderHook< + UseTimelineEventsProps, + [DataLoadingState, TimelineArgs] + >((args) => useTimelineEvents(args), { + initialProps: { ...props }, }); + + // useEffect on params request + await waitFor(() => null); + rerender({ ...props, startDate, endDate }); + // useEffect on params request + await waitFor(() => null); + + mockUseRouteSpy.mockReturnValue([ + { + pageName: SecurityPageName.timelines, + detailName: undefined, + tabName: undefined, + search: '', + pathName: '/timelines', + }, + ]); + + expect(mockSearch).toHaveBeenCalledTimes(2); + + expect(result.current).toEqual([ + DataLoadingState.loaded, + { + events: mockEvents, + id: TimelineId.active, + inspect: result.current[1].inspect, + loadPage: result.current[1].loadPage, + pageInfo: result.current[1].pageInfo, + refetch: result.current[1].refetch, + totalCount: 32, + refreshedAt: result.current[1].refreshedAt, + }, + ]); }); test('Correlation pagination is calling search strategy when switching page', async () => { - await act(async () => { - const { result, waitForNextUpdate, rerender } = renderHook< - UseTimelineEventsProps, - [DataLoadingState, TimelineArgs] - >((args) => useTimelineEvents(args), { - initialProps: { - ...props, - language: 'eql', - eqlOptions: { - eventCategoryField: 'category', - tiebreakerField: '', - timestampField: '@timestamp', - query: 'find it EQL', - size: 100, - }, - }, - }); - - // useEffect on params request - await waitForNextUpdate(); - rerender({ + const { result, rerender } = renderHook< + [DataLoadingState, TimelineArgs], + UseTimelineEventsProps + >((args) => useTimelineEvents(args), { + initialProps: { ...props, - startDate, - endDate, language: 'eql', eqlOptions: { eventCategoryField: 'category', @@ -269,124 +244,133 @@ describe('useTimelineEvents', () => { query: 'find it EQL', size: 100, }, - }); - // useEffect on params request - await waitForNextUpdate(); - mockSearch.mockReset(); + }, + }); + + // useEffect on params request + await waitFor(() => null); + rerender({ + ...props, + startDate, + endDate, + language: 'eql', + eqlOptions: { + eventCategoryField: 'category', + tiebreakerField: '', + timestampField: '@timestamp', + query: 'find it EQL', + size: 100, + }, + }); + // useEffect on params request + await waitFor(() => null); + mockSearch.mockReset(); + act(() => { result.current[1].loadPage(4); - await waitForNextUpdate(); - expect(mockSearch).toHaveBeenCalledTimes(1); }); + await waitFor(() => null); + expect(mockSearch).toHaveBeenCalledTimes(1); }); test('should query again when a new field is added', async () => { - await act(async () => { - const { waitForNextUpdate, rerender } = renderHook< - UseTimelineEventsProps, - [DataLoadingState, TimelineArgs] - >((args) => useTimelineEvents(args), { + const { rerender } = renderHook( + (args) => useTimelineEvents(args), + { initialProps: { ...props }, - }); - - // useEffect on params request - await waitForNextUpdate(); - rerender({ ...props, startDate, endDate }); - // useEffect on params request - await waitForNextUpdate(); - - expect(mockSearch).toHaveBeenCalledTimes(2); - mockSearch.mockClear(); - - rerender({ - ...props, - startDate, - endDate, - fields: ['@timestamp', 'event.kind', 'event.category'], - }); + } + ); + + // useEffect on params request + await waitFor(() => null); + rerender({ ...props, startDate, endDate }); + // useEffect on params request + await waitFor(() => null); + + expect(mockSearch).toHaveBeenCalledTimes(2); + mockSearch.mockClear(); + + rerender({ + ...props, + startDate, + endDate, + fields: ['@timestamp', 'event.kind', 'event.category'], + }); - await waitForNextUpdate(); + await waitFor(() => null); - expect(mockSearch).toHaveBeenCalledTimes(1); - }); + expect(mockSearch).toHaveBeenCalledTimes(1); }); test('should not query again when a field is removed', async () => { - await act(async () => { - const { waitForNextUpdate, rerender } = renderHook< - UseTimelineEventsProps, - [DataLoadingState, TimelineArgs] - >((args) => useTimelineEvents(args), { + const { rerender } = renderHook( + (args) => useTimelineEvents(args), + { initialProps: { ...props }, - }); + } + ); - // useEffect on params request - await waitForNextUpdate(); - rerender({ ...props, startDate, endDate }); - // useEffect on params request - await waitForNextUpdate(); + // useEffect on params request + await waitFor(() => null); + rerender({ ...props, startDate, endDate }); + // useEffect on params request + await waitFor(() => null); - expect(mockSearch).toHaveBeenCalledTimes(2); - mockSearch.mockClear(); + expect(mockSearch).toHaveBeenCalledTimes(2); + mockSearch.mockClear(); - rerender({ ...props, startDate, endDate, fields: ['@timestamp'] }); + rerender({ ...props, startDate, endDate, fields: ['@timestamp'] }); - // since there is no new update in useEffect, it should throw an timeout error - await expect(waitForNextUpdate()).rejects.toThrowError(); + await waitFor(() => null); - expect(mockSearch).toHaveBeenCalledTimes(0); - }); + expect(mockSearch).toHaveBeenCalledTimes(0); }); test('should not query again when a removed field is added back', async () => { - await act(async () => { - const { waitForNextUpdate, rerender } = renderHook< - UseTimelineEventsProps, - [DataLoadingState, TimelineArgs] - >((args) => useTimelineEvents(args), { + const { rerender } = renderHook<[DataLoadingState, TimelineArgs], UseTimelineEventsProps>( + (args) => useTimelineEvents(args), + { initialProps: { ...props }, - }); + } + ); - // useEffect on params request - await waitForNextUpdate(); - rerender({ ...props, startDate, endDate }); - // useEffect on params request - await waitForNextUpdate(); + // useEffect on params request + await waitFor(() => null); + rerender({ ...props, startDate, endDate }); + // useEffect on params request + await waitFor(() => null); - expect(mockSearch).toHaveBeenCalledTimes(2); - mockSearch.mockClear(); + expect(mockSearch).toHaveBeenCalledTimes(2); + mockSearch.mockClear(); - // remove `event.kind` from default fields - rerender({ ...props, startDate, endDate, fields: ['@timestamp'] }); + // remove `event.kind` from default fields + rerender({ ...props, startDate, endDate, fields: ['@timestamp'] }); - // since there is no new update in useEffect, it should throw an timeout error - await expect(waitForNextUpdate()).rejects.toThrowError(); + await waitFor(() => null); - expect(mockSearch).toHaveBeenCalledTimes(0); + expect(mockSearch).toHaveBeenCalledTimes(0); - // request default Fields - rerender({ ...props, startDate, endDate }); + // request default Fields + rerender({ ...props, startDate, endDate }); - // since there is no new update in useEffect, it should throw an timeout error - await expect(waitForNextUpdate()).rejects.toThrowError(); + // since there is no new update in useEffect, it should throw an timeout error + // await expect(waitFor(() => null)).rejects.toThrowError(); + await waitFor(() => null); - expect(mockSearch).toHaveBeenCalledTimes(0); - }); + expect(mockSearch).toHaveBeenCalledTimes(0); }); describe('Fetch Notes', () => { test('should call onLoad for notes when events are fetched', async () => { - await act(async () => { - const { waitFor } = renderHook( - (args) => useTimelineEvents(args), - { - initialProps: { ...props }, - } - ); - - await waitFor(() => { - expect(mockSearch).toHaveBeenCalledTimes(1); - expect(onLoadMock).toHaveBeenNthCalledWith(1, expect.objectContaining(mockEvents)); - }); - }); + renderHook( + (args) => useTimelineEvents(args), + { + initialProps: { ...props }, + } + ); + + await waitFor(() => null); + + expect(mockSearch).toHaveBeenCalledTimes(1); + expect(onLoadMock).toHaveBeenNthCalledWith(1, expect.objectContaining(mockEvents)); }); }); }); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/email/use_email_config.test.ts b/x-pack/plugins/stack_connectors/public/connector_types/email/use_email_config.test.ts index ee5ba95bf577b..7b03d016ec8f8 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/email/use_email_config.test.ts +++ b/x-pack/plugins/stack_connectors/public/connector_types/email/use_email_config.test.ts @@ -6,7 +6,8 @@ */ import { httpServiceMock, notificationServiceMock } from '@kbn/core/public/mocks'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useEmailConfig } from './use_email_config'; const http = httpServiceMock.createStartContract(); @@ -26,14 +27,16 @@ describe('useEmailConfig', () => { }); const { result } = renderUseEmailConfigHook(); + let res: ReturnType; await act(async () => { - const res = await result.current.getEmailServiceConfig('gmail'); - expect(http.get).toHaveBeenCalledWith('/internal/stack_connectors/_email_config/gmail'); - expect(res).toEqual({ - host: 'smtp.gmail.com', - port: 465, - secure: true, - }); + res = await result.current.getEmailServiceConfig('gmail'); + }); + + expect(http.get).toHaveBeenCalledWith('/internal/stack_connectors/_email_config/gmail'); + expect(res).toEqual({ + host: 'smtp.gmail.com', + port: 465, + secure: true, }); }); @@ -44,14 +47,17 @@ describe('useEmailConfig', () => { }); const { result } = renderUseEmailConfigHook(); + + let res: ReturnType; await act(async () => { - const res = await result.current.getEmailServiceConfig('gmail'); - expect(http.get).toHaveBeenCalledWith('/internal/stack_connectors/_email_config/gmail'); - expect(res).toEqual({ - host: 'smtp.gmail.com', - port: 465, - secure: false, - }); + res = await result.current.getEmailServiceConfig('gmail'); + }); + + expect(http.get).toHaveBeenCalledWith('/internal/stack_connectors/_email_config/gmail'); + expect(res).toEqual({ + host: 'smtp.gmail.com', + port: 465, + secure: false, }); }); @@ -59,14 +65,16 @@ describe('useEmailConfig', () => { http.get.mockResolvedValueOnce({}); const { result } = renderUseEmailConfigHook(); + let res: ReturnType; await act(async () => { - const res = await result.current.getEmailServiceConfig('foo'); - expect(http.get).toHaveBeenCalledWith('/internal/stack_connectors/_email_config/foo'); - expect(res).toEqual({ - host: '', - port: 0, - secure: false, - }); + res = await result.current.getEmailServiceConfig('foo'); + }); + + expect(http.get).toHaveBeenCalledWith('/internal/stack_connectors/_email_config/foo'); + expect(res).toEqual({ + host: '', + port: 0, + secure: false, }); }); @@ -75,13 +83,14 @@ describe('useEmailConfig', () => { throw new Error('no!'); }); - const { result, waitForNextUpdate } = renderUseEmailConfigHook(); + const { result } = renderUseEmailConfigHook(); await act(async () => { result.current.getEmailServiceConfig('foo'); - await waitForNextUpdate(); - expect(toasts.addDanger).toHaveBeenCalled(); }); + + await waitFor(() => null); + expect(toasts.addDanger).toHaveBeenCalled(); }); it('should not make an API call if the service is empty', async () => { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/lib/gen_ai/use_get_dashboard.test.ts b/x-pack/plugins/stack_connectors/public/connector_types/lib/gen_ai/use_get_dashboard.test.ts index 18bcdc6232792..88b4f7b39d777 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/lib/gen_ai/use_get_dashboard.test.ts +++ b/x-pack/plugins/stack_connectors/public/connector_types/lib/gen_ai/use_get_dashboard.test.ts @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useGetDashboard } from './use_get_dashboard'; import { getDashboard } from './api'; import { useKibana } from '@kbn/triggers-actions-ui-plugin/public'; @@ -58,10 +59,8 @@ describe('useGetDashboard', () => { ])( 'fetches the %p dashboard and sets the dashboard URL with %p', async (selectedProvider, urlKey) => { - const { result, waitForNextUpdate } = renderHook(() => - useGetDashboard({ ...defaultArgs, selectedProvider }) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useGetDashboard({ ...defaultArgs, selectedProvider })); + await waitFor(() => null); expect(mockDashboard).toHaveBeenCalledWith( expect.objectContaining({ connectorId, @@ -84,8 +83,8 @@ describe('useGetDashboard', () => { it('handles the case where the dashboard is not available.', async () => { mockDashboard.mockResolvedValue({ data: { available: false } }); - const { result, waitForNextUpdate } = renderHook(() => useGetDashboard(defaultArgs)); - await waitForNextUpdate(); + const { result } = renderHook(() => useGetDashboard(defaultArgs)); + await waitFor(() => null); expect(mockDashboard).toHaveBeenCalledWith( expect.objectContaining({ connectorId, @@ -111,10 +110,8 @@ describe('useGetDashboard', () => { }); it('handles the case where connectorId is empty string', async () => { - const { result, waitForNextUpdate } = renderHook(() => - useGetDashboard({ ...defaultArgs, connectorId: '' }) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useGetDashboard({ ...defaultArgs, connectorId: '' })); + await waitFor(() => null); expect(mockDashboard).not.toHaveBeenCalled(); expect(mockGetRedirectUrl).not.toHaveBeenCalled(); expect(result.current.isLoading).toBe(false); @@ -125,16 +122,16 @@ describe('useGetDashboard', () => { mockKibana.mockReturnValue({ services: { ...mockServices, dashboard: {} }, }); - const { result, waitForNextUpdate } = renderHook(() => useGetDashboard(defaultArgs)); - await waitForNextUpdate(); + const { result } = renderHook(() => useGetDashboard(defaultArgs)); + await waitFor(() => null); expect(result.current.isLoading).toBe(false); expect(result.current.dashboardUrl).toBe(null); }); it('correctly handles errors and displays the appropriate toast messages.', async () => { mockDashboard.mockRejectedValue(new Error('Error fetching dashboard')); - const { result, waitForNextUpdate } = renderHook(() => useGetDashboard(defaultArgs)); - await waitForNextUpdate(); + const { result } = renderHook(() => useGetDashboard(defaultArgs)); + await waitFor(() => null); expect(result.current.isLoading).toBe(false); expect(mockToasts.addDanger).toHaveBeenCalledWith({ title: 'Error finding OpenAI Token Usage Dashboard.', diff --git a/x-pack/plugins/stack_connectors/public/connector_types/lib/servicenow/use_choices.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/lib/servicenow/use_choices.test.tsx index 721897ece7266..f489fa69cea0a 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/lib/servicenow/use_choices.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/lib/servicenow/use_choices.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useKibana } from '@kbn/triggers-actions-ui-plugin/public'; import { ActionConnector } from '@kbn/triggers-actions-ui-plugin/public/types'; @@ -73,7 +74,7 @@ describe('UseChoices', () => { const fields = ['category']; it('init', async () => { - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useChoices({ http: services.http, actionConnector, @@ -82,13 +83,13 @@ describe('UseChoices', () => { }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual(useChoicesResponse); }); it('returns an empty array if the field is not in response', async () => { - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useChoices({ http: services.http, actionConnector, @@ -97,7 +98,7 @@ describe('UseChoices', () => { }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual({ isLoading: false, @@ -127,7 +128,7 @@ describe('UseChoices', () => { serviceMessage: 'An error occurred', }); - const { waitForNextUpdate } = renderHook(() => + renderHook(() => useChoices({ http: services.http, actionConnector, @@ -136,7 +137,7 @@ describe('UseChoices', () => { }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(services.notifications.toasts.addDanger).toHaveBeenCalledWith({ text: 'An error occurred', diff --git a/x-pack/plugins/stack_connectors/public/connector_types/lib/servicenow/use_get_choices.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/lib/servicenow/use_get_choices.test.tsx index 38ea6d55b4e17..b8001ae496091 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/lib/servicenow/use_get_choices.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/lib/servicenow/use_get_choices.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useKibana } from '@kbn/triggers-actions-ui-plugin/public'; import { ActionConnector } from '@kbn/triggers-actions-ui-plugin/public/types'; @@ -69,7 +70,7 @@ describe('useGetChoices', () => { const fields = ['priority']; it('init', async () => { - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useGetChoices({ http: services.http, actionConnector, @@ -79,7 +80,7 @@ describe('useGetChoices', () => { }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current).toEqual({ isLoading: false, @@ -105,7 +106,7 @@ describe('useGetChoices', () => { }); it('it calls onSuccess', async () => { - const { waitForNextUpdate } = renderHook(() => + renderHook(() => useGetChoices({ http: services.http, actionConnector, @@ -115,7 +116,7 @@ describe('useGetChoices', () => { }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(onSuccess).toHaveBeenCalledWith(getChoicesResponse); }); @@ -126,7 +127,7 @@ describe('useGetChoices', () => { serviceMessage: 'An error occurred', }); - const { waitForNextUpdate } = renderHook(() => + renderHook(() => useGetChoices({ http: services.http, actionConnector, @@ -136,7 +137,7 @@ describe('useGetChoices', () => { }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(services.notifications.toasts.addDanger).toHaveBeenCalledWith({ text: 'An error occurred', diff --git a/x-pack/plugins/stack_connectors/public/connector_types/swimlane/use_get_application.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/swimlane/use_get_application.test.tsx index 82e514ec51fd9..bdbbe5c160dcd 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/swimlane/use_get_application.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/swimlane/use_get_application.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useKibana } from '@kbn/triggers-actions-ui-plugin/public/common/lib/kibana'; import { getApplication } from './api'; @@ -43,87 +44,85 @@ describe('useGetApplication', () => { }); it('init', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useGetApplication({ - toastNotifications: services.notifications.toasts, - }) - ); - - await waitForNextUpdate(); - expect(result.current).toEqual({ - isLoading: false, - getApplication: result.current.getApplication, - }); + const { result } = renderHook(() => + useGetApplication({ + toastNotifications: services.notifications.toasts, + }) + ); + + expect(result.current).toEqual({ + isLoading: false, + getApplication: result.current.getApplication, }); }); it('calls getApplication with correct arguments', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useGetApplication({ - toastNotifications: services.notifications.toasts, - }) - ); + const { result } = renderHook(() => + useGetApplication({ + toastNotifications: services.notifications.toasts, + }) + ); - await waitForNextUpdate(); + await waitFor(() => null); + act(() => { result.current.getApplication({ appId: action.config.appId, apiToken: action.secrets.apiToken, apiUrl: action.config.apiUrl, }); + }); - await waitForNextUpdate(); - expect(getApplicationMock).toBeCalledWith({ - signal: abortCtrl.signal, - appId: action.config.appId, - apiToken: action.secrets.apiToken, - url: action.config.apiUrl, - }); + await waitFor(() => null); + expect(getApplicationMock).toBeCalledWith({ + signal: abortCtrl.signal, + appId: action.config.appId, + apiToken: action.secrets.apiToken, + url: action.config.apiUrl, }); }); it('get application', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useGetApplication({ - toastNotifications: services.notifications.toasts, - }) - ); - - await waitForNextUpdate(); + const { result } = renderHook(() => + useGetApplication({ + toastNotifications: services.notifications.toasts, + }) + ); + + await waitFor(() => null); + act(() => { result.current.getApplication({ appId: action.config.appId, apiToken: action.secrets.apiToken, apiUrl: action.config.apiUrl, }); - await waitForNextUpdate(); + }); + await waitFor(() => null); - expect(result.current).toEqual({ - isLoading: false, - getApplication: result.current.getApplication, - }); + expect(result.current).toEqual({ + isLoading: false, + getApplication: result.current.getApplication, }); }); it('set isLoading to true when getting the application', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useGetApplication({ - toastNotifications: services.notifications.toasts, - }) - ); - - await waitForNextUpdate(); + const { result } = renderHook(() => + useGetApplication({ + toastNotifications: services.notifications.toasts, + }) + ); + + await waitFor(() => null); + + act(() => { result.current.getApplication({ appId: action.config.appId, apiToken: action.secrets.apiToken, apiUrl: action.config.apiUrl, }); - - expect(result.current.isLoading).toBe(true); }); + + expect(result.current.isLoading).toBe(true); }); it('it displays an error when http throws an error', async () => { @@ -131,52 +130,52 @@ describe('useGetApplication', () => { throw new Error('Something went wrong'); }); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useGetApplication({ - toastNotifications: services.notifications.toasts, - }) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => + useGetApplication({ + toastNotifications: services.notifications.toasts, + }) + ); + await waitFor(() => null); + act(() => { result.current.getApplication({ appId: action.config.appId, apiToken: action.secrets.apiToken, apiUrl: action.config.apiUrl, }); + }); - expect(result.current).toEqual({ - isLoading: false, - getApplication: result.current.getApplication, - }); + expect(result.current).toEqual({ + isLoading: false, + getApplication: result.current.getApplication, + }); - expect(services.notifications.toasts.addDanger).toHaveBeenCalledWith({ - title: 'Unable to get application with id bcq16kdTbz5jlwM6h', - text: 'Something went wrong', - }); + expect(services.notifications.toasts.addDanger).toHaveBeenCalledWith({ + title: 'Unable to get application with id bcq16kdTbz5jlwM6h', + text: 'Something went wrong', }); }); it('it displays an error when the response does not contain the correct fields', async () => { getApplicationMock.mockResolvedValue({}); - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useGetApplication({ - toastNotifications: services.notifications.toasts, - }) - ); - await waitForNextUpdate(); + const { result } = renderHook(() => + useGetApplication({ + toastNotifications: services.notifications.toasts, + }) + ); + await waitFor(() => null); + act(() => { result.current.getApplication({ appId: action.config.appId, apiToken: action.secrets.apiToken, apiUrl: action.config.apiUrl, }); - await waitForNextUpdate(); + }); + await waitFor(() => null); - expect(services.notifications.toasts.addDanger).toHaveBeenCalledWith({ - title: 'Unable to get application with id bcq16kdTbz5jlwM6h', - text: 'Unable to get application fields', - }); + expect(services.notifications.toasts.addDanger).toHaveBeenCalledWith({ + title: 'Unable to get application with id bcq16kdTbz5jlwM6h', + text: 'Unable to get application fields', }); }); }); diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.test.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.test.tsx index 5007065113782..1677404c1cb12 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.test.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.test.tsx @@ -8,6 +8,7 @@ import React, { type FC, type PropsWithChildren } from 'react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; jest.mock('../../../../app_dependencies'); @@ -19,12 +20,11 @@ describe('Transform: Transform List Actions', () => { const wrapper: FC> = ({ children }) => ( {children} ); - const { result, waitForNextUpdate } = renderHook( - () => useActions({ forceDisable: false, transformNodes: 1 }), - { wrapper } - ); + const { result } = renderHook(() => useActions({ forceDisable: false, transformNodes: 1 }), { + wrapper, + }); - await waitForNextUpdate(); + await waitFor(() => null); const actions = result.current.actions; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_columns.test.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_columns.test.tsx index dcab70822ecd9..f3f59b03019bd 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_columns.test.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_columns.test.tsx @@ -8,6 +8,7 @@ import React, { type FC, type PropsWithChildren } from 'react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useColumns } from './use_columns'; @@ -19,11 +20,11 @@ describe('Transform: Job List Columns', () => { const wrapper: FC> = ({ children }) => ( {children} ); - const { result, waitForNextUpdate } = renderHook(() => useColumns([], () => {}, 1, [], false), { + const { result } = renderHook(() => useColumns([], () => {}, 1, [], false), { wrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); const columns: ReturnType['columns'] = result.current.columns; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_create_connector.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_create_connector.test.tsx index 5fe09dd8ae906..0b135c31ab159 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_create_connector.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_create_connector.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useKibana } from '../../common/lib/kibana'; import { useCreateConnector } from './use_create_connector'; @@ -29,7 +30,7 @@ describe('useCreateConnector', () => { }); it('executes correctly', async () => { - const { result, waitForNextUpdate } = renderHook(() => useCreateConnector()); + const { result } = renderHook(() => useCreateConnector()); act(() => { result.current.createConnector({ @@ -40,7 +41,7 @@ describe('useCreateConnector', () => { }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(useKibanaMock().services.http.post).toHaveBeenCalledWith('/api/actions/connector', { body: '{"name":"test","config":{},"secrets":{},"connector_type_id":".test"}', diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_execute_connector.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_execute_connector.test.tsx index 4b93900ea6b4e..d9863aece1058 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_execute_connector.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_execute_connector.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useKibana } from '../../common/lib/kibana'; import { useExecuteConnector } from './use_execute_connector'; @@ -29,13 +30,13 @@ describe('useExecuteConnector', () => { }); it('executes correctly', async () => { - const { result, waitForNextUpdate } = renderHook(() => useExecuteConnector()); + const { result } = renderHook(() => useExecuteConnector()); act(() => { result.current.executeConnector({ connectorId: 'test-id', params: {} }); }); - await waitForNextUpdate(); + await waitFor(() => null); expect(useKibanaMock().services.http.post).toHaveBeenCalledWith( '/api/actions/connector/test-id/_execute', diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_alert_summary.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_alert_summary.test.ts index e56c8aa1348b9..27eaa2d2ee808 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_alert_summary.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_alert_summary.test.ts @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { ValidFeatureId } from '@kbn/rule-data-utils'; import { useKibana } from '../../common/lib/kibana'; import { @@ -34,7 +35,7 @@ describe('useLoadAlertSummary', () => { ...mockedAlertSummaryResponse, }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useLoadAlertSummary({ featureIds, timeRange: mockedAlertSummaryTimeRange, @@ -49,7 +50,7 @@ describe('useLoadAlertSummary', () => { }, }); - await waitForNextUpdate(); + await waitFor(() => null); const { alertSummary, error } = result.current; expect(alertSummary).toEqual({ @@ -70,7 +71,7 @@ describe('useLoadAlertSummary', () => { ...mockedAlertSummaryResponse, }); - const { waitForNextUpdate } = renderHook(() => + renderHook(() => useLoadAlertSummary({ featureIds, timeRange: mockedAlertSummaryTimeRange, @@ -78,7 +79,7 @@ describe('useLoadAlertSummary', () => { }) ); - await waitForNextUpdate(); + await waitFor(() => null); const body = JSON.stringify({ fixed_interval: fixedInterval, @@ -99,14 +100,14 @@ describe('useLoadAlertSummary', () => { const error = new Error('Fetch Alert Summary Failed'); mockedPostAPI.mockRejectedValueOnce(error); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useLoadAlertSummary({ featureIds, timeRange: mockedAlertSummaryTimeRange, }) ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.error).toMatch(error.message); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations.test.tsx index c0e143119f6fa..8585e1ab5d1d7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations.test.tsx @@ -5,13 +5,12 @@ * 2.0. */ import React from 'react'; -import { renderHook } from '@testing-library/react-hooks/dom'; +import { renderHook, waitFor } from '@testing-library/react'; import { useLoadRuleAggregationsQuery as useLoadRuleAggregations } from './use_load_rule_aggregations_query'; import { RuleStatus } from '../../types'; import { useKibana } from '../../common/lib/kibana'; import { IToasts } from '@kbn/core-notifications-browser'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { waitFor } from '@testing-library/react'; jest.mock('../../common/lib/kibana'); jest.mock('../lib/rule_api/aggregate_kuery_filter', () => ({ @@ -75,7 +74,7 @@ describe('useLoadRuleAggregations', () => { refresh: undefined, }; - const { rerender, result, waitForNextUpdate } = renderHook( + const { rerender, result } = renderHook( () => { return useLoadRuleAggregations(params); }, @@ -83,7 +82,7 @@ describe('useLoadRuleAggregations', () => { ); rerender(); - await waitForNextUpdate(); + await waitFor(() => null); expect(loadRuleAggregationsWithKueryFilter).toBeCalledWith( expect.objectContaining({ @@ -115,15 +114,12 @@ describe('useLoadRuleAggregations', () => { refresh: undefined, }; - const { rerender, result, waitForNextUpdate } = renderHook( - () => useLoadRuleAggregations(params), - { - wrapper, - } - ); + const { rerender, result } = renderHook(() => useLoadRuleAggregations(params), { + wrapper, + }); rerender(); - await waitForNextUpdate(); + await waitFor(() => null); expect(loadRuleAggregationsWithKueryFilter).toBeCalledWith( expect.objectContaining({ diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.test.tsx index 8cc07c87e2411..06050b25040d0 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ import React from 'react'; -import { renderHook } from '@testing-library/react-hooks/dom'; +import { renderHook, waitFor } from '@testing-library/react'; import { useLoadRulesQuery as useLoadRules } from './use_load_rules_query'; import { RuleExecutionStatusErrorReasons, @@ -15,7 +15,6 @@ import { RuleStatus } from '../../types'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useKibana } from '../../common/lib/kibana'; import { IToasts } from '@kbn/core-notifications-browser'; -import { waitFor } from '@testing-library/react'; jest.mock('../../common/lib/kibana'); jest.mock('../lib/rule_api/rules_kuery_filter', () => ({ @@ -282,7 +281,7 @@ describe('useLoadRules', () => { sort: { field: 'name', direction: 'asc' }, }; - const { result, waitForNextUpdate, rerender } = renderHook(() => useLoadRules(params), { + const { result, rerender } = renderHook(() => useLoadRules(params), { wrapper, }); @@ -291,7 +290,7 @@ describe('useLoadRules', () => { expect(result.current.rulesState.isLoading).toBeTruthy(); rerender(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.rulesState.initialLoad).toBeFalsy(); expect(result.current.hasData).toBeTruthy(); @@ -339,12 +338,12 @@ describe('useLoadRules', () => { sort: { field: 'name', direction: 'asc' }, }; - const { waitForNextUpdate, rerender } = renderHook(() => useLoadRules(params), { + const { rerender } = renderHook(() => useLoadRules(params), { wrapper, }); rerender(); - await waitForNextUpdate(); + await waitFor(() => null); expect(loadRulesWithKueryFilter).toBeCalledWith( expect.objectContaining({ @@ -391,7 +390,7 @@ describe('useLoadRules', () => { sort: { field: 'name', direction: 'asc' }, }; - const { rerender, waitForNextUpdate } = renderHook( + const { rerender } = renderHook( () => { return useLoadRules(params); }, @@ -399,7 +398,7 @@ describe('useLoadRules', () => { ); rerender(); - await waitForNextUpdate(); + await waitFor(() => null); expect(onPage).toHaveBeenCalledWith({ index: 0, @@ -459,14 +458,14 @@ describe('useLoadRules', () => { sort: { field: 'name', direction: 'asc' }, }; - const { rerender, result, waitForNextUpdate } = renderHook(() => useLoadRules(params), { + const { rerender, result } = renderHook(() => useLoadRules(params), { wrapper, }); expect(result.current.hasData).toBeFalsy(); rerender(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.hasData).toBeFalsy(); }); @@ -494,14 +493,14 @@ describe('useLoadRules', () => { hasDefaultRuleTypesFiltersOn: true, }; - const { rerender, result, waitForNextUpdate } = renderHook(() => useLoadRules(params), { + const { rerender, result } = renderHook(() => useLoadRules(params), { wrapper, }); expect(result.current.hasData).toBeFalsy(); rerender(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.hasData).toBeFalsy(); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_tags_query.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_tags_query.test.tsx index 081538d1432ef..0cdc676db6015 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_tags_query.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_tags_query.test.tsx @@ -5,12 +5,11 @@ * 2.0. */ import React from 'react'; -import { renderHook } from '@testing-library/react-hooks/dom'; +import { renderHook, waitFor } from '@testing-library/react'; import { useLoadTagsQuery } from './use_load_tags_query'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useKibana } from '../../common/lib/kibana'; import { IToasts } from '@kbn/core-notifications-browser'; -import { waitFor } from '@testing-library/react'; const MOCK_TAGS = ['a', 'b', 'c']; @@ -53,7 +52,7 @@ describe('useLoadTagsQuery', () => { }); it('should call loadRuleTags API and handle result', async () => { - const { rerender, result, waitForNextUpdate } = renderHook( + const { rerender, result } = renderHook( () => useLoadTagsQuery({ enabled: true, @@ -67,7 +66,7 @@ describe('useLoadTagsQuery', () => { ); rerender(); - await waitForNextUpdate(); + await waitFor(() => null); expect(loadRuleTags).toHaveBeenLastCalledWith( expect.objectContaining({ @@ -88,7 +87,7 @@ describe('useLoadTagsQuery', () => { perPage: 5, total: 10, }); - const { rerender, result, waitForNextUpdate } = renderHook( + const { rerender, result } = renderHook( () => useLoadTagsQuery({ enabled: true, @@ -101,7 +100,7 @@ describe('useLoadTagsQuery', () => { ); rerender(); - await waitForNextUpdate(); + await waitFor(() => null); expect(loadRuleTags).toHaveBeenLastCalledWith( expect.objectContaining({ @@ -129,7 +128,7 @@ describe('useLoadTagsQuery', () => { ); rerender(); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.hasNextPage).toEqual(false); }); @@ -142,7 +141,7 @@ describe('useLoadTagsQuery', () => { total: 0, }); - const { rerender, result, waitForNextUpdate } = renderHook( + const { rerender, result } = renderHook( () => useLoadTagsQuery({ enabled: true, @@ -155,7 +154,7 @@ describe('useLoadTagsQuery', () => { ); rerender(); - await waitForNextUpdate(); + await waitFor(() => null); expect(loadRuleTags).toHaveBeenLastCalledWith( expect.objectContaining({ diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_sub_action.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_sub_action.test.tsx index 1f2552511de00..56996644ef043 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_sub_action.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_sub_action.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useKibana } from '../../common/lib/kibana'; import { useSubAction, UseSubActionParams } from './use_sub_action'; @@ -30,8 +31,8 @@ describe('useSubAction', () => { }); it('init', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSubAction(params)); - await waitForNextUpdate(); + const { result } = renderHook(() => useSubAction(params)); + await waitFor(() => null); expect(result.current).toEqual({ isLoading: false, @@ -41,8 +42,8 @@ describe('useSubAction', () => { }); it('executes the sub action correctly', async () => { - const { waitForNextUpdate } = renderHook(() => useSubAction(params)); - await waitForNextUpdate(); + renderHook(() => useSubAction(params)); + await waitFor(() => null); expect(mockHttpPost).toHaveBeenCalledWith('/api/actions/connector/test-id/_execute', { body: '{"params":{"subAction":"test","subActionParams":{"foo":"bar"}}}', @@ -51,45 +52,45 @@ describe('useSubAction', () => { }); it('executes sub action if subAction parameter changes', async () => { - const { rerender, waitForNextUpdate } = renderHook(useSubAction, { initialProps: params }); - await waitForNextUpdate(); + const { rerender } = renderHook(useSubAction, { initialProps: params }); + await waitFor(() => null); expect(mockHttpPost).toHaveBeenCalledTimes(1); await act(async () => { rerender({ ...params, subAction: 'test-2' }); - await waitForNextUpdate(); + await waitFor(() => null); }); expect(mockHttpPost).toHaveBeenCalledTimes(2); }); it('executes sub action if connectorId parameter changes', async () => { - const { rerender, waitForNextUpdate } = renderHook(useSubAction, { initialProps: params }); - await waitForNextUpdate(); + const { rerender } = renderHook(useSubAction, { initialProps: params }); + await waitFor(() => null); expect(mockHttpPost).toHaveBeenCalledTimes(1); await act(async () => { rerender({ ...params, connectorId: 'test-id-2' }); - await waitForNextUpdate(); + await waitFor(() => null); }); expect(mockHttpPost).toHaveBeenCalledTimes(2); }); it('returns memoized response if subActionParams changes but values are equal', async () => { - const { result, rerender, waitForNextUpdate } = renderHook(useSubAction, { + const { result, rerender } = renderHook(useSubAction, { initialProps: { ...params, subActionParams: { foo: 'bar' } }, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(mockHttpPost).toHaveBeenCalledTimes(1); const previous = result.current; await act(async () => { rerender({ ...params, subActionParams: { foo: 'bar' } }); - await waitForNextUpdate(); + await waitFor(() => null); }); expect(result.current.response).toBe(previous.response); @@ -97,17 +98,17 @@ describe('useSubAction', () => { }); it('executes sub action if subActionParams changes and values are not equal', async () => { - const { result, rerender, waitForNextUpdate } = renderHook(useSubAction, { + const { result, rerender } = renderHook(useSubAction, { initialProps: { ...params, subActionParams: { foo: 'bar' } }, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(mockHttpPost).toHaveBeenCalledTimes(1); const previous = result.current; await act(async () => { rerender({ ...params, subActionParams: { foo: 'baz' } }); - await waitForNextUpdate(); + await waitFor(() => null); }); expect(result.current.response).not.toBe(previous.response); @@ -118,8 +119,8 @@ describe('useSubAction', () => { const error = new Error('error executing'); mockHttpPost.mockRejectedValueOnce(error); - const { result, waitForNextUpdate } = renderHook(() => useSubAction(params)); - await waitForNextUpdate(); + const { result } = renderHook(() => useSubAction(params)); + await waitFor(() => null); expect(result.current).toEqual({ isLoading: false, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_get_muted_alerts.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_get_muted_alerts.test.tsx index 8d65532c5f10a..67aac2638f9cf 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_get_muted_alerts.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_get_muted_alerts.test.tsx @@ -31,11 +31,11 @@ describe('useGetMutedAlerts', () => { it('calls the api when invoked with the correct parameters', async () => { const muteAlertInstanceSpy = jest.spyOn(api, 'getMutedAlerts'); - const { waitForNextUpdate } = renderHook(() => useGetMutedAlerts(ruleIds), { + renderHook(() => useGetMutedAlerts(ruleIds), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); await waitFor(() => { expect(muteAlertInstanceSpy).toHaveBeenCalledWith( @@ -59,11 +59,11 @@ describe('useGetMutedAlerts', () => { it('shows a toast error when the api returns an error', async () => { const spy = jest.spyOn(api, 'getMutedAlerts').mockRejectedValue(new Error('An error')); - const { waitForNextUpdate } = renderHook(() => useGetMutedAlerts(ruleIds), { + renderHook(() => useGetMutedAlerts(ruleIds), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); await waitFor(() => { expect(spy).toHaveBeenCalled(); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_get_cases.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_get_cases.test.tsx index b4598f56c02f2..097fb5de87621 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_get_cases.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_get_cases.test.tsx @@ -35,11 +35,11 @@ describe('useBulkGetCases', () => { const spy = jest.spyOn(api, 'bulkGetCases'); spy.mockResolvedValue(response); - const { waitForNextUpdate } = renderHook(() => useBulkGetCases(['case-1'], true), { + renderHook(() => useBulkGetCases(['case-1'], true), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); expect(spy).toHaveBeenCalledWith( expect.anything(), @@ -64,11 +64,11 @@ describe('useBulkGetCases', () => { it('shows a toast error when the api return an error', async () => { const spy = jest.spyOn(api, 'bulkGetCases').mockRejectedValue(new Error('An error')); - const { waitForNextUpdate } = renderHook(() => useBulkGetCases(['case-1'], true), { + renderHook(() => useBulkGetCases(['case-1'], true), { wrapper: appMockRender.AppWrapper, }); - await waitForNextUpdate(); + await waitFor(() => null); await waitFor(() => { expect(spy).toHaveBeenCalledWith( diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_get_maintenance_windows.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_get_maintenance_windows.test.ts index b1f8a65e16037..7b5aaf87a9335 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_get_maintenance_windows.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_get_maintenance_windows.test.ts @@ -96,7 +96,7 @@ describe('useBulkGetMaintenanceWindows', () => { const spy = jest.spyOn(api, 'bulkGetMaintenanceWindows'); spy.mockResolvedValue(response); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useBulkGetMaintenanceWindows({ ids: ['test-id'], @@ -107,7 +107,7 @@ describe('useBulkGetMaintenanceWindows', () => { } ); - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.data?.get('test-id')).toEqual(mockMaintenanceWindow); @@ -185,7 +185,7 @@ describe('useBulkGetMaintenanceWindows', () => { .spyOn(api, 'bulkGetMaintenanceWindows') .mockRejectedValue(new Error('An error')); - const { waitForNextUpdate } = renderHook( + renderHook( () => useBulkGetMaintenanceWindows({ ids: ['test-id'], @@ -196,7 +196,7 @@ describe('useBulkGetMaintenanceWindows', () => { } ); - await waitForNextUpdate(); + await waitFor(() => null); await waitFor(() => { expect(spy).toHaveBeenCalledWith({ From 896d91118193739d56115b063a9178d0ddfe35c5 Mon Sep 17 00:00:00 2001 From: Eyo Okon Eyo Date: Mon, 23 Sep 2024 17:02:30 +0100 Subject: [PATCH 02/18] fix missed waitFor usages --- .../src/hooks/use_grouping.test.tsx | 152 +++++++++--------- .../src/hooks/use_field_filters.test.tsx | 2 +- .../hooks/use_update_user_profile.test.tsx | 15 +- .../assignees/use_assignees_action.test.tsx | 9 +- .../copy_id/use_copy_id_action.test.tsx | 5 +- .../severity/use_severity_action.test.tsx | 9 +- .../actions/status/use_status_action.test.tsx | 9 +- .../actions/tags/use_tags_action.test.tsx | 9 +- .../actions/use_items_action.test.tsx | 25 +-- .../use_get_fields_by_issue_type.test.tsx | 7 +- .../connectors/jira/use_get_issue.test.tsx | 7 +- .../jira/use_get_issue_types.test.tsx | 7 +- .../connectors/jira/use_get_issues.test.tsx | 7 +- .../resilient/use_get_incident_types.test.tsx | 7 +- .../resilient/use_get_severity.test.tsx | 7 +- .../servicenow/use_get_choices.test.tsx | 7 +- .../use_markdown_session_storage.test.tsx | 22 ++- .../use_user_actions_pagination.test.tsx | 11 +- .../use_persist_configuration.test.tsx | 19 +-- .../use_get_case_connectors.test.tsx | 5 +- .../containers/use_messages_storage.test.tsx | 38 ++--- .../use_get_current_user_profile.test.ts | 7 +- .../single_page_layout/hooks/form.test.tsx | 19 ++- .../hooks/setup_technology.test.ts | 5 +- .../single_page_layout/index.test.tsx | 16 +- .../hooks/use_action_status.test.tsx | 3 +- .../hooks/use_agent_soft_limit.test.tsx | 8 +- .../hooks/use_fetch_agents_data.test.tsx | 6 +- .../hooks/use_update_tags.test.tsx | 3 +- .../hooks/use_fleet_server_unhealthy.test.tsx | 12 +- .../public/hooks/use_dismissable_tour.test.ts | 3 +- .../public/mock/create_test_renderer.tsx | 2 + .../helpers/use_workspace_loader.test.tsx | 3 +- .../ml/ml_notifications_context.test.tsx | 3 +- .../hooks/use_composite_image.test.tsx | 3 +- .../hooks/use_monitor_name.test.tsx | 17 +- .../cases/use_case_view_navigation.test.ts | 7 +- .../hooks/use_columns/use_columns.test.tsx | 8 +- 38 files changed, 262 insertions(+), 242 deletions(-) diff --git a/packages/kbn-grouping/src/hooks/use_grouping.test.tsx b/packages/kbn-grouping/src/hooks/use_grouping.test.tsx index 4dc9f1332a97c..3eebec2facdc6 100644 --- a/packages/kbn-grouping/src/hooks/use_grouping.test.tsx +++ b/packages/kbn-grouping/src/hooks/use_grouping.test.tsx @@ -8,9 +8,9 @@ */ import React from 'react'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; -import { render } from '@testing-library/react'; +import { render, waitFor } from '@testing-library/react'; import { useGrouping } from './use_grouping'; @@ -46,90 +46,86 @@ const groupingArgs = { describe('useGrouping', () => { it('Renders child component without grouping table wrapper when no group is selected', async () => { - await act(async () => { - const { result } = renderHook(() => useGrouping(defaultArgs)); - await waitFor(() => null); - const { getByTestId, queryByTestId } = render( - - {result.current.getGrouping({ - ...groupingArgs, - data: { - groupsCount: { - value: 9, - }, - groupByFields: { - buckets: [ - { - key: ['critical hosts', 'description'], - key_as_string: 'critical hosts|description', - doc_count: 3, - unitsCount: { - value: 3, - }, + const { result } = renderHook(() => useGrouping(defaultArgs)); + await waitFor(() => null); + const { getByTestId, queryByTestId } = render( + + {result.current.getGrouping({ + ...groupingArgs, + data: { + groupsCount: { + value: 9, + }, + groupByFields: { + buckets: [ + { + key: ['critical hosts', 'description'], + key_as_string: 'critical hosts|description', + doc_count: 3, + unitsCount: { + value: 3, }, - ], - }, - unitsCount: { - value: 18, - }, + }, + ], + }, + unitsCount: { + value: 18, }, - renderChildComponent: () =>

{'hello'}

, - selectedGroup: 'none', - })} -
- ); + }, + renderChildComponent: () =>

{'hello'}

, + selectedGroup: 'none', + })} +
+ ); - expect(getByTestId('innerTable')).toBeInTheDocument(); - expect(queryByTestId('grouping-table')).not.toBeInTheDocument(); - }); + expect(getByTestId('innerTable')).toBeInTheDocument(); + expect(queryByTestId('grouping-table')).not.toBeInTheDocument(); }); it('Renders child component with grouping table wrapper when group is selected', async () => { - await act(async () => { - const getItem = jest.spyOn(window.localStorage.__proto__, 'getItem'); - getItem.mockReturnValue( - JSON.stringify({ - 'test-table': { - itemsPerPageOptions: [10, 25, 50, 100], - itemsPerPage: 25, - activeGroup: 'kibana.alert.rule.name', - options: defaultGroupingOptions, - }, - }) - ); + const getItem = jest.spyOn(window.localStorage.__proto__, 'getItem'); + getItem.mockReturnValue( + JSON.stringify({ + 'test-table': { + itemsPerPageOptions: [10, 25, 50, 100], + itemsPerPage: 25, + activeGroup: 'kibana.alert.rule.name', + options: defaultGroupingOptions, + }, + }) + ); - const { result } = renderHook(() => useGrouping(defaultArgs)); - await waitFor(() => null); - const { getByTestId } = render( - - {result.current.getGrouping({ - ...groupingArgs, - data: { - groupsCount: { - value: 9, - }, - groupByFields: { - buckets: [ - { - key: ['critical hosts', 'description'], - key_as_string: 'critical hosts|description', - doc_count: 3, - unitsCount: { - value: 3, - }, + const { result } = renderHook(() => useGrouping(defaultArgs)); + await waitFor(() => null); + const { getByTestId } = render( + + {result.current.getGrouping({ + ...groupingArgs, + data: { + groupsCount: { + value: 9, + }, + groupByFields: { + buckets: [ + { + key: ['critical hosts', 'description'], + key_as_string: 'critical hosts|description', + doc_count: 3, + unitsCount: { + value: 3, }, - ], - }, - unitsCount: { - value: 18, - }, + }, + ], + }, + unitsCount: { + value: 18, }, - renderChildComponent: jest.fn(), - selectedGroup: 'test', - })} - - ); + }, + renderChildComponent: jest.fn(), + selectedGroup: 'test', + })} + + ); - expect(getByTestId('grouping-table')).toBeInTheDocument(); - }); + expect(getByTestId('grouping-table')).toBeInTheDocument(); }); }); diff --git a/packages/kbn-unified-field-list/src/hooks/use_field_filters.test.tsx b/packages/kbn-unified-field-list/src/hooks/use_field_filters.test.tsx index d0adb4125ab3d..649809f0fda80 100644 --- a/packages/kbn-unified-field-list/src/hooks/use_field_filters.test.tsx +++ b/packages/kbn-unified-field-list/src/hooks/use_field_filters.test.tsx @@ -8,7 +8,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; -import { act } from 'react-test-renderer'; +import { act } from '@testing-library/react'; import { stubLogstashDataView as dataView } from '@kbn/data-views-plugin/common/data_view.stub'; import type { DataViewField } from '@kbn/data-views-plugin/common'; import { coreMock } from '@kbn/core/public/mocks'; diff --git a/packages/kbn-user-profile-components/src/hooks/use_update_user_profile.test.tsx b/packages/kbn-user-profile-components/src/hooks/use_update_user_profile.test.tsx index 87d41bd222637..5ba47b4c56c68 100644 --- a/packages/kbn-user-profile-components/src/hooks/use_update_user_profile.test.tsx +++ b/packages/kbn-user-profile-components/src/hooks/use_update_user_profile.test.tsx @@ -7,7 +7,8 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { act, renderHook, type WrapperComponent } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; +import { renderHook, type WrapperComponent } from '@testing-library/react-hooks'; import React from 'react'; import { BehaviorSubject, first, lastValueFrom, of } from 'rxjs'; @@ -78,7 +79,7 @@ describe('useUpdateUserProfile() hook', () => { await lastValueFrom(updateDone.pipe(first((v) => v === true))); }); - const { result, waitForNextUpdate } = renderHook(() => useUpdateUserProfile(), { wrapper }); + const { result } = renderHook(() => useUpdateUserProfile(), { wrapper }); const { update } = result.current; expect(result.current.isLoading).toBeFalsy(); @@ -90,7 +91,7 @@ describe('useUpdateUserProfile() hook', () => { expect(result.current.isLoading).toBeTruthy(); updateDone.next(true); // Resolve the http.post promise - await waitForNextUpdate(); + await waitFor(() => null); expect(result.current.isLoading).toBeFalsy(); }); @@ -118,7 +119,9 @@ describe('useUpdateUserProfile() hook', () => { return true; }; - const { result } = renderHook(() => useUpdateUserProfile({ pageReloadChecker }), { wrapper }); + const { result } = renderHook(() => useUpdateUserProfile({ pageReloadChecker }), { + wrapper, + }); const { update } = result.current; await act(async () => { @@ -146,7 +149,9 @@ describe('useUpdateUserProfile() hook', () => { userProfile$: of(initialValue), }; - const { result } = renderHook(() => useUpdateUserProfile({ pageReloadChecker }), { wrapper }); + const { result } = renderHook(() => useUpdateUserProfile({ pageReloadChecker }), { + wrapper, + }); const { update } = result.current; const nextValue = { userSettings: { darkMode: 'light' as const } }; diff --git a/x-pack/plugins/cases/public/components/actions/assignees/use_assignees_action.test.tsx b/x-pack/plugins/cases/public/components/actions/assignees/use_assignees_action.test.tsx index 98cac1dfaf466..73af88262ae64 100644 --- a/x-pack/plugins/cases/public/components/actions/assignees/use_assignees_action.test.tsx +++ b/x-pack/plugins/cases/public/components/actions/assignees/use_assignees_action.test.tsx @@ -7,7 +7,8 @@ import type { AppMockRenderer } from '../../../common/mock'; import { createAppMockRenderer } from '../../../common/mock'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useAssigneesAction } from './use_assignees_action'; import * as api from '../../../containers/api'; @@ -56,7 +57,7 @@ describe('useAssigneesAction', () => { it('update the assignees correctly', async () => { const updateSpy = jest.spyOn(api, 'updateCases'); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useAssigneesAction({ onAction, onActionSuccess, isDisabled: false }), { wrapper: appMockRender.AppWrapper, @@ -92,7 +93,7 @@ describe('useAssigneesAction', () => { }); it('shows the success toaster correctly when updating one case', async () => { - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useAssigneesAction({ onAction, onActionSuccess, isDisabled: false }), { wrapper: appMockRender.AppWrapper, @@ -118,7 +119,7 @@ describe('useAssigneesAction', () => { }); it('shows the success toaster correctly when updating multiple cases', async () => { - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useAssigneesAction({ onAction, onActionSuccess, isDisabled: false }), { wrapper: appMockRender.AppWrapper, diff --git a/x-pack/plugins/cases/public/components/actions/copy_id/use_copy_id_action.test.tsx b/x-pack/plugins/cases/public/components/actions/copy_id/use_copy_id_action.test.tsx index 388b3de940ec5..e8075b76676d8 100644 --- a/x-pack/plugins/cases/public/components/actions/copy_id/use_copy_id_action.test.tsx +++ b/x-pack/plugins/cases/public/components/actions/copy_id/use_copy_id_action.test.tsx @@ -8,6 +8,7 @@ import type { AppMockRenderer } from '../../../common/mock'; import { createAppMockRenderer } from '../../../common/mock'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useCopyIDAction } from './use_copy_id_action'; import { basicCase } from '../../../containers/mock'; @@ -58,7 +59,7 @@ describe('useCopyIDAction', () => { }); it('copies the id of the selected case to the clipboard', async () => { - const { result, waitFor } = renderHook(() => useCopyIDAction({ onActionSuccess }), { + const { result } = renderHook(() => useCopyIDAction({ onActionSuccess }), { wrapper: appMockRender.AppWrapper, }); @@ -73,7 +74,7 @@ describe('useCopyIDAction', () => { }); it('shows the success toaster correctly when copying the case id', async () => { - const { result, waitFor } = renderHook(() => useCopyIDAction({ onActionSuccess }), { + const { result } = renderHook(() => useCopyIDAction({ onActionSuccess }), { wrapper: appMockRender.AppWrapper, }); diff --git a/x-pack/plugins/cases/public/components/actions/severity/use_severity_action.test.tsx b/x-pack/plugins/cases/public/components/actions/severity/use_severity_action.test.tsx index 79ae67610d902..9f3f8ab65d3d2 100644 --- a/x-pack/plugins/cases/public/components/actions/severity/use_severity_action.test.tsx +++ b/x-pack/plugins/cases/public/components/actions/severity/use_severity_action.test.tsx @@ -7,7 +7,8 @@ import type { AppMockRenderer } from '../../../common/mock'; import { createAppMockRenderer } from '../../../common/mock'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useSeverityAction } from './use_severity_action'; import * as api from '../../../containers/api'; @@ -80,7 +81,7 @@ describe('useSeverityAction', () => { it('update the severity cases', async () => { const updateSpy = jest.spyOn(api, 'updateCases'); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useSeverityAction({ onAction, onActionSuccess, isDisabled: false }), { wrapper: appMockRender.AppWrapper, @@ -120,7 +121,7 @@ describe('useSeverityAction', () => { it.each(singleCaseTests)( 'shows the success toaster correctly when updating the severity of the case: %s', async (_, index, expectedMessage) => { - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useSeverityAction({ onAction, onActionSuccess, isDisabled: false }), { wrapper: appMockRender.AppWrapper, @@ -153,7 +154,7 @@ describe('useSeverityAction', () => { it.each(multipleCasesTests)( 'shows the success toaster correctly when updating the severity of the case: %s', async (_, index, expectedMessage) => { - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useSeverityAction({ onAction, onActionSuccess, isDisabled: false }), { wrapper: appMockRender.AppWrapper, diff --git a/x-pack/plugins/cases/public/components/actions/status/use_status_action.test.tsx b/x-pack/plugins/cases/public/components/actions/status/use_status_action.test.tsx index bb4aef3379aa3..15da87ad1b3a1 100644 --- a/x-pack/plugins/cases/public/components/actions/status/use_status_action.test.tsx +++ b/x-pack/plugins/cases/public/components/actions/status/use_status_action.test.tsx @@ -7,7 +7,8 @@ import type { AppMockRenderer } from '../../../common/mock'; import { createAppMockRenderer } from '../../../common/mock'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useStatusAction } from './use_status_action'; import * as api from '../../../containers/api'; @@ -72,7 +73,7 @@ describe('useStatusAction', () => { it('update the status cases', async () => { const updateSpy = jest.spyOn(api, 'updateCases'); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useStatusAction({ onAction, onActionSuccess, isDisabled: false }), { wrapper: appMockRender.AppWrapper, @@ -110,7 +111,7 @@ describe('useStatusAction', () => { it.each(singleCaseTests)( 'shows the success toaster correctly when updating the status of the case: %s', async (_, index, expectedMessage) => { - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useStatusAction({ onAction, onActionSuccess, isDisabled: false }), { wrapper: appMockRender.AppWrapper, @@ -142,7 +143,7 @@ describe('useStatusAction', () => { it.each(multipleCasesTests)( 'shows the success toaster correctly when updating the status of the case: %s', async (_, index, expectedMessage) => { - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useStatusAction({ onAction, onActionSuccess, isDisabled: false }), { wrapper: appMockRender.AppWrapper, diff --git a/x-pack/plugins/cases/public/components/actions/tags/use_tags_action.test.tsx b/x-pack/plugins/cases/public/components/actions/tags/use_tags_action.test.tsx index 14973cc59be78..4980768d140db 100644 --- a/x-pack/plugins/cases/public/components/actions/tags/use_tags_action.test.tsx +++ b/x-pack/plugins/cases/public/components/actions/tags/use_tags_action.test.tsx @@ -7,7 +7,8 @@ import type { AppMockRenderer } from '../../../common/mock'; import { createAppMockRenderer } from '../../../common/mock'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useTagsAction } from './use_tags_action'; import * as api from '../../../containers/api'; @@ -56,7 +57,7 @@ describe('useTagsAction', () => { it('update the tags correctly', async () => { const updateSpy = jest.spyOn(api, 'updateCases'); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useTagsAction({ onAction, onActionSuccess, isDisabled: false }), { wrapper: appMockRender.AppWrapper, @@ -86,7 +87,7 @@ describe('useTagsAction', () => { }); it('shows the success toaster correctly when updating one case', async () => { - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useTagsAction({ onAction, onActionSuccess, isDisabled: false }), { wrapper: appMockRender.AppWrapper, @@ -112,7 +113,7 @@ describe('useTagsAction', () => { }); it('shows the success toaster correctly when updating multiple cases', async () => { - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useTagsAction({ onAction, onActionSuccess, isDisabled: false }), { wrapper: appMockRender.AppWrapper, diff --git a/x-pack/plugins/cases/public/components/actions/use_items_action.test.tsx b/x-pack/plugins/cases/public/components/actions/use_items_action.test.tsx index 25a08007ac31a..332a59c8cf883 100644 --- a/x-pack/plugins/cases/public/components/actions/use_items_action.test.tsx +++ b/x-pack/plugins/cases/public/components/actions/use_items_action.test.tsx @@ -7,7 +7,8 @@ import type { AppMockRenderer } from '../../common/mock'; import { createAppMockRenderer } from '../../common/mock'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useItemsAction } from './use_items_action'; import * as api from '../../containers/api'; @@ -54,7 +55,7 @@ describe('useItemsAction', () => { }); it('closes the flyout', async () => { - const { result, waitFor } = renderHook(() => useItemsAction(props), { + const { result } = renderHook(() => useItemsAction(props), { wrapper: appMockRender.AppWrapper, }); @@ -81,7 +82,7 @@ describe('useItemsAction', () => { it('update the items correctly', async () => { const updateSpy = jest.spyOn(api, 'updateCases'); - const { result, waitFor } = renderHook(() => useItemsAction(props), { + const { result } = renderHook(() => useItemsAction(props), { wrapper: appMockRender.AppWrapper, }); @@ -117,7 +118,7 @@ describe('useItemsAction', () => { }); it('calls fieldSelector correctly', async () => { - const { result, waitFor } = renderHook(() => useItemsAction(props), { + const { result } = renderHook(() => useItemsAction(props), { wrapper: appMockRender.AppWrapper, }); @@ -142,7 +143,7 @@ describe('useItemsAction', () => { }); it('calls itemsTransformer correctly', async () => { - const { result, waitFor } = renderHook(() => useItemsAction(props), { + const { result } = renderHook(() => useItemsAction(props), { wrapper: appMockRender.AppWrapper, }); @@ -169,7 +170,7 @@ describe('useItemsAction', () => { it('removes duplicates', async () => { const updateSpy = jest.spyOn(api, 'updateCases'); - const { result, waitFor } = renderHook(() => useItemsAction(props), { + const { result } = renderHook(() => useItemsAction(props), { wrapper: appMockRender.AppWrapper, }); @@ -203,7 +204,7 @@ describe('useItemsAction', () => { }); it('shows the success toaster correctly when updating a case', async () => { - const { result, waitFor } = renderHook(() => useItemsAction(props), { + const { result } = renderHook(() => useItemsAction(props), { wrapper: appMockRender.AppWrapper, }); @@ -229,7 +230,7 @@ describe('useItemsAction', () => { it('do not update cases with no changes', async () => { const updateSpy = jest.spyOn(api, 'updateCases'); - const { result, waitFor } = renderHook(() => useItemsAction(props), { + const { result } = renderHook(() => useItemsAction(props), { wrapper: appMockRender.AppWrapper, }); @@ -254,7 +255,7 @@ describe('useItemsAction', () => { it('do not update if the selected items are the same but with different order', async () => { const updateSpy = jest.spyOn(api, 'updateCases'); - const { result, waitFor } = renderHook(() => useItemsAction(props), { + const { result } = renderHook(() => useItemsAction(props), { wrapper: appMockRender.AppWrapper, }); @@ -279,7 +280,7 @@ describe('useItemsAction', () => { it('do not update if the selected items are the same', async () => { const updateSpy = jest.spyOn(api, 'updateCases'); - const { result, waitFor } = renderHook(() => useItemsAction(props), { + const { result } = renderHook(() => useItemsAction(props), { wrapper: appMockRender.AppWrapper, }); @@ -304,7 +305,7 @@ describe('useItemsAction', () => { it('do not update if selecting and unselecting the same item', async () => { const updateSpy = jest.spyOn(api, 'updateCases'); - const { result, waitFor } = renderHook(() => useItemsAction(props), { + const { result } = renderHook(() => useItemsAction(props), { wrapper: appMockRender.AppWrapper, }); @@ -329,7 +330,7 @@ describe('useItemsAction', () => { it('do not update with empty items and no selection', async () => { const updateSpy = jest.spyOn(api, 'updateCases'); - const { result, waitFor } = renderHook(() => useItemsAction(props), { + const { result } = renderHook(() => useItemsAction(props), { wrapper: appMockRender.AppWrapper, }); diff --git a/x-pack/plugins/cases/public/components/connectors/jira/use_get_fields_by_issue_type.test.tsx b/x-pack/plugins/cases/public/components/connectors/jira/use_get_fields_by_issue_type.test.tsx index f1cb277f1a24b..6af6dd13e1895 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/use_get_fields_by_issue_type.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/jira/use_get_fields_by_issue_type.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useKibana, useToasts } from '../../../common/lib/kibana'; import { connector } from '../mock'; @@ -30,7 +31,7 @@ describe('useGetFieldsByIssueType', () => { it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'getFieldsByIssueType'); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useGetFieldsByIssueType({ http, @@ -88,7 +89,7 @@ describe('useGetFieldsByIssueType', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError }); - const { waitFor } = renderHook( + renderHook( () => useGetFieldsByIssueType({ http, @@ -114,7 +115,7 @@ describe('useGetFieldsByIssueType', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError }); - const { waitFor } = renderHook( + renderHook( () => useGetFieldsByIssueType({ http, diff --git a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue.test.tsx b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue.test.tsx index 876738025e6a8..ae8d3fded83a7 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useKibana, useToasts } from '../../../common/lib/kibana'; import { connector as actionConnector } from '../mock'; @@ -30,7 +31,7 @@ describe('useGetIssue', () => { it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'getIssue'); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useGetIssue({ http, @@ -88,7 +89,7 @@ describe('useGetIssue', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError }); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useGetIssue({ http, @@ -114,7 +115,7 @@ describe('useGetIssue', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError }); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useGetIssue({ http, diff --git a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue_types.test.tsx b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue_types.test.tsx index 0d7e3127dd9fe..162ec06ef0a28 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue_types.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue_types.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useKibana, useToasts } from '../../../common/lib/kibana'; import { connector } from '../mock'; @@ -30,7 +31,7 @@ describe('useGetIssueTypes', () => { it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'getIssueTypes'); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useGetIssueTypes({ http, @@ -70,7 +71,7 @@ describe('useGetIssueTypes', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError }); - const { waitFor } = renderHook( + renderHook( () => useGetIssueTypes({ http, @@ -95,7 +96,7 @@ describe('useGetIssueTypes', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError }); - const { waitFor } = renderHook( + renderHook( () => useGetIssueTypes({ http, diff --git a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issues.test.tsx b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issues.test.tsx index a06cd4391f766..2edb0ac38e377 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issues.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issues.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useKibana, useToasts } from '../../../common/lib/kibana'; import { connector as actionConnector } from '../mock'; @@ -30,7 +31,7 @@ describe('useGetIssues', () => { it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'getIssues'); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useGetIssues({ http, @@ -74,7 +75,7 @@ describe('useGetIssues', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError }); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useGetIssues({ http, @@ -100,7 +101,7 @@ describe('useGetIssues', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError }); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useGetIssues({ http, diff --git a/x-pack/plugins/cases/public/components/connectors/resilient/use_get_incident_types.test.tsx b/x-pack/plugins/cases/public/components/connectors/resilient/use_get_incident_types.test.tsx index 7bd0c16a6a4d5..8b314ff11f646 100644 --- a/x-pack/plugins/cases/public/components/connectors/resilient/use_get_incident_types.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/resilient/use_get_incident_types.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useKibana, useToasts } from '../../../common/lib/kibana'; import { connector } from '../mock'; @@ -30,7 +31,7 @@ describe('useGetIncidentTypes', () => { it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'getIncidentTypes'); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useGetIncidentTypes({ http, @@ -70,7 +71,7 @@ describe('useGetIncidentTypes', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError }); - const { waitFor } = renderHook( + renderHook( () => useGetIncidentTypes({ http, @@ -95,7 +96,7 @@ describe('useGetIncidentTypes', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError }); - const { waitFor } = renderHook( + renderHook( () => useGetIncidentTypes({ http, diff --git a/x-pack/plugins/cases/public/components/connectors/resilient/use_get_severity.test.tsx b/x-pack/plugins/cases/public/components/connectors/resilient/use_get_severity.test.tsx index 6f59b4d50c31c..c7f742b638c3a 100644 --- a/x-pack/plugins/cases/public/components/connectors/resilient/use_get_severity.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/resilient/use_get_severity.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useKibana, useToasts } from '../../../common/lib/kibana'; import { connector } from '../mock'; @@ -30,7 +31,7 @@ describe('useGetSeverity', () => { it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'getSeverity'); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useGetSeverity({ http, @@ -70,7 +71,7 @@ describe('useGetSeverity', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError }); - const { waitFor } = renderHook( + renderHook( () => useGetSeverity({ http, @@ -95,7 +96,7 @@ describe('useGetSeverity', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError }); - const { waitFor } = renderHook( + renderHook( () => useGetSeverity({ http, diff --git a/x-pack/plugins/cases/public/components/connectors/servicenow/use_get_choices.test.tsx b/x-pack/plugins/cases/public/components/connectors/servicenow/use_get_choices.test.tsx index 1508817619501..e5825dba22bd9 100644 --- a/x-pack/plugins/cases/public/components/connectors/servicenow/use_get_choices.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/servicenow/use_get_choices.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useKibana, useToasts } from '../../../common/lib/kibana'; import type { ActionConnector } from '../../../../common/types/domain'; @@ -47,7 +48,7 @@ describe('useGetChoices', () => { it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'getChoices'); - const { waitFor } = renderHook( + renderHook( () => useGetChoices({ http, @@ -92,7 +93,7 @@ describe('useGetChoices', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError }); - const { waitFor } = renderHook( + renderHook( () => useGetChoices({ http, @@ -118,7 +119,7 @@ describe('useGetChoices', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError }); - const { waitFor } = renderHook( + renderHook( () => useGetChoices({ http, diff --git a/x-pack/plugins/cases/public/components/markdown_editor/use_markdown_session_storage.test.tsx b/x-pack/plugins/cases/public/components/markdown_editor/use_markdown_session_storage.test.tsx index e4ce68ed45237..4d50aabf380b8 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/use_markdown_session_storage.test.tsx +++ b/x-pack/plugins/cases/public/components/markdown_editor/use_markdown_session_storage.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import type { FieldHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import type { SessionStorageType } from './use_markdown_session_storage'; import { useMarkdownSessionStorage } from './use_markdown_session_storage'; @@ -45,7 +46,7 @@ describe('useMarkdownSessionStorage', () => { }); it('should return hasConflicts as false', async () => { - const { result, waitFor } = renderHook(() => + const { result } = renderHook(() => useMarkdownSessionStorage({ field, sessionKey, initialValue }) ); @@ -55,7 +56,7 @@ describe('useMarkdownSessionStorage', () => { }); it('should return hasConflicts as false when sessionKey is empty', async () => { - const { result, waitFor } = renderHook(() => + const { result } = renderHook(() => useMarkdownSessionStorage({ field, sessionKey: '', initialValue }) ); @@ -66,7 +67,7 @@ describe('useMarkdownSessionStorage', () => { }); it('should update the session value with field value when it is first render', async () => { - const { waitFor } = renderHook( + renderHook<{ hasConflicts: boolean }, SessionStorageType>( (props) => { return useMarkdownSessionStorage(props); }, @@ -86,7 +87,7 @@ describe('useMarkdownSessionStorage', () => { it('should set session storage when field has value and session key is not created yet', async () => { const specialCharsValue = '!{tooltip[Hello again](This is tooltip!)}'; - const { waitFor, result } = renderHook( + const { result } = renderHook<{ hasConflicts: boolean }, SessionStorageType>( (props) => { return useMarkdownSessionStorage(props); }, @@ -110,7 +111,7 @@ describe('useMarkdownSessionStorage', () => { }); it('should update session value ', async () => { - const { result, rerender, waitFor } = renderHook( + const { result, rerender } = renderHook<{ hasConflicts: boolean }, SessionStorageType>( (props) => { return useMarkdownSessionStorage(props); }, @@ -138,7 +139,7 @@ describe('useMarkdownSessionStorage', () => { }); it('should return has conflict true', async () => { - const { result, rerender, waitFor } = renderHook( + const { result, rerender } = renderHook<{ hasConflicts: boolean }, SessionStorageType>( (props) => { return useMarkdownSessionStorage(props); }, @@ -162,7 +163,7 @@ describe('useMarkdownSessionStorage', () => { }); it('should set field value if session already exists and it is a first render', async () => { - const { waitFor, result } = renderHook( + const { result } = renderHook<{ hasConflicts: boolean }, SessionStorageType>( (props) => { return useMarkdownSessionStorage(props); }, @@ -190,10 +191,7 @@ describe('useMarkdownSessionStorage', () => { }); it('should update existing session key if field value changed', async () => { - const { waitFor, rerender, result } = renderHook< - SessionStorageType, - { hasConflicts: boolean } - >( + const { rerender, result } = renderHook<{ hasConflicts: boolean }, SessionStorageType>( (props) => { return useMarkdownSessionStorage(props); }, diff --git a/x-pack/plugins/cases/public/components/user_actions/use_user_actions_pagination.test.tsx b/x-pack/plugins/cases/public/components/user_actions/use_user_actions_pagination.test.tsx index 0d005a8b404fd..5fcb9e7ad5d72 100644 --- a/x-pack/plugins/cases/public/components/user_actions/use_user_actions_pagination.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/use_user_actions_pagination.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useUserActionsPagination } from './use_user_actions_pagination'; import type { UserActivityParams } from '../user_actions_activity_bar/types'; @@ -32,7 +33,7 @@ describe('useUserActionsPagination', () => { }); it('renders expandable option correctly when user actions are more than 10', async () => { - const { result, waitFor } = renderHook(() => + const { result } = renderHook(() => useUserActionsPagination({ userActivityQueryParams, caseId: basicCase.id, @@ -62,7 +63,7 @@ describe('useUserActionsPagination', () => { }); it('renders less than 10 user actions correctly', async () => { - const { result, waitFor } = renderHook(() => + const { result } = renderHook(() => useUserActionsPagination({ userActivityQueryParams, caseId: basicCase.id, @@ -92,7 +93,7 @@ describe('useUserActionsPagination', () => { it('returns loading state correctly', async () => { useInfiniteFindCaseUserActionsMock.mockReturnValue({ isLoading: true }); - const { result, waitFor } = renderHook(() => + const { result } = renderHook(() => useUserActionsPagination({ userActivityQueryParams, caseId: basicCase.id, @@ -124,7 +125,7 @@ describe('useUserActionsPagination', () => { it('returns empty array when data is undefined', async () => { useInfiniteFindCaseUserActionsMock.mockReturnValue({ isLoading: false, data: undefined }); - const { result, waitFor } = renderHook(() => + const { result } = renderHook(() => useUserActionsPagination({ userActivityQueryParams, caseId: basicCase.id, @@ -161,7 +162,7 @@ describe('useUserActionsPagination', () => { }, }); - const { result, waitFor } = renderHook(() => + const { result } = renderHook(() => useUserActionsPagination({ userActivityQueryParams, caseId: basicCase.id, diff --git a/x-pack/plugins/cases/public/containers/configure/use_persist_configuration.test.tsx b/x-pack/plugins/cases/public/containers/configure/use_persist_configuration.test.tsx index 4fab35fd5ce5f..681f27fe48d9f 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_persist_configuration.test.tsx +++ b/x-pack/plugins/cases/public/containers/configure/use_persist_configuration.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { usePersistConfiguration } from './use_persist_configuration'; import * as api from './api'; @@ -55,7 +56,7 @@ describe('usePersistConfiguration', () => { const spyPost = jest.spyOn(api, 'postCaseConfigure'); const spyPatch = jest.spyOn(api, 'patchCaseConfigure'); - const { waitFor, result } = renderHook(() => usePersistConfiguration(), { + const { result } = renderHook(() => usePersistConfiguration(), { wrapper: appMockRender.AppWrapper, }); @@ -80,7 +81,7 @@ describe('usePersistConfiguration', () => { const spyPost = jest.spyOn(api, 'postCaseConfigure'); const spyPatch = jest.spyOn(api, 'patchCaseConfigure'); - const { waitFor, result } = renderHook(() => usePersistConfiguration(), { + const { result } = renderHook(() => usePersistConfiguration(), { wrapper: appMockRender.AppWrapper, }); @@ -104,7 +105,7 @@ describe('usePersistConfiguration', () => { it('calls postCaseConfigure with correct data', async () => { const spyPost = jest.spyOn(api, 'postCaseConfigure'); - const { waitFor, result } = renderHook(() => usePersistConfiguration(), { + const { result } = renderHook(() => usePersistConfiguration(), { wrapper: appMockRender.AppWrapper, }); @@ -133,7 +134,7 @@ describe('usePersistConfiguration', () => { const spyPost = jest.spyOn(api, 'postCaseConfigure'); const spyPatch = jest.spyOn(api, 'patchCaseConfigure'); - const { waitFor, result } = renderHook(() => usePersistConfiguration(), { + const { result } = renderHook(() => usePersistConfiguration(), { wrapper: appMockRender.AppWrapper, }); @@ -157,7 +158,7 @@ describe('usePersistConfiguration', () => { it('calls patchCaseConfigure with correct data', async () => { const spyPatch = jest.spyOn(api, 'patchCaseConfigure'); - const { waitFor, result } = renderHook(() => usePersistConfiguration(), { + const { result } = renderHook(() => usePersistConfiguration(), { wrapper: appMockRender.AppWrapper, }); @@ -184,7 +185,7 @@ describe('usePersistConfiguration', () => { it('invalidates the queries correctly', async () => { const queryClientSpy = jest.spyOn(appMockRender.queryClient, 'invalidateQueries'); - const { waitFor, result } = renderHook(() => usePersistConfiguration(), { + const { result } = renderHook(() => usePersistConfiguration(), { wrapper: appMockRender.AppWrapper, }); @@ -198,7 +199,7 @@ describe('usePersistConfiguration', () => { }); it('shows the success toaster', async () => { - const { waitFor, result } = renderHook(() => usePersistConfiguration(), { + const { result } = renderHook(() => usePersistConfiguration(), { wrapper: appMockRender.AppWrapper, }); @@ -216,7 +217,7 @@ describe('usePersistConfiguration', () => { .spyOn(api, 'postCaseConfigure') .mockRejectedValue(new Error('useCreateAttachments: Test error')); - const { waitFor, result } = renderHook(() => usePersistConfiguration(), { + const { result } = renderHook(() => usePersistConfiguration(), { wrapper: appMockRender.AppWrapper, }); diff --git a/x-pack/plugins/cases/public/containers/use_get_case_connectors.test.tsx b/x-pack/plugins/cases/public/containers/use_get_case_connectors.test.tsx index e73012f83f729..8dc6df0a98d2c 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_connectors.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_connectors.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import * as api from './api'; import type { AppMockRenderer } from '../common/mock'; import { createAppMockRenderer } from '../common/mock'; @@ -30,7 +31,7 @@ describe('useGetCaseConnectors', () => { it('calls getCaseConnectors with correct arguments', async () => { const spyOnGetCases = jest.spyOn(api, 'getCaseConnectors'); - const { waitFor } = renderHook(() => useGetCaseConnectors(caseId), { + renderHook(() => useGetCaseConnectors(caseId), { wrapper: appMockRender.AppWrapper, }); @@ -50,7 +51,7 @@ describe('useGetCaseConnectors', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess, addError }); - const { waitFor } = renderHook(() => useGetCaseConnectors(caseId), { + renderHook(() => useGetCaseConnectors(caseId), { wrapper: appMockRender.AppWrapper, }); diff --git a/x-pack/plugins/cases/public/containers/use_messages_storage.test.tsx b/x-pack/plugins/cases/public/containers/use_messages_storage.test.tsx index 2e0f258b81020..b57952a75c08b 100644 --- a/x-pack/plugins/cases/public/containers/use_messages_storage.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_messages_storage.test.tsx @@ -19,29 +19,29 @@ describe('useMessagesStorage', () => { }); it('should return an empty array when there is no messages', async () => { + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); + const { getMessages } = result.current; await act(async () => { - const { result } = renderHook(() => useMessagesStorage()); - await waitFor(() => null); - const { getMessages } = result.current; expect(getMessages('case')).toEqual([]); }); }); it('should add a message', async () => { + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); + const { getMessages, addMessage } = result.current; await act(async () => { - const { result } = renderHook(() => useMessagesStorage()); - await waitFor(() => null); - const { getMessages, addMessage } = result.current; addMessage('case', 'id-1'); expect(getMessages('case')).toEqual(['id-1']); }); }); it('should add multiple messages', async () => { + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); + const { getMessages, addMessage } = result.current; await act(async () => { - const { result } = renderHook(() => useMessagesStorage()); - await waitFor(() => null); - const { getMessages, addMessage } = result.current; addMessage('case', 'id-1'); addMessage('case', 'id-2'); expect(getMessages('case')).toEqual(['id-1', 'id-2']); @@ -49,10 +49,10 @@ describe('useMessagesStorage', () => { }); it('should remove a message', async () => { + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); + const { getMessages, addMessage, removeMessage } = result.current; await act(async () => { - const { result } = renderHook(() => useMessagesStorage()); - await waitFor(() => null); - const { getMessages, addMessage, removeMessage } = result.current; addMessage('case', 'id-1'); addMessage('case', 'id-2'); removeMessage('case', 'id-2'); @@ -61,10 +61,10 @@ describe('useMessagesStorage', () => { }); it('should return presence of a message', async () => { + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); + const { hasMessage, addMessage, removeMessage } = result.current; await act(async () => { - const { result } = renderHook(() => useMessagesStorage()); - await waitFor(() => null); - const { hasMessage, addMessage, removeMessage } = result.current; addMessage('case', 'id-1'); addMessage('case', 'id-2'); removeMessage('case', 'id-2'); @@ -74,14 +74,14 @@ describe('useMessagesStorage', () => { }); it('should clear all messages', async () => { + const { result } = renderHook(() => useMessagesStorage()); + await waitFor(() => null); + const { getMessages, addMessage, clearAllMessages } = result.current; await act(async () => { - const { result } = renderHook(() => useMessagesStorage()); - await waitFor(() => null); - const { getMessages, addMessage, clearAllMessages } = result.current; addMessage('case', 'id-1'); addMessage('case', 'id-2'); clearAllMessages('case'); - expect(getMessages('case')).toEqual([]); }); + expect(getMessages('case')).toEqual([]); }); }); diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.test.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.test.ts index c26a6af826548..0a307b360ebc6 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.test.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.test.ts @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useToasts, useKibana } from '../../common/lib/kibana'; import { createStartServicesMock } from '../../common/lib/kibana/kibana_react.mock'; import type { AppMockRenderer } from '../../common/mock'; @@ -36,7 +37,7 @@ describe('useGetCurrentUserProfile', () => { it('calls getCurrentUserProfile with correct arguments', async () => { const spyOnGetCurrentUserProfile = jest.spyOn(api, 'getCurrentUserProfile'); - const { waitFor } = renderHook(() => useGetCurrentUserProfile(), { + renderHook(() => useGetCurrentUserProfile(), { wrapper: appMockRender.AppWrapper, }); @@ -59,7 +60,7 @@ describe('useGetCurrentUserProfile', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess, addError }); - const { waitFor } = renderHook(() => useGetCurrentUserProfile(), { + renderHook(() => useGetCurrentUserProfile(), { wrapper: appMockRender.AppWrapper, }); @@ -78,7 +79,7 @@ describe('useGetCurrentUserProfile', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess, addError }); - const { waitFor } = renderHook(() => useGetCurrentUserProfile(), { + renderHook(() => useGetCurrentUserProfile(), { wrapper: appMockRender.AppWrapper, }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/form.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/form.test.tsx index 9283a8fa42c39..92a1850e5c52d 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/form.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/form.test.tsx @@ -5,8 +5,8 @@ * 2.0. */ -import { act } from '@testing-library/react-hooks'; import type { RenderHookResult } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import type { TestRenderer } from '../../../../../../../mock'; import { createFleetTestRendererMock } from '../../../../../../../mock'; @@ -74,8 +74,8 @@ describe('useOnSubmit', () => { Parameters, ReturnType >; - const render = ({ isUpdate } = { isUpdate: false }) => - (renderResult = testRenderer.renderHook(() => + const render = async ({ isUpdate } = { isUpdate: false }) => { + renderResult = testRenderer.renderHook(() => useOnSubmit({ agentCount: 0, packageInfo, @@ -85,7 +85,12 @@ describe('useOnSubmit', () => { queryParamsPolicyId: undefined, hasFleetAddAgentsPrivileges: true, }) - )); + ); + + await waitFor(() => null); + + return renderResult; + }; beforeEach(() => { testRenderer = createFleetTestRendererMock(); @@ -95,10 +100,8 @@ describe('useOnSubmit', () => { }); describe('default API response', () => { - beforeEach(() => { - act(() => { - render(); - }); + beforeEach(async () => { + await render(); }); it('should set new values when package policy changes', () => { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts index 616feb04408ee..22aba1b2f2a66 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts @@ -5,9 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; - -import { waitFor } from '@testing-library/react'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor, act } from '@testing-library/react'; import { createPackagePolicyMock } from '../../../../../../../../common/mocks'; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.test.tsx index b8c46a4688e6b..e63709bae1115 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.test.tsx @@ -284,17 +284,15 @@ describe('When on the package policy create page', () => { let cancelButton: HTMLAnchorElement; beforeEach(async () => { - await act(async () => { - render(); + render(); - cancelLink = renderResult.getByTestId( - 'createPackagePolicy_cancelBackLink' - ) as HTMLAnchorElement; + cancelLink = renderResult.getByTestId( + 'createPackagePolicy_cancelBackLink' + ) as HTMLAnchorElement; - cancelButton = (await renderResult.findByTestId( - 'createPackagePolicyCancelButton' - )) as HTMLAnchorElement; - }); + cancelButton = (await renderResult.findByTestId( + 'createPackagePolicyCancelButton' + )) as HTMLAnchorElement; }); test('should use custom "cancel" URL', () => { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_action_status.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_action_status.test.tsx index 1b4f3e6faff7c..040152d31fffa 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_action_status.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_action_status.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act } from '@testing-library/react'; import { sendGetActionStatus, sendPostCancelAction, useStartServices } from '../../../../hooks'; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_agent_soft_limit.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_agent_soft_limit.test.tsx index 38ab07031086f..d37f81ea79485 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_agent_soft_limit.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_agent_soft_limit.test.tsx @@ -38,8 +38,8 @@ describe('useAgentSoftLimit', () => { total: 5, }, } as any); - const { result, waitFor } = renderer.renderHook(() => useAgentSoftLimit()); - await waitFor(() => null); + const { result } = renderer.renderHook(() => useAgentSoftLimit()); + await renderer.waitFor(() => null); expect(mockedSendGetAgents).toBeCalled(); expect(result.current.shouldDisplayAgentSoftLimit).toEqual(false); @@ -53,8 +53,8 @@ describe('useAgentSoftLimit', () => { total: 15, }, } as any); - const { result, waitFor } = renderer.renderHook(() => useAgentSoftLimit()); - await waitFor(() => null); + const { result } = renderer.renderHook(() => useAgentSoftLimit()); + await renderer.waitFor(() => null); expect(mockedSendGetAgents).toBeCalled(); expect(result.current.shouldDisplayAgentSoftLimit).toEqual(true); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_fetch_agents_data.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_fetch_agents_data.test.tsx index f633602ce0592..6b8ca1702b79b 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_fetch_agents_data.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_fetch_agents_data.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { act } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useStartServices } from '../../../../hooks'; @@ -118,7 +118,7 @@ describe('useFetchAgentsData', () => { it('should fetch agents and agent policies data', async () => { const renderer = createFleetTestRendererMock(); - const { result, waitFor } = renderer.renderHook(() => useFetchAgentsData()); + const { result } = renderer.renderHook(() => useFetchAgentsData()); await waitFor(() => null); expect(result?.current.selectedStatus).toEqual(['healthy', 'unhealthy', 'updating', 'offline']); @@ -153,7 +153,7 @@ describe('useFetchAgentsData', () => { it('sync querystring kuery with current search', async () => { const renderer = createFleetTestRendererMock(); - const { result, waitFor } = renderer.renderHook(() => useFetchAgentsData()); + const { result } = renderer.renderHook(() => useFetchAgentsData()); await waitFor(() => null); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_update_tags.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_update_tags.test.tsx index 89059d5a17971..d7999565f67f1 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_update_tags.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_update_tags.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act } from '@testing-library/react'; import { sendPostBulkAgentTagsUpdate, diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy.test.tsx index 4f9aa30f1ba4f..34af261fde382 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy.test.tsx @@ -46,8 +46,8 @@ describe('useFleetServerUnhealthy', () => { }, }); - const { result, waitFor } = testRenderer.renderHook(() => useFleetServerUnhealthy()); - await waitFor(() => null); + const { result } = testRenderer.renderHook(() => useFleetServerUnhealthy()); + await testRenderer.waitFor(() => null); expect(result.current.isLoading).toBeFalsy(); expect(result.current.isUnhealthy).toBeFalsy(); }); @@ -62,8 +62,8 @@ describe('useFleetServerUnhealthy', () => { }, }, }); - const { result, waitFor } = testRenderer.renderHook(() => useFleetServerUnhealthy()); - await waitFor(() => null); + const { result } = testRenderer.renderHook(() => useFleetServerUnhealthy()); + await testRenderer.waitFor(() => null); expect(result.current.isLoading).toBeFalsy(); expect(result.current.isUnhealthy).toBeTruthy(); }); @@ -73,8 +73,8 @@ describe('useFleetServerUnhealthy', () => { error: new Error('Invalid request'), data: null, }); - const { result, waitFor } = testRenderer.renderHook(() => useFleetServerUnhealthy()); - await waitFor(() => null); + const { result } = testRenderer.renderHook(() => useFleetServerUnhealthy()); + await testRenderer.waitFor(() => null); expect(result.current.isLoading).toBeFalsy(); expect(result.current.isUnhealthy).toBeFalsy(); expect(testRenderer.startServices.notifications.toasts.addError).toBeCalled(); diff --git a/x-pack/plugins/fleet/public/hooks/use_dismissable_tour.test.ts b/x-pack/plugins/fleet/public/hooks/use_dismissable_tour.test.ts index 394699fc3f34f..e6bb79f033c9c 100644 --- a/x-pack/plugins/fleet/public/hooks/use_dismissable_tour.test.ts +++ b/x-pack/plugins/fleet/public/hooks/use_dismissable_tour.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act } from '@testing-library/react'; import { TOUR_STORAGE_KEYS } from '../constants'; import { createStartServices } from '../mock'; diff --git a/x-pack/plugins/fleet/public/mock/create_test_renderer.tsx b/x-pack/plugins/fleet/public/mock/create_test_renderer.tsx index 363bda2968ced..c9d7e9fd56243 100644 --- a/x-pack/plugins/fleet/public/mock/create_test_renderer.tsx +++ b/x-pack/plugins/fleet/public/mock/create_test_renderer.tsx @@ -122,6 +122,7 @@ export const createFleetTestRendererMock = (): TestRenderer => { {children} ); + return renderHook(callback, { wrapper, }); @@ -137,6 +138,7 @@ export const createFleetTestRendererMock = (): TestRenderer => { }); return renderResponse!; }, + waitFor, }; return testRendererMocks; diff --git a/x-pack/plugins/graph/public/helpers/use_workspace_loader.test.tsx b/x-pack/plugins/graph/public/helpers/use_workspace_loader.test.tsx index 22790bc7f639b..5f9891ade53c9 100644 --- a/x-pack/plugins/graph/public/helpers/use_workspace_loader.test.tsx +++ b/x-pack/plugins/graph/public/helpers/use_workspace_loader.test.tsx @@ -10,7 +10,8 @@ import { spacesPluginMock } from '@kbn/spaces-plugin/public/mocks'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { createMockGraphStore } from '../state_management/mocks'; import { Workspace } from '../types'; -import { renderHook, act, RenderHookOptions } from '@testing-library/react-hooks'; +import { renderHook, RenderHookOptions } from '@testing-library/react-hooks'; +import { act } from '@testing-library/react'; import { ContentClient } from '@kbn/content-management-plugin/public'; jest.mock('react-router-dom', () => { diff --git a/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.test.tsx b/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.test.tsx index a2623266712dc..8a9d6ea1ed0fd 100644 --- a/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.test.tsx +++ b/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act } from '@testing-library/react'; import { of, throwError } from 'rxjs'; import { useMlNotifications, MlNotificationsContextProvider } from './ml_notifications_context'; import { useStorage } from '@kbn/ml-local-storage'; 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..6c3ce41ed1472 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 @@ -7,6 +7,7 @@ import * as redux from 'react-redux'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { ScreenshotRefImageData, ScreenshotBlockCache } from '../../../../common/runtime_types'; import { fetchBlocksAction } from '../state'; import { shouldCompose, useComposeImageFromRef } from './use_composite_image'; @@ -179,7 +180,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_monitor_name.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_monitor_name.test.tsx index af7700f549d88..cdf6f5b6071a4 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 @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { fetchMonitorManagementList } from '../state'; import { useMonitorName } from './use_monitor_name'; @@ -54,7 +55,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 +63,7 @@ describe('useMonitorName', () => { nameAlreadyExists: false, }); - await waitForValueToChange(() => result.current.values); + await waitFor(() => result.current.values); expect(result.current).toStrictEqual({ loading: false, @@ -78,11 +79,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 +96,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/triggers_actions_ui/public/application/sections/alerts_table/cases/use_case_view_navigation.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/cases/use_case_view_navigation.test.ts index 904a8cae4eec7..0907ed511c5a3 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/cases/use_case_view_navigation.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/cases/use_case_view_navigation.test.ts @@ -6,7 +6,8 @@ */ import { BehaviorSubject } from 'rxjs'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useKibana } from '../../../../common/lib/kibana'; import { AppMockRenderer, createAppMockRenderer } from '../../test_utils'; import { useCaseViewNavigation } from './use_case_view_navigation'; @@ -26,7 +27,7 @@ describe('useCaseViewNavigation', () => { }); it('calls navigateToApp with correct arguments', () => { - const { result, waitFor } = renderHook(() => useCaseViewNavigation(), { + const { result } = renderHook(() => useCaseViewNavigation(), { wrapper: appMockRender.AppWrapper, }); @@ -43,7 +44,7 @@ describe('useCaseViewNavigation', () => { }); it('calls navigateToApp with correct arguments and bypass current app id', () => { - const { result, waitFor } = renderHook(() => useCaseViewNavigation('superAppId'), { + const { result } = renderHook(() => useCaseViewNavigation('superAppId'), { wrapper: appMockRender.AppWrapper, }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_columns/use_columns.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_columns/use_columns.test.tsx index fb79f87162bcb..c09bfde38d278 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_columns/use_columns.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_columns/use_columns.test.tsx @@ -9,7 +9,8 @@ import React, { FunctionComponent } from 'react'; import { EuiDataGridColumn } from '@elastic/eui'; import { AlertConsumers } from '@kbn/rule-data-utils'; import { Storage } from '@kbn/kibana-utils-plugin/public'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { BrowserFields } from '@kbn/alerting-types'; import { testQueryClientConfig } from '@kbn/alerts-ui-shared/src/common/test_utils/test_query_client_config'; @@ -340,10 +341,7 @@ describe('useColumns', () => { describe('columns', () => { test('should changes the column list when defaultColumns has been updated', async () => { const localStorageAlertsTable = getStorageAlertsTableByDefaultColumns(defaultColumns); - const { result, waitFor } = renderHook< - React.PropsWithChildren, - UseColumnsResp - >( + const { result } = renderHook, UseColumnsResp>( () => useColumns({ defaultColumns, From 1eed435be95acf4c9e650e77f7f6141b1dde29e2 Mon Sep 17 00:00:00 2001 From: Eyo Okon Eyo Date: Tue, 24 Sep 2024 09:50:39 +0100 Subject: [PATCH 03/18] use waitFor and act appropriately to improve test stability --- .../use_fetch_alerts_fields_query.test.tsx | 5 +- ...se_fetch_alerts_index_names_query.test.tsx | 5 +- .../hooks/use_search_alerts_query.test.tsx | 5 +- .../use_virtual_data_view_query.test.tsx | 8 +- .../chart/hooks/use_chart_actions.test.ts | 2 +- .../hooks/use_edit_visualization.test.ts | 16 ++- .../public/chart/hooks/use_lens_props.test.ts | 2 +- .../container/hooks/use_state_props.test.ts | 3 + .../saved_query_management_list.test.tsx | 2 +- .../hooks/persist_exception_item.test.ts | 102 +++++++++--------- .../hooks/use_exception_lists.test.ts | 2 - .../use_latency_correlations.test.tsx | 10 +- .../app/service_map/empty_banner.test.tsx | 9 +- .../app/trace_link/trace_link.test.tsx | 9 +- .../hooks/use_loading_state.test.ts | 11 +- .../hooks/use_request_observable.test.ts | 13 +-- .../hooks/use_metrics_explorer_data.test.tsx | 27 ++--- .../public/hooks/use_fetch_bulk_cases.test.ts | 14 ++- .../use_recently_viewed_monitors.test.tsx | 12 +-- .../use_responder_action_data.test.ts | 27 +++-- .../guided_onboarding_tour/tour.test.tsx | 57 +++++----- .../hooks/use_installed_security_jobs.test.ts | 6 +- .../ml/links/create_explorer_link.test.tsx | 32 +++--- .../hooks/use_security_jobs.test.ts | 4 +- .../use_bulk_get_user_profiles.test.tsx | 4 +- .../use_get_current_user_profile.test.tsx | 3 +- .../user_profiles/use_suggest_users.test.tsx | 3 +- .../containers/query_toggle/index.test.tsx | 23 ++-- .../containers/use_full_screen/index.test.tsx | 95 ++++++++-------- .../use_integrations.test.tsx | 3 +- .../left/hooks/use_fetch_alerts.test.ts | 5 +- .../components/artifact_flyout.test.tsx | 6 +- .../public/management/hooks/test_utils.tsx | 3 +- .../public/hooks/use_integrations.test.tsx | 9 +- .../hooks/use_aggregated_indicators.test.tsx | 7 +- .../indicators/hooks/use_indicators.test.tsx | 9 +- 36 files changed, 272 insertions(+), 281 deletions(-) diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.test.tsx index 3607e75bc868e..37386027c6fa4 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.test.tsx @@ -11,6 +11,7 @@ import React, { FC } from 'react'; import { AlertConsumers } from '@kbn/rule-data-utils'; import * as ReactQuery from '@tanstack/react-query'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { testQueryClientConfig } from '../test_utils/test_query_client_config'; import { useFetchAlertsFieldsQuery } from './use_fetch_alerts_fields_query'; import { httpServiceMock } from '@kbn/core-http-browser-mocks'; @@ -88,14 +89,14 @@ describe('useFetchAlertsFieldsQuery', () => { }); it('should call the api only once', async () => { - const { result, rerender, waitForValueToChange } = renderHook( + const { result, rerender } = renderHook( () => useFetchAlertsFieldsQuery({ http: mockHttpClient, featureIds: ['apm'] }), { wrapper, } ); - await waitForValueToChange(() => result.current.data); + await waitFor(() => result.current.data); expect(mockHttpGet).toHaveBeenCalledTimes(1); expect(result.current.data).toEqual({ diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_index_names_query.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_index_names_query.test.tsx index ab702a2ea09ec..3d378ae7eca7f 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_index_names_query.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_index_names_query.test.tsx @@ -10,6 +10,7 @@ import React, { FunctionComponent } from 'react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { testQueryClientConfig } from '../test_utils/test_query_client_config'; import { useFetchAlertsIndexNamesQuery } from './use_fetch_alerts_index_names_query'; import { fetchAlertsIndexNames } from '../apis/fetch_alerts_index_names'; @@ -56,14 +57,14 @@ describe('useFetchAlertsIndexNamesQuery', () => { }); it('correctly caches the index names', async () => { - const { result, rerender, waitForValueToChange } = renderHook( + const { result, rerender } = renderHook( () => useFetchAlertsIndexNamesQuery({ http: mockHttpClient, featureIds: ['apm'] }), { wrapper, } ); - await waitForValueToChange(() => result.current.data); + await waitFor(() => result.current.data); expect(mockFetchAlertsIndexNames).toHaveBeenCalledTimes(1); diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.test.tsx index 664a525796d42..1442b877766d4 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.test.tsx @@ -13,6 +13,7 @@ import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { IKibanaSearchResponse } from '@kbn/search-types'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import type { UseSearchAlertsQueryParams } from './use_search_alerts_query'; import { AlertsQueryContext } from '../contexts/alerts_query_context'; import { useSearchAlertsQuery } from './use_search_alerts_query'; @@ -126,10 +127,10 @@ describe('useSearchAlertsQuery', () => { }); it('returns the response correctly', async () => { - const { result, waitForValueToChange } = renderHook(() => useSearchAlertsQuery(params), { + const { result } = renderHook(() => useSearchAlertsQuery(params), { wrapper, }); - await waitForValueToChange(() => result.current.data); + await waitFor(() => result.current.data); expect(result.current.data).toEqual( expect.objectContaining({ ...expectedResponse, diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_virtual_data_view_query.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_virtual_data_view_query.test.tsx index 834409a87f52a..ca8b0eebefb1e 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_virtual_data_view_query.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_virtual_data_view_query.test.tsx @@ -10,6 +10,7 @@ import React, { FunctionComponent } from 'react'; import * as ReactQuery from '@tanstack/react-query'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { testQueryClientConfig } from '../test_utils/test_query_client_config'; import { queryKeyPrefix, useVirtualDataViewQuery } from './use_virtual_data_view_query'; import { DataView } from '@kbn/data-views-plugin/common'; @@ -38,10 +39,11 @@ describe('useVirtualDataViewQuery', () => { it('does not create a data view if indexNames is empty or nullish', () => { const { rerender } = renderHook( - ({ indexNames }: React.PropsWithChildren<{ indexNames: string[] }>) => + ({ indexNames }: React.PropsWithChildren<{ indexNames?: string[] }>) => useVirtualDataViewQuery({ dataViewsService: mockDataViewsService, indexNames }), { wrapper, + initialProps: {}, } ); @@ -89,7 +91,7 @@ describe('useVirtualDataViewQuery', () => { }); it('removes the data view from the instance cache on unmount', async () => { - const { result, waitForValueToChange, unmount } = renderHook( + const { result, unmount } = renderHook( () => useVirtualDataViewQuery({ dataViewsService: mockDataViewsService, @@ -100,7 +102,7 @@ describe('useVirtualDataViewQuery', () => { } ); - await waitForValueToChange(() => result.current.data); + await waitFor(() => result.current.data); unmount(); diff --git a/src/plugins/unified_histogram/public/chart/hooks/use_chart_actions.test.ts b/src/plugins/unified_histogram/public/chart/hooks/use_chart_actions.test.ts index ab8acc7b694fe..242a9a8f05f35 100644 --- a/src/plugins/unified_histogram/public/chart/hooks/use_chart_actions.test.ts +++ b/src/plugins/unified_histogram/public/chart/hooks/use_chart_actions.test.ts @@ -8,7 +8,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; -import { act } from 'react-test-renderer'; +import { act } from '@testing-library/react'; import { UnifiedHistogramChartContext } from '../../types'; import { useChartActions } from './use_chart_actions'; diff --git a/src/plugins/unified_histogram/public/chart/hooks/use_edit_visualization.test.ts b/src/plugins/unified_histogram/public/chart/hooks/use_edit_visualization.test.ts index e64b41e40e547..5886e1469a4cf 100644 --- a/src/plugins/unified_histogram/public/chart/hooks/use_edit_visualization.test.ts +++ b/src/plugins/unified_histogram/public/chart/hooks/use_edit_visualization.test.ts @@ -10,8 +10,7 @@ import type { DataView } from '@kbn/data-views-plugin/common'; import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; import { renderHook } from '@testing-library/react-hooks'; -import { act } from 'react-test-renderer'; -import { setTimeout } from 'timers/promises'; +import { waitFor } from '@testing-library/react'; import { dataViewMock } from '../../__mocks__/data_view'; import { dataViewWithTimefieldMock } from '../../__mocks__/data_view_with_timefield'; import { unifiedHistogramServicesMock } from '../../__mocks__/services'; @@ -44,8 +43,7 @@ describe('useEditVisualization', () => { lensAttributes, }) ); - await act(() => setTimeout(0)); - expect(hook.result.current).toBeDefined(); + await waitFor(() => expect(hook.result.current).toBeDefined()); hook.result.current!(); expect(navigateToPrefilledEditor).toHaveBeenCalledWith({ id: '', @@ -64,7 +62,7 @@ describe('useEditVisualization', () => { lensAttributes: {} as unknown as TypedLensByValueInput['attributes'], }) ); - await act(() => setTimeout(0)); + await waitFor(() => null); expect(hook.result.current).toBeUndefined(); }); @@ -78,7 +76,7 @@ describe('useEditVisualization', () => { lensAttributes: {} as unknown as TypedLensByValueInput['attributes'], }) ); - await act(() => setTimeout(0)); + await waitFor(() => null); expect(hook.result.current).toBeUndefined(); }); @@ -93,7 +91,7 @@ describe('useEditVisualization', () => { isPlainRecord: true, }) ); - await act(() => setTimeout(0)); + await waitFor(() => null); expect(hook.result.current).toBeUndefined(); }); @@ -113,7 +111,7 @@ describe('useEditVisualization', () => { lensAttributes: {} as unknown as TypedLensByValueInput['attributes'], }) ); - await act(() => setTimeout(0)); + await waitFor(() => null); expect(hook.result.current).toBeUndefined(); }); @@ -127,7 +125,7 @@ describe('useEditVisualization', () => { lensAttributes: {} as unknown as TypedLensByValueInput['attributes'], }) ); - await act(() => setTimeout(0)); + await waitFor(() => null); expect(hook.result.current).toBeUndefined(); }); }); diff --git a/src/plugins/unified_histogram/public/chart/hooks/use_lens_props.test.ts b/src/plugins/unified_histogram/public/chart/hooks/use_lens_props.test.ts index 9d1522398b018..9a512c862be92 100644 --- a/src/plugins/unified_histogram/public/chart/hooks/use_lens_props.test.ts +++ b/src/plugins/unified_histogram/public/chart/hooks/use_lens_props.test.ts @@ -8,7 +8,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; -import { act } from 'react-test-renderer'; +import { act } from '@testing-library/react'; import { Subject } from 'rxjs'; import type { UnifiedHistogramInputMessage } from '../../types'; import { dataViewWithTimefieldMock } from '../../__mocks__/data_view_with_timefield'; diff --git a/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts b/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts index 44a36be34d1ab..b4c97669031e3 100644 --- a/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts +++ b/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts @@ -503,6 +503,9 @@ describe('useStateProps', () => { columns: undefined, }) ); + + await waitFor(() => null); + const { onTopPanelHeightChange, onTimeIntervalChange, diff --git a/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.test.tsx b/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.test.tsx index ae51b96522c27..0abc6587b8726 100644 --- a/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.test.tsx +++ b/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.test.tsx @@ -155,7 +155,7 @@ describe('Saved query management list component', () => { it('should render the saved queries on the selectable component', async () => { render(wrapSavedQueriesListComponentInContext(props)); - expect(await screen.findAllByRole('option')).toHaveLength(1); + await waitFor(() => expect(screen.queryAllByRole('option')).toHaveLength(1)); expect(screen.getByRole('option', { name: 'Test' })).toBeInTheDocument(); }); diff --git a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts b/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts index 9a7cc24910802..bb929609f8d95 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts +++ b/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts @@ -46,98 +46,96 @@ describe('usePersistExceptionItem', () => { }); test('"isLoading" is "true" when exception item is being saved', async () => { - await act(async () => { - const { result, rerender } = renderHook(() => - usePersistExceptionItem({ http: mockKibanaHttpService, onError }) - ); + const { result, rerender } = renderHook(() => + usePersistExceptionItem({ http: mockKibanaHttpService, onError }) + ); - await waitFor(() => null); + await act(async () => { result.current[1](getCreateExceptionListItemSchemaMock()); rerender(); - - expect(result.current).toEqual([{ isLoading: true, isSaved: false }, result.current[1]]); }); + + expect(result.current).toEqual([{ isLoading: true, isSaved: false }, result.current[1]]); }); test('"isSaved" is "true" when exception item saved successfully', async () => { - await act(async () => { - const { result } = renderHook(() => - usePersistExceptionItem({ http: mockKibanaHttpService, onError }) - ); + const { result } = renderHook(() => + usePersistExceptionItem({ http: mockKibanaHttpService, onError }) + ); - await waitFor(() => null); + await act(async () => { result.current[1](getCreateExceptionListItemSchemaMock()); - await waitFor(() => null); - - expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); }); + + expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); }); test('it invokes "updateExceptionListItem" when payload has "id"', async () => { const addExceptionListItem = jest.spyOn(api, 'addExceptionListItem'); const updateExceptionListItem = jest.spyOn(api, 'updateExceptionListItem'); - await act(async () => { - const { result } = renderHook(() => - usePersistExceptionItem({ http: mockKibanaHttpService, onError }) - ); + const { result } = renderHook(() => + usePersistExceptionItem({ http: mockKibanaHttpService, onError }) + ); + + await waitFor(() => null); - await waitFor(() => null); + await act(async () => { // NOTE: Take note here passing in an exception item where it's // entries have been enriched with ids to ensure that they get stripped // before the call goes through result.current[1]({ ...getUpdateExceptionListItemSchemaMock(), entries: ENTRIES_WITH_IDS }); - await waitFor(() => null); - - expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); - expect(addExceptionListItem).not.toHaveBeenCalled(); - expect(updateExceptionListItem).toHaveBeenCalledWith({ - http: mockKibanaHttpService, - listItem: getUpdateExceptionListItemSchemaMock(), - signal: new AbortController().signal, - }); + }); + + await waitFor(() => null); + + expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); + expect(addExceptionListItem).not.toHaveBeenCalled(); + expect(updateExceptionListItem).toHaveBeenCalledWith({ + http: mockKibanaHttpService, + listItem: getUpdateExceptionListItemSchemaMock(), + signal: new AbortController().signal, }); }); test('it invokes "addExceptionListItem" when payload does not have "id"', async () => { const updateExceptionListItem = jest.spyOn(api, 'updateExceptionListItem'); const addExceptionListItem = jest.spyOn(api, 'addExceptionListItem'); - await act(async () => { - const { result } = renderHook(() => - usePersistExceptionItem({ http: mockKibanaHttpService, onError }) - ); + const { result } = renderHook(() => + usePersistExceptionItem({ http: mockKibanaHttpService, onError }) + ); - await waitFor(() => null); + await waitFor(() => null); + await act(async () => { // NOTE: Take note here passing in an exception item where it's // entries have been enriched with ids to ensure that they get stripped // before the call goes through result.current[1]({ ...getCreateExceptionListItemSchemaMock(), entries: ENTRIES_WITH_IDS }); - await waitFor(() => null); - - expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); - expect(updateExceptionListItem).not.toHaveBeenCalled(); - expect(addExceptionListItem).toHaveBeenCalledWith({ - http: mockKibanaHttpService, - listItem: getCreateExceptionListItemSchemaMock(), - signal: new AbortController().signal, - }); + }); + await waitFor(() => null); + + expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); + expect(updateExceptionListItem).not.toHaveBeenCalled(); + expect(addExceptionListItem).toHaveBeenCalledWith({ + http: mockKibanaHttpService, + listItem: getCreateExceptionListItemSchemaMock(), + signal: new AbortController().signal, }); }); test('"onError" callback is invoked and "isSaved" is "false" when api call fails', async () => { const error = new Error('persist rule failed'); jest.spyOn(api, 'addExceptionListItem').mockRejectedValue(error); + const { result } = renderHook(() => + usePersistExceptionItem({ http: mockKibanaHttpService, onError }) + ); + await waitFor(() => null); await act(async () => { - const { result } = renderHook(() => - usePersistExceptionItem({ http: mockKibanaHttpService, onError }) - ); - - await waitFor(() => null); result.current[1](getCreateExceptionListItemSchemaMock()); - await waitFor(() => null); - - expect(result.current).toEqual([{ isLoading: false, isSaved: false }, result.current[1]]); - expect(onError).toHaveBeenCalledWith(error); }); + await waitFor(() => null); + + expect(result.current).toEqual([{ isLoading: false, isSaved: false }, result.current[1]]); + expect(onError).toHaveBeenCalledWith(error); }); }); diff --git a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_lists.test.ts b/x-pack/plugins/lists/public/exceptions/hooks/use_exception_lists.test.ts index 281504856ef91..672424b7d8cb6 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_lists.test.ts +++ b/x-pack/plugins/lists/public/exceptions/hooks/use_exception_lists.test.ts @@ -48,8 +48,6 @@ describe('useExceptionLists', () => { }) ); - await waitFor(() => null); - expect(result.current).toEqual([ true, [], diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/correlations/use_latency_correlations.test.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/correlations/use_latency_correlations.test.tsx index 70446d1d2b1fd..616f92466fb44 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/correlations/use_latency_correlations.test.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/correlations/use_latency_correlations.test.tsx @@ -8,7 +8,9 @@ import React, { ReactNode } from 'react'; import { merge } from 'lodash'; import { createMemoryHistory } from 'history'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { act } from '@testing-library/react-hooks'; + +import { act, waitFor } from '@testing-library/react'; import { ApmPluginContextValue } from '../../../context/apm_plugin/apm_plugin_context'; import { @@ -131,7 +133,7 @@ describe('useLatencyCorrelations', () => { }); it('should receive partial updates and finish running', async () => { - const { result, unmount, waitFor } = renderHook(() => useLatencyCorrelations(), { + const { result, unmount } = renderHook(() => useLatencyCorrelations(), { wrapper, }); @@ -253,7 +255,7 @@ describe('useLatencyCorrelations', () => { }); it('should stop and return an error after more than 100ms', async () => { - const { result, unmount, waitFor } = renderHook(() => useLatencyCorrelations(), { + const { result, unmount } = renderHook(() => useLatencyCorrelations(), { wrapper, initialProps: { error: true, @@ -277,7 +279,7 @@ describe('useLatencyCorrelations', () => { describe('when canceled', () => { it('should stop running', async () => { - const { result, unmount, waitFor } = renderHook(() => useLatencyCorrelations(), { + const { result, unmount } = renderHook(() => useLatencyCorrelations(), { wrapper, }); diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_map/empty_banner.test.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_map/empty_banner.test.tsx index 20149d0f40795..168180e89c97e 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/service_map/empty_banner.test.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_map/empty_banner.test.tsx @@ -58,11 +58,12 @@ describe('EmptyBanner', () => { it('does not render null', async () => { const component = renderWithTheme(, { wrapper }); - await act(async () => { + act(() => { cy.add({ data: { id: 'test id' } }); - await waitFor(() => { - expect(component.container.children.length).toBeGreaterThan(0); - }); + }); + + await waitFor(() => { + expect(component.container.children.length).toBeGreaterThan(0); }); }); }); diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/trace_link/trace_link.test.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/trace_link/trace_link.test.tsx index 3250702b0cb80..06f7101520bab 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/trace_link/trace_link.test.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/trace_link/trace_link.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { act, render, waitFor } from '@testing-library/react'; +import { render, waitFor } from '@testing-library/react'; import { shallow } from 'enzyme'; import React, { ReactNode } from 'react'; import { MemoryRouter } from 'react-router-dom'; @@ -67,12 +67,9 @@ describe('TraceLink', () => { }, }); - let result; - act(() => { - const component = render(, renderOptions); + const component = render(, renderOptions); - result = component.getByText('Fetching trace...'); - }); + const result = component.getByText('Fetching trace...'); await waitFor(() => {}); expect(result).toBeDefined(); }); diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_loading_state.test.ts b/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_loading_state.test.ts index becd0e81c0a9a..cf01a7779cdcc 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_loading_state.test.ts +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_loading_state.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useLoadingState } from './use_loading_state'; import { useDatePickerContext, type UseDateRangeProviderProps } from './use_date_picker'; import { BehaviorSubject, EMPTY, of, Subject, Subscription, skip } from 'rxjs'; @@ -102,7 +103,7 @@ describe('useLoadingState', () => { }); it('should set isAutoRefreshRequestPending to true when there are requests pending', async () => { - const { result, unmount, waitFor } = renderHook(() => useLoadingState()); + const { result, unmount } = renderHook(() => useLoadingState()); let receivedValue = false; subscription.add( @@ -128,7 +129,7 @@ describe('useLoadingState', () => { }); it('should set isAutoRefreshRequestPending to false when all requests complete', async () => { - const { result, unmount, waitFor } = renderHook(() => useLoadingState()); + const { result, unmount } = renderHook(() => useLoadingState()); let receivedValue = true; subscription.add( @@ -153,7 +154,7 @@ describe('useLoadingState', () => { }); it('should not call updateSearchSessionId if waitUntilNextSessionCompletesMock$ returns empty', async () => { - const { unmount, waitFor } = renderHook(() => useLoadingState()); + const { unmount } = renderHook(() => useLoadingState()); // waitUntilNextSessionCompletes$ returns EMPTY when the status is loading or none sessionState$.next(SearchSessionState.Loading); @@ -171,7 +172,7 @@ describe('useLoadingState', () => { }); it('should call updateSearchSessionId when waitUntilNextSessionCompletesMock$ returns', async () => { - const { unmount, waitFor } = renderHook(() => useLoadingState()); + const { unmount } = renderHook(() => useLoadingState()); // waitUntilNextSessionCompletes$ returns something when the status is Completed or BackgroundCompleted sessionState$.next(SearchSessionState.Loading); diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_request_observable.test.ts b/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_request_observable.test.ts index 9ca4bd17ca34b..889e00726c166 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_request_observable.test.ts +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_request_observable.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useRequestObservable } from './use_request_observable'; import { type RequestState, useLoadingStateContext } from './use_loading_state'; import { useDatePickerContext, type UseDateRangeProviderProps } from './use_date_picker'; @@ -69,7 +70,7 @@ describe('useRequestObservable', () => { }); it('should process a valid request function', async () => { - const { result, waitFor, unmount } = renderHook(() => useRequestObservable()); + const { result, unmount } = renderHook(() => useRequestObservable()); act(() => { result.current.request$.next(() => Promise.resolve()); @@ -85,7 +86,7 @@ describe('useRequestObservable', () => { }); it('should be able to make new requests if isAutoRefreshRequestPending is false', async () => { - const { result, waitFor, unmount } = renderHook(() => useRequestObservable()); + const { result, unmount } = renderHook(() => useRequestObservable()); act(() => { isAutoRefreshRequestPendingMock$.next(false); @@ -102,7 +103,7 @@ describe('useRequestObservable', () => { }); it('should block new requests when isAutoRefreshRequestPending is true', async () => { - const { result, waitFor, unmount } = renderHook(() => useRequestObservable()); + const { result, unmount } = renderHook(() => useRequestObservable()); act(() => { isAutoRefreshRequestPendingMock$.next(false); @@ -123,7 +124,7 @@ describe('useRequestObservable', () => { }); it('should not block new requests when auto-refresh is paused', async () => { - const { result, waitFor, unmount } = renderHook(() => useRequestObservable()); + const { result, unmount } = renderHook(() => useRequestObservable()); act(() => { autoRefreshConfig$.next({ isPaused: true, interval: 5000 }); @@ -144,7 +145,7 @@ describe('useRequestObservable', () => { }); it('should complete the request when an error is thrown', async () => { - const { result, waitFor, unmount } = renderHook(() => useRequestObservable()); + const { result, unmount } = renderHook(() => useRequestObservable()); act(() => { autoRefreshConfig$.next({ isPaused: true, interval: 5000 }); diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.test.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.test.tsx index b14efc3f1bdb1..2bc0d30af7a3a 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.test.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.test.tsx @@ -114,10 +114,9 @@ describe('useMetricsExplorerData Hook', () => { expect(result.current.data).toBeUndefined(); expect(result.current.isLoading).toBe(true); - await waitFor(() => null); + await waitFor(() => expect(result.current.isLoading).toBe(false)); expect(result.current.data!.pages[0]).toEqual(resp); - expect(result.current.isLoading).toBe(false); const { series } = result.current.data!.pages[0]; expect(series).toBeDefined(); expect(series.length).toBe(3); @@ -128,9 +127,8 @@ describe('useMetricsExplorerData Hook', () => { const { result } = renderUseMetricsExplorerDataHook(); expect(result.current.data).toBeUndefined(); expect(result.current.isLoading).toBe(true); - await waitFor(() => null); + await waitFor(() => expect(result.current.isLoading).toBe(false)); expect(result.current.data!.pages[0]).toEqual(resp); - expect(result.current.isLoading).toBe(false); const { series } = result.current.data!.pages[0]; expect(series).toBeDefined(); expect(series.length).toBe(3); @@ -141,8 +139,7 @@ describe('useMetricsExplorerData Hook', () => { act(() => { result.current.fetchNextPage(); }); - await waitFor(() => null); - expect(result.current.isLoading).toBe(false); + await waitFor(() => expect(result.current.isLoading).toBe(false)); const { series: nextSeries } = result.current.data!.pages[1]; expect(nextSeries).toBeDefined(); expect(nextSeries.length).toBe(3); @@ -155,17 +152,15 @@ describe('useMetricsExplorerData Hook', () => { expect(result.current.data).toBeUndefined(); expect(result.current.error).toEqual(null); expect(result.current.isLoading).toBe(true); - await waitFor(() => null); + await waitFor(() => expect(result.current.isLoading).toBe(false)); expect(result.current.data).toBeUndefined(); expect(result.current.error).toEqual(error); - expect(result.current.isLoading).toBe(false); mockedFetch.mockResolvedValue(resp as any); act(() => { result.current.refetch(); }); - await waitFor(() => null); + await waitFor(() => expect(result.current.isLoading).toBe(false)); expect(result.current.data!.pages[0]).toEqual(resp); - expect(result.current.isLoading).toBe(false); expect(result.current.error).toBe(null); }); @@ -174,9 +169,8 @@ describe('useMetricsExplorerData Hook', () => { const { result, rerender } = renderUseMetricsExplorerDataHook(); expect(result.current.data).toBeUndefined(); expect(result.current.isLoading).toBe(true); - await waitFor(() => null); + await waitFor(() => expect(result.current.isLoading).toBe(false)); expect(result.current.data!.pages[0]).toEqual(resp); - expect(result.current.isLoading).toBe(false); const { series } = result.current.data!.pages[0]; expect(series).toBeDefined(); expect(series.length).toBe(3); @@ -192,9 +186,8 @@ describe('useMetricsExplorerData Hook', () => { timestamps, }); expect(result.current.isLoading).toBe(true); - await waitFor(() => null); + await waitFor(() => expect(result.current.isLoading).toBe(false)); expect(result.current.data!.pages[0]).toEqual(resp); - expect(result.current.isLoading).toBe(false); }); it('should not paginate on time change', async () => { @@ -202,9 +195,8 @@ describe('useMetricsExplorerData Hook', () => { const { result, rerender } = renderUseMetricsExplorerDataHook(); expect(result.current.data).toBeUndefined(); expect(result.current.isLoading).toBe(true); - await waitFor(() => null); + await waitFor(() => expect(result.current.isLoading).toBe(false)); expect(result.current.data!.pages[0]).toEqual(resp); - expect(result.current.isLoading).toBe(false); const { series } = result.current.data!.pages[0]; expect(series).toBeDefined(); expect(series.length).toBe(3); @@ -216,8 +208,7 @@ describe('useMetricsExplorerData Hook', () => { timestamps: { fromTimestamp: 1678378092225, toTimestamp: 1678381693477, interval: '>=10s' }, }); expect(result.current.isLoading).toBe(true); - await waitFor(() => null); + await waitFor(() => expect(result.current.isLoading).toBe(false)); expect(result.current.data!.pages[0]).toEqual(resp); - expect(result.current.isLoading).toBe(false); }); }); 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 a4cac9612daa7..a327abdb2e074 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 @@ -7,7 +7,7 @@ import { useFetchBulkCases } from './use_fetch_bulk_cases'; import { renderHook } from '@testing-library/react-hooks'; -import { act, waitFor } from '@testing-library/react'; +import { waitFor } from '@testing-library/react'; import { kibanaStartMock } from '../utils/kibana_react.mock'; const mockUseKibanaReturnValue = kibanaStartMock.startContract(); @@ -19,14 +19,12 @@ 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 } = renderHook(() => useFetchBulkCases({ ids: [] })); + const { result } = renderHook(() => useFetchBulkCases({ ids: [] })); - await waitFor(() => null); + await waitFor(() => null); - expect(result.current.cases).toEqual([]); - expect(result.current.error).toEqual(undefined); - expect(result.current.isLoading).toEqual(false); - }); + 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/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..e37c4051274b4 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 @@ -7,6 +7,7 @@ import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import type { FETCH_STATUS } from '@kbn/observability-shared-plugin/public'; import { useFetcher } from '@kbn/observability-shared-plugin/public'; @@ -94,13 +95,10 @@ describe('useRecentlyViewedMonitors', () => { ); }; - 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/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_data.test.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_data.test.ts index 3b68c0efdf9e6..aef471f814210 100644 --- a/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_data.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_data.test.ts @@ -25,7 +25,8 @@ import type { AppContextTestRender } from '../../../../mock/endpoint'; import { createAppRootMockRenderer, endpointAlertDataMock } from '../../../../mock/endpoint'; import { HOST_METADATA_LIST_ROUTE } from '../../../../../../common/endpoint/constants'; import { endpointMetadataHttpMocks } from '../../../../../management/pages/endpoint_hosts/mocks'; -import type { RenderHookResult } from '@testing-library/react-hooks/src/types'; +import type { RenderHookResult } from '@testing-library/react-hooks'; +import { waitFor, act } from '@testing-library/react'; import { createHttpFetchError } from '@kbn/core-http-browser-mocks'; import { HostStatus } from '../../../../../../common/endpoint/types'; import { @@ -169,8 +170,8 @@ describe('use responder action data hooks', () => { }); it('should show action enabled if host metadata was retrieved and host is enrolled', async () => { - const { result, waitForValueToChange } = renderHook(); - await waitForValueToChange(() => result.current.isDisabled); + const { result } = renderHook(); + await waitFor(() => expect(result.current.isDisabled).toBe(true)); expect(result.current).toEqual(getExpectedResponderActionData()); }); @@ -181,8 +182,9 @@ describe('use responder action data hooks', () => { statusCode: 404, }); }); - const { result, waitForValueToChange } = renderHook(); - await waitForValueToChange(() => result.current.tooltip); + const { result } = renderHook(); + + await waitFor(() => null); expect(result.current).toEqual( getExpectedResponderActionData({ @@ -266,9 +268,13 @@ describe('use responder action data hooks', () => { }); it('should call `onClick` prop when action is enabled', async () => { - const { result, waitForValueToChange } = renderHook(); - await waitForValueToChange(() => result.current.isDisabled); - result.current.handleResponseActionsClick(); + const { result } = renderHook(); + + await waitFor(() => expect(result.current.isDisabled).toBe(false)); + + act(() => { + result.current.handleResponseActionsClick(); + }); expect(onClickMock).toHaveBeenCalled(); }); @@ -276,7 +282,10 @@ describe('use responder action data hooks', () => { it('should not call `onCLick` prop when action is disabled', () => { hookProps.agentType = 'sentinel_one'; const { result } = renderHook(); - result.current.handleResponseActionsClick(); + + act(() => { + result.current.handleResponseActionsClick(); + }); expect(onClickMock).not.toHaveBeenCalled(); }); diff --git a/x-pack/plugins/security_solution/public/common/components/guided_onboarding_tour/tour.test.tsx b/x-pack/plugins/security_solution/public/common/components/guided_onboarding_tour/tour.test.tsx index c9e7c667ddd73..3f77d96dc4bfe 100644 --- a/x-pack/plugins/security_solution/public/common/components/guided_onboarding_tour/tour.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/guided_onboarding_tour/tour.test.tsx @@ -67,14 +67,14 @@ describe('useTourContext', () => { expect(result.current.isTourShown(tourId)).toBe(true); }); it('endTourStep calls completeGuideStep with correct tourId', async () => { - await act(async () => { - const { result } = renderHook(() => useTourContext(), { - wrapper: TourContextProvider, - }); - await waitFor(() => null); + const { result } = renderHook(() => useTourContext(), { + wrapper: TourContextProvider, + }); + await waitFor(() => null); + act(() => { result.current.endTourStep(tourId); - expect(mockCompleteGuideStep).toHaveBeenCalledWith(siemGuideId, tourId); }); + expect(mockCompleteGuideStep).toHaveBeenCalledWith(siemGuideId, tourId); }); it('activeStep is initially 1', () => { const { result } = renderHook(() => useTourContext(), { @@ -83,43 +83,46 @@ describe('useTourContext', () => { expect(result.current.activeStep).toBe(1); }); it('incrementStep properly increments for each tourId, and if attempted to increment beyond length of tour config steps resets activeStep to 1', async () => { - await act(async () => { - const { result } = renderHook(() => useTourContext(), { - wrapper: TourContextProvider, - }); - await waitFor(() => null); - const stepCount = securityTourConfig[tourId].length; + const { result } = renderHook(() => useTourContext(), { + wrapper: TourContextProvider, + }); + await waitFor(() => null); + const stepCount = securityTourConfig[tourId].length; + act(() => { for (let i = 0; i < stepCount - 1; i++) { result.current.incrementStep(tourId); } - const lastStep = stepCount ? stepCount : 1; - expect(result.current.activeStep).toBe(lastStep); + }); + const lastStep = stepCount ? stepCount : 1; + expect(result.current.activeStep).toBe(lastStep); + act(() => { result.current.incrementStep(tourId); - expect(result.current.activeStep).toBe(1); }); + expect(result.current.activeStep).toBe(1); }); it('setStep sets activeStep to step number argument', async () => { - await act(async () => { - const { result } = renderHook(() => useTourContext(), { - wrapper: TourContextProvider, - }); - await waitFor(() => null); + const { result } = renderHook(() => useTourContext(), { + wrapper: TourContextProvider, + }); + await waitFor(() => null); + act(() => { result.current.setStep(tourId, 7); - expect(result.current.activeStep).toBe(7); }); + expect(result.current.activeStep).toBe(7); }); it('does not setStep sets activeStep to non-existing step number', async () => { - await act(async () => { - const { result } = renderHook(() => useTourContext(), { - wrapper: TourContextProvider, - }); - await waitFor(() => null); + const { result } = renderHook(() => useTourContext(), { + wrapper: TourContextProvider, + }); + await waitFor(() => null); + + act(() => { // @ts-expect-error testing invalid step result.current.setStep(tourId, 88); - expect(result.current.activeStep).toBe(1); }); + expect(result.current.activeStep).toBe(1); }); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/ml/hooks/use_installed_security_jobs.test.ts b/x-pack/plugins/security_solution/public/common/components/ml/hooks/use_installed_security_jobs.test.ts index 7e0643139158a..52ada32c6c791 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/hooks/use_installed_security_jobs.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/ml/hooks/use_installed_security_jobs.test.ts @@ -43,9 +43,8 @@ describe('useInstalledSecurityJobs', () => { wrapper: TestProviders, }); - await waitFor(() => null); + await waitFor(() => expect(result.current.jobs).toHaveLength(3)); - expect(result.current.jobs).toHaveLength(3); expect(result.current.jobs).toEqual( expect.arrayContaining([ { @@ -76,9 +75,8 @@ describe('useInstalledSecurityJobs', () => { const { result } = renderHook(() => useInstalledSecurityJobs(), { wrapper: TestProviders, }); - await waitFor(() => null); + await waitFor(() => expect(result.current.jobs.length).toBeGreaterThan(0)); - expect(result.current.jobs.length).toBeGreaterThan(0); expect(result.current.jobs.every(isSecurityJob)).toEqual(true); }); diff --git a/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.test.tsx b/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.test.tsx index 28d70edcce46a..32aa97f1aea00 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { render, act } from '@testing-library/react'; +import { render } from '@testing-library/react'; import { mockAnomalies } from '../mock'; import { cloneDeep } from 'lodash/fp'; import { ExplorerLink } from './create_explorer_link'; @@ -27,23 +27,21 @@ describe('create_explorer_link', () => { const ml = { locator }; const http = { basePath: { get: jest.fn(() => {}) } }; - await act(async () => { - const { findByText } = render( - - - - ); + const { findByText } = render( + + + + ); - const url = (await findByText('Open in Anomaly Explorer')).getAttribute('href'); + const url = (await findByText('Open in Anomaly Explorer')).getAttribute('href'); - expect(url).toEqual( - "/app/ml/explorer?_g=(ml:(jobIds:!(job-1)),refreshInterval:(pause:!t,value:0),time:(from:'1970-01-01T00:00:00.000Z',mode:absolute,to:'3000-01-01T00:00:00.000Z'))&_a=(explorer:(mlExplorerFilter:(),mlExplorerSwimlane:()))" - ); - }); + expect(url).toEqual( + "/app/ml/explorer?_g=(ml:(jobIds:!(job-1)),refreshInterval:(pause:!t,value:0),time:(from:'1970-01-01T00:00:00.000Z',mode:absolute,to:'3000-01-01T00:00:00.000Z'))&_a=(explorer:(mlExplorerFilter:(),mlExplorerSwimlane:()))" + ); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_security_jobs.test.ts b/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_security_jobs.test.ts index 5d2f87911b3a6..6244cb7ee9314 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_security_jobs.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_security_jobs.test.ts @@ -75,9 +75,7 @@ describe('useSecurityJobs', () => { const { result } = renderHook(() => useSecurityJobs(), { wrapper: TestProviders, }); - await waitFor(() => null); - - expect(result.current.jobs).toHaveLength(6); + await waitFor(() => expect(result.current.jobs).toHaveLength(6)); expect(result.current.jobs).toEqual(expect.arrayContaining([expectedSecurityJob])); }); diff --git a/x-pack/plugins/security_solution/public/common/components/user_profiles/use_bulk_get_user_profiles.test.tsx b/x-pack/plugins/security_solution/public/common/components/user_profiles/use_bulk_get_user_profiles.test.tsx index eff56069c3724..88cad88800f68 100644 --- a/x-pack/plugins/security_solution/public/common/components/user_profiles/use_bulk_get_user_profiles.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/user_profiles/use_bulk_get_user_profiles.test.tsx @@ -43,10 +43,10 @@ describe('useBulkGetUserProfiles hook', () => { const { result } = renderHook(() => useBulkGetUserProfiles({ uids: assigneesIds }), { wrapper: TestProviders, }); - await waitFor(() => null); + + await waitFor(() => expect(result.current.isLoading).toEqual(false)); expect(spyOnUserProfiles).toHaveBeenCalledTimes(1); - expect(result.current.isLoading).toEqual(false); expect(result.current.data).toEqual(mockUserProfiles); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/user_profiles/use_get_current_user_profile.test.tsx b/x-pack/plugins/security_solution/public/common/components/user_profiles/use_get_current_user_profile.test.tsx index c95bb2643fc60..4c5cb1199a683 100644 --- a/x-pack/plugins/security_solution/public/common/components/user_profiles/use_get_current_user_profile.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/user_profiles/use_get_current_user_profile.test.tsx @@ -42,10 +42,9 @@ describe('useGetCurrentUserProfile hook', () => { const { result } = renderHook(() => useGetCurrentUserProfile(), { wrapper: TestProviders, }); - await waitFor(() => null); + await waitFor(() => expect(result.current.isLoading).toEqual(false)); expect(spyOnUserProfiles).toHaveBeenCalledTimes(1); - expect(result.current.isLoading).toEqual(false); expect(result.current.data).toEqual(mockCurrentUserProfile); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/user_profiles/use_suggest_users.test.tsx b/x-pack/plugins/security_solution/public/common/components/user_profiles/use_suggest_users.test.tsx index fb0ca98052527..42da0ee86dbd0 100644 --- a/x-pack/plugins/security_solution/public/common/components/user_profiles/use_suggest_users.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/user_profiles/use_suggest_users.test.tsx @@ -31,9 +31,8 @@ describe('useSuggestUsers hook', () => { const { result } = renderHook(() => useSuggestUsers({ searchTerm: '' }), { wrapper: TestProviders, }); - await waitFor(() => null); + await waitFor(() => expect(result.current.isLoading).toEqual(false)); expect(spyOnUserProfiles).toHaveBeenCalledTimes(1); - expect(result.current.isLoading).toEqual(false); expect(result.current.data).toEqual(mockUserProfiles); }); }); diff --git a/x-pack/plugins/security_solution/public/common/containers/query_toggle/index.test.tsx b/x-pack/plugins/security_solution/public/common/containers/query_toggle/index.test.tsx index d9cd0c181ba47..92185bcd3f7bc 100644 --- a/x-pack/plugins/security_solution/public/common/containers/query_toggle/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/query_toggle/index.test.tsx @@ -5,8 +5,9 @@ * 2.0. */ -import type { RenderResult, WaitForNextUpdate } from '@testing-library/react-hooks'; -import { renderHook, act, cleanup } from '@testing-library/react-hooks'; +import type { RenderResult } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor, act, cleanup } from '@testing-library/react'; import type { QueryToggle } from '.'; import { useQueryToggle } from '.'; import type { RouteSpyState } from '../../utils/route/types'; @@ -27,7 +28,7 @@ jest.mock('../../utils/route/use_route_spy', () => ({ describe('useQueryToggle', () => { let result: RenderResult; - let waitForNextUpdate: WaitForNextUpdate; + const mockSet = jest.fn(); beforeAll(() => { (useKibana as jest.Mock).mockReturnValue({ @@ -43,11 +44,9 @@ describe('useQueryToggle', () => { jest.clearAllMocks(); }); it('Toggles local storage', async () => { - await act(async () => { - ({ result, waitForNextUpdate } = renderHook(() => useQueryToggle('queryId'))); - await waitForNextUpdate(); - expect(result.current.toggleStatus).toEqual(true); - }); + ({ result } = renderHook(() => useQueryToggle('queryId'))); + await waitFor(() => null); + expect(result.current.toggleStatus).toEqual(true); act(() => { result.current.setToggleStatus(false); }); @@ -56,11 +55,9 @@ describe('useQueryToggle', () => { cleanup(); }); it('null storage key, do not set', async () => { - await act(async () => { - ({ result, waitForNextUpdate } = renderHook(() => useQueryToggle())); - await waitForNextUpdate(); - expect(result.current.toggleStatus).toEqual(true); - }); + ({ result } = renderHook(() => useQueryToggle())); + await waitFor(() => null); + expect(result.current.toggleStatus).toEqual(true); act(() => { result.current.setToggleStatus(false); }); diff --git a/x-pack/plugins/security_solution/public/common/containers/use_full_screen/index.test.tsx b/x-pack/plugins/security_solution/public/common/containers/use_full_screen/index.test.tsx index b4de304a0d9a7..bc5d5661380c1 100644 --- a/x-pack/plugins/security_solution/public/common/containers/use_full_screen/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/use_full_screen/index.test.tsx @@ -7,31 +7,32 @@ import React, { useEffect } from 'react'; import { TestProviders } from '../../mock'; -import type { RenderResult, WaitForNextUpdate } from '@testing-library/react-hooks'; -import { renderHook, act, cleanup } from '@testing-library/react-hooks'; +import type { RenderResult } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor, act, cleanup } from '@testing-library/react'; import type { GlobalFullScreen } from '.'; import { useGlobalFullScreen } from '.'; describe('useFullScreen', () => { describe('with no data-grid present in the dom', () => { let result: RenderResult; - let waitForNextUpdate: WaitForNextUpdate; + test('Default values with no data grid in the dom', async () => { - await act(async () => { - const WrapperContainer: React.FC<{ children?: React.ReactNode }> = ({ children }) => ( -
- {children} -
- ); - ({ result, waitForNextUpdate } = renderHook(() => useGlobalFullScreen(), { - wrapper: WrapperContainer, - })); - await waitForNextUpdate(); - expect(result.current.globalFullScreen).toEqual(false); - }); + const WrapperContainer: RenderOptions['wrapper'] = ({ children }) => ( +
+ {children} +
+ ); + ({ result } = renderHook(() => useGlobalFullScreen(), { + wrapper: WrapperContainer, + })); + await waitFor(() => null); + expect(result.current.globalFullScreen).toEqual(false); + act(() => { result.current.setGlobalFullScreen(true); }); + expect(result.current.globalFullScreen).toEqual(true); cleanup(); }); @@ -39,49 +40,47 @@ describe('useFullScreen', () => { describe('with a mock full screen data-grid in the dom', () => { let result: RenderResult; - let waitForNextUpdate: WaitForNextUpdate; + afterEach(() => { cleanup(); }); test('setting globalFullScreen to true should not remove the chrome removal class and data grid remains open and full screen', async () => { - await act(async () => { - const WrapperContainer: React.FC<{ children?: React.ReactNode }> = ({ children }) => { - useEffect(() => { - document.body.classList.add('euiDataGrid__restrictBody'); - }, []); - return ( -
- {children} -
- ); - }; - ({ result, waitForNextUpdate } = renderHook(() => useGlobalFullScreen(), { - wrapper: WrapperContainer, - })); - await waitForNextUpdate(); - }); + const WrapperContainer: React.FC<{ children?: React.ReactNode }> = ({ children }) => { + useEffect(() => { + document.body.classList.add('euiDataGrid__restrictBody'); + }, []); + return ( +
+ {children} +
+ ); + }; + + ({ result } = renderHook(() => useGlobalFullScreen(), { + wrapper: WrapperContainer, + })); + + await waitFor(() => null); act(() => { result.current.setGlobalFullScreen(true); }); expect(document.querySelector('.euiDataGrid__restrictBody')).toBeTruthy(); }); test('setting globalFullScreen to false should remove the chrome removal class and data grid remains open and full screen', async () => { - await act(async () => { - const WrapperContainer: React.FC<{ children?: React.ReactNode }> = ({ children }) => { - useEffect(() => { - document.body.classList.add('euiDataGrid__restrictBody'); - }, []); - return ( -
- {children} -
- ); - }; - ({ result, waitForNextUpdate } = renderHook(() => useGlobalFullScreen(), { - wrapper: WrapperContainer, - })); - await waitForNextUpdate(); - }); + const WrapperContainer: React.FC<{ children?: React.ReactNode }> = ({ children }) => { + useEffect(() => { + document.body.classList.add('euiDataGrid__restrictBody'); + }, []); + return ( +
+ {children} +
+ ); + }; + ({ result } = renderHook(() => useGlobalFullScreen(), { + wrapper: WrapperContainer, + })); + await waitFor(() => null); act(() => { result.current.setGlobalFullScreen(false); }); diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/related_integrations/use_integrations.test.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/related_integrations/use_integrations.test.tsx index 6da6c4fe0f775..e2852eadeac8c 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/related_integrations/use_integrations.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/related_integrations/use_integrations.test.tsx @@ -64,10 +64,9 @@ describe('useIntegrations', () => { expect(result.current.isError).toEqual(false); // When fetchRuleExecutionEvents returns - await waitFor(() => null); + await waitFor(() => expect(result.current.isLoading).toEqual(false)); // It switches to a success state - expect(result.current.isLoading).toEqual(false); expect(result.current.isSuccess).toEqual(true); expect(result.current.isError).toEqual(false); expect(result.current.data).toEqual([ diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/hooks/use_fetch_alerts.test.ts b/x-pack/plugins/security_solution/public/flyout/document_details/left/hooks/use_fetch_alerts.test.ts index c4910f5daa42a..59bb6a8666065 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/hooks/use_fetch_alerts.test.ts +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/hooks/use_fetch_alerts.test.ts @@ -47,9 +47,8 @@ describe('useFetchAlerts', () => { expect(result.current.loading).toBe(true); - await waitFor(() => !result.current.loading); + await waitFor(() => expect(result.current.loading).toBe(false)); - expect(result.current.loading).toBe(false); expect(result.current.error).toBe(false); expect(result.current.totalItemCount).toBe(10); expect(result.current.data).toEqual(['alert1', 'alert2', 'alert3']); @@ -76,7 +75,7 @@ describe('useFetchAlerts', () => { expect(result.current.loading).toBe(true); - await waitFor(() => !result.current.loading); + await waitFor(() => expect(result.current.loading).toBe(false)); expect(result.current.loading).toBe(false); expect(result.current.error).toBe(true); diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_list_page/components/artifact_flyout.test.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_list_page/components/artifact_flyout.test.tsx index 83b8682190101..66f372b7903b0 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_list_page/components/artifact_flyout.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/artifact_list_page/components/artifact_flyout.test.tsx @@ -47,9 +47,9 @@ describe('When the flyout is opened in the ArtifactListPage component', () => { render = async (props = {}) => { renderResult = renderSetup.renderArtifactListPage(props); - await waitFor(async () => { - expect(renderResult.getByTestId('testPage-flyout')); - }); + await waitFor(async () => + expect(renderResult.getByTestId('testPage-flyout')).toBeInTheDocument() + ); return renderResult; }; diff --git a/x-pack/plugins/security_solution/public/management/hooks/test_utils.tsx b/x-pack/plugins/security_solution/public/management/hooks/test_utils.tsx index 149eee55872aa..4152c7e708ead 100644 --- a/x-pack/plugins/security_solution/public/management/hooks/test_utils.tsx +++ b/x-pack/plugins/security_solution/public/management/hooks/test_utils.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import type { HttpSetup } from '@kbn/core/public'; import type { CreateExceptionListSchema } from '@kbn/securitysolution-io-ts-list-types'; import { coreMock } from '@kbn/core/public/mocks'; @@ -39,7 +40,7 @@ export const renderQuery = async ( const wrapper = ({ children }: { children: React.ReactNode }): JSX.Element => ( {children} ); - const { result: resultHook, waitFor } = renderHook(() => hook(), { + const { result: resultHook } = renderHook(() => hook(), { wrapper, }); await waitFor(() => resultHook.current[waitForHook]); diff --git a/x-pack/plugins/threat_intelligence/public/hooks/use_integrations.test.tsx b/x-pack/plugins/threat_intelligence/public/hooks/use_integrations.test.tsx index 2df9bea337ba5..9bbeb17bd57c5 100644 --- a/x-pack/plugins/threat_intelligence/public/hooks/use_integrations.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/hooks/use_integrations.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query'; import { INSTALLATION_STATUS, THREAT_INTELLIGENCE_CATEGORY } from '../utils/filter_integrations'; @@ -25,9 +26,7 @@ const renderUseQuery = (result: { items: any[] }) => describe('useIntegrations', () => { it('should have undefined data during loading state', async () => { const mockIntegrations = { items: [] }; - const { result, waitFor } = renderUseQuery(mockIntegrations); - - await waitFor(() => result.current.isLoading); + const { result } = renderUseQuery(mockIntegrations); expect(result.current.isLoading).toBeTruthy(); expect(result.current.data).toBeUndefined(); @@ -43,9 +42,9 @@ describe('useIntegrations', () => { }, ], }; - const { result, waitFor } = renderUseQuery(mockIntegrations); + const { result } = renderUseQuery(mockIntegrations); - await waitFor(() => result.current.isSuccess); + await waitFor(() => expect(result.current.isSuccess).toBe(true)); expect(result.current.isLoading).toBeFalsy(); expect(result.current.data).toEqual(mockIntegrations); diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_aggregated_indicators.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_aggregated_indicators.test.tsx index 11e1d03a32b51..cf2cb27d5a9b3 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_aggregated_indicators.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_aggregated_indicators.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useAggregatedIndicators, UseAggregatedIndicatorsParam } from './use_aggregated_indicators'; import { mockedTimefilterService, TestProvidersComponent } from '../../../mocks/test_providers'; import { createFetchAggregatedIndicators } from '../services/fetch_aggregated_indicators'; @@ -47,7 +48,7 @@ describe('useAggregatedIndicators()', () => { it('should create and call the aggregatedIndicatorsQuery correctly', async () => { aggregatedIndicatorsQuery.mockResolvedValue([]); - const { result, rerender, waitFor } = renderUseAggregatedIndicators(); + const { result, rerender } = renderUseAggregatedIndicators(); // indicators service and the query should be called just once expect( @@ -81,7 +82,7 @@ describe('useAggregatedIndicators()', () => { expect.any(AbortSignal) ); - await waitFor(() => !result.current.isLoading); + await waitFor(() => expect(result.current.isLoading).toBe(false)); expect(result.current).toMatchInlineSnapshot(` Object { diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.test.tsx index be710e771b040..300992e0db186 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useIndicators, UseIndicatorsParams, UseIndicatorsValue } from './use_indicators'; import { TestProvidersComponent } from '../../../mocks/test_providers'; import { createFetchIndicators } from '../services/fetch_indicators'; @@ -53,7 +54,7 @@ describe('useIndicators()', () => { expect(indicatorsQuery).toHaveBeenCalledTimes(1); // isLoading should turn to false eventually - await hookResult.waitFor(() => !hookResult.result.current.isLoading); + await waitFor(() => expect(hookResult.result.current.isLoading).toBe(false)); expect(hookResult.result.current.isLoading).toEqual(false); }); }); @@ -77,7 +78,7 @@ describe('useIndicators()', () => { // Change page size await act(async () => hookResult.result.current.onChangeItemsPerPage(50)); - expect(indicatorsQuery).toHaveBeenCalledTimes(3); + await waitFor(() => expect(indicatorsQuery).toHaveBeenCalledTimes(3)); expect(indicatorsQuery).toHaveBeenLastCalledWith( expect.objectContaining({ pagination: expect.objectContaining({ pageIndex: 0, pageSize: 50 }), @@ -101,7 +102,7 @@ describe('useIndicators()', () => { expect.any(AbortSignal) ); - await hookResult.waitFor(() => !hookResult.result.current.isLoading); + await waitFor(() => expect(hookResult.result.current.isLoading).toBe(false)); expect(hookResult.result.current).toMatchInlineSnapshot(` Object { From 9e7e6a1945dfe53011ebbf89f1a9ce6855aa9379 Mon Sep 17 00:00:00 2001 From: Eyo Okon Eyo Date: Tue, 24 Sep 2024 21:29:50 +0100 Subject: [PATCH 04/18] adjust tests to match testing-library changes --- .../src/field/__tests__/use_field.test.ts | 9 +-- .../container/hooks/use_state_props.test.ts | 18 +++++- .../src/hooks/use_alerts_history.test.tsx | 36 ++++------- .../pattern/hooks/use_stats/index.test.tsx | 1 + .../hooks/use_indices_check/index.test.tsx | 23 +++---- .../routes/workpad/hooks/use_workpad.test.tsx | 7 ++- .../actions/delete/use_delete_action.test.tsx | 11 ++-- .../use_push_to_service/index.test.tsx | 5 +- .../public/containers/use_get_cases.test.tsx | 13 ++-- .../apm/public/hooks/use_fetcher.test.tsx | 42 +++++++++---- .../hooks/use_composite_image.test.tsx | 3 +- .../public/hooks/use_delete_endpoint.test.tsx | 5 +- .../use_discover_in_timeline_actions.test.tsx | 34 +++++++++-- .../use_host_isolation_action.test.tsx | 19 +++--- .../use_responder_action_data.test.ts | 25 ++++---- .../mock/endpoint/app_context_render.tsx | 10 +++- .../api/hooks/use_risk_score.test.tsx | 4 +- .../open_timeline/use_timeline_types.test.tsx | 60 +++++++++---------- .../block_list/hooks/use_policies.test.tsx | 9 ++- .../cases/hooks/use_indicator_by_id.test.tsx | 4 +- 20 files changed, 191 insertions(+), 147 deletions(-) diff --git a/packages/kbn-securitysolution-autocomplete/src/field/__tests__/use_field.test.ts b/packages/kbn-securitysolution-autocomplete/src/field/__tests__/use_field.test.ts index ef2c19740617a..3bf9e57c3fab0 100644 --- a/packages/kbn-securitysolution-autocomplete/src/field/__tests__/use_field.test.ts +++ b/packages/kbn-securitysolution-autocomplete/src/field/__tests__/use_field.test.ts @@ -10,10 +10,7 @@ import { DataViewFieldBase } from '@kbn/es-query'; import { ReactElement } from 'react'; import { act } from '@testing-library/react'; - import { renderHook } from '@testing-library/react-hooks'; -import TestRenderer from 'react-test-renderer'; -const { act: actTestRenderer } = TestRenderer; import { fields } from '../../fields/index.mock'; import { useField } from '../use_field'; @@ -480,7 +477,7 @@ describe('useField', () => { useField({ indexPattern, onChange: onChangeMock, isRequired: true }) ); - actTestRenderer(() => { + act(() => { result.current.handleTouch(); }); expect(result.current.isInvalid).toBeTruthy(); @@ -490,7 +487,7 @@ describe('useField', () => { useField({ indexPattern, onChange: onChangeMock, isRequired: true, selectedField }) ); - actTestRenderer(() => { + act(() => { result.current.handleTouch(); }); expect(result.current.isInvalid).toBeFalsy(); @@ -498,7 +495,7 @@ describe('useField', () => { it('should return isInvalid equals false when isRequired is false', () => { const { result } = renderHook(() => useField({ indexPattern, onChange: onChangeMock })); - actTestRenderer(() => { + act(() => { result.current.handleTouch(); }); expect(result.current.isInvalid).toBeFalsy(); diff --git a/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts b/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts index b4c97669031e3..b26223de96e4e 100644 --- a/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts +++ b/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts @@ -10,7 +10,7 @@ import { DataView, DataViewField, DataViewType } from '@kbn/data-views-plugin/common'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; import { renderHook } from '@testing-library/react-hooks'; -import { act } from 'react-test-renderer'; +import { waitFor, act } from '@testing-library/react'; import type { DatatableColumn } from '@kbn/expressions-plugin/common'; import { convertDatatableColumnToDataViewFieldSpec } from '@kbn/data-view-utils'; import { UnifiedHistogramFetchStatus, UnifiedHistogramSuggestionContext } from '../../types'; @@ -491,7 +491,7 @@ describe('useStateProps', () => { `); }); - it('should execute callbacks correctly', () => { + it('should execute callbacks correctly', async () => { const stateService = getStateService({ initialState }); const { result } = renderHook(() => useStateProps({ @@ -504,7 +504,19 @@ describe('useStateProps', () => { }) ); - await waitFor(() => null); + await waitFor(() => + expect(result.current).toEqual( + expect.objectContaining({ + onTopPanelHeightChange: expect.any(Function), + onTimeIntervalChange: expect.any(Function), + onTotalHitsChange: expect.any(Function), + onChartHiddenChange: expect.any(Function), + onChartLoad: expect.any(Function), + onBreakdownFieldChange: expect.any(Function), + onSuggestionContextChange: expect.any(Function), + }) + ) + ); const { onTopPanelHeightChange, 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 82ced89354006..518130eb6364c 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 @@ -8,7 +8,8 @@ import React from 'react'; import { HttpSetup } from '@kbn/core-http-browser'; import { AlertConsumers } from '@kbn/rule-data-utils'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { type UseAlertsHistory, useAlertsHistory, @@ -40,7 +41,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, @@ -52,10 +53,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(); }); @@ -66,7 +64,7 @@ describe('useAlertsHistory', () => { throw new Error('ES error'); }), } as unknown as HttpSetup; - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useAlertsHistory({ http, @@ -78,10 +76,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 +125,7 @@ describe('useAlertsHistory', () => { }, }), } as unknown as HttpSetup; - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useAlertsHistory({ http, @@ -142,9 +137,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); @@ -170,7 +163,7 @@ describe('useAlertsHistory', () => { }), } as unknown as HttpSetup; - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useAlertsHistory({ http, @@ -183,10 +176,7 @@ describe('useAlertsHistory', () => { wrapper, } ); - - await act(async () => { - await waitFor(() => result.current.isSuccess); - }); + await waitFor(() => expect(result.current.isSuccess).toBe(true)); expect(mockedHttpPost).toBeCalledWith('/internal/rac/alerts/find', { body: '{"size":0,"feature_ids":["apm"],"query":{"bool":{"must":[' + @@ -219,7 +209,7 @@ describe('useAlertsHistory', () => { }), } as unknown as HttpSetup; - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useAlertsHistory({ http, @@ -233,9 +223,7 @@ describe('useAlertsHistory', () => { } ); - await act(async () => { - await waitFor(() => result.current.isSuccess); - }); + await waitFor(() => expect(result.current.isSuccess).toBe(true)); expect(mockedHttpPost).toBeCalledWith('/internal/rac/alerts/find', { body: '{"size":0,"feature_ids":["apm"],"query":{"bool":{"must":[' + diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/hooks/use_stats/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/hooks/use_stats/index.test.tsx index f46e07b98cf39..2c1017d196b58 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/hooks/use_stats/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/hooks/use_stats/index.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import React, { FC, PropsWithChildren } from 'react'; import { DataQualityProvider } from '../../../../../data_quality_context'; diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_indices_check/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_indices_check/index.test.tsx index f16803936794d..6b83ddcc3c635 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_indices_check/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/hooks/use_indices_check/index.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useIndicesCheck } from '.'; @@ -82,9 +83,7 @@ describe('useIndicesCheck', () => { describe('when checkIndex completes', () => { it('should set correct data', async () => { - const { result, waitFor } = renderHook(() => - useIndicesCheck({ onCheckCompleted: jest.fn() }) - ); + const { result } = renderHook(() => useIndicesCheck({ onCheckCompleted: jest.fn() })); const httpFetchMock = jest.fn((route) => { if (route.startsWith('/internal/ecs_data_quality_dashboard/mappings')) { @@ -124,9 +123,7 @@ describe('useIndicesCheck', () => { describe('errors', () => { describe('when mappings request errors', () => { it('should set mappingsError', async () => { - const { result, waitFor } = renderHook(() => - useIndicesCheck({ onCheckCompleted: jest.fn() }) - ); + const { result } = renderHook(() => useIndicesCheck({ onCheckCompleted: jest.fn() })); const httpFetchMock = jest.fn((route) => { if (route.startsWith('/internal/ecs_data_quality_dashboard/mappings')) { @@ -160,9 +157,7 @@ describe('useIndicesCheck', () => { describe('when unallowed values request errors', () => { it('should set unallowedValuesError', async () => { - const { result, waitFor } = renderHook(() => - useIndicesCheck({ onCheckCompleted: jest.fn() }) - ); + const { result } = renderHook(() => useIndicesCheck({ onCheckCompleted: jest.fn() })); const httpFetchMock = jest.fn((route) => { if (route.startsWith('/internal/ecs_data_quality_dashboard/mappings')) { @@ -232,9 +227,7 @@ describe('useIndicesCheck', () => { onStart?.(); }); - const { result, waitFor } = renderHook(() => - useIndicesCheck({ onCheckCompleted: jest.fn() }) - ); + const { result } = renderHook(() => useIndicesCheck({ onCheckCompleted: jest.fn() })); act(() => result.current.checkIndex({ @@ -265,9 +258,7 @@ describe('useIndicesCheck', () => { onLoadMappingsStart?.(); }); - const { result, waitFor } = renderHook(() => - useIndicesCheck({ onCheckCompleted: jest.fn() }) - ); + const { result } = renderHook(() => useIndicesCheck({ onCheckCompleted: jest.fn() })); act(() => result.current.checkIndex({ diff --git a/x-pack/plugins/canvas/public/routes/workpad/hooks/use_workpad.test.tsx b/x-pack/plugins/canvas/public/routes/workpad/hooks/use_workpad.test.tsx index 1ba0dacd8c143..e01b6cdfbbfdd 100644 --- a/x-pack/plugins/canvas/public/routes/workpad/hooks/use_workpad.test.tsx +++ b/x-pack/plugins/canvas/public/routes/workpad/hooks/use_workpad.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useWorkpad } from './use_workpad'; import { spacesService } from '../../../services/kibana_services'; @@ -62,7 +63,7 @@ describe('useWorkpad', () => { workpad: workpadResponse, }); - const { waitFor, unmount } = renderHook(() => useWorkpad(workpadId, true, getRedirectPath)); + const { unmount } = renderHook(() => useWorkpad(workpadId, true, getRedirectPath)); try { await waitFor(() => expect(mockDispatch).toHaveBeenCalledTimes(3)); @@ -88,7 +89,7 @@ describe('useWorkpad', () => { aliasId, }); - const { waitFor, unmount } = renderHook(() => useWorkpad(workpadId, true, getRedirectPath)); + const { unmount } = renderHook(() => useWorkpad(workpadId, true, getRedirectPath)); try { await waitFor(() => expect(mockDispatch).toHaveBeenCalledTimes(3)); @@ -118,7 +119,7 @@ describe('useWorkpad', () => { aliasPurpose: 'savedObjectConversion', }); - const { waitFor, unmount } = renderHook(() => useWorkpad(workpadId, true, getRedirectPath)); + const { unmount } = renderHook(() => useWorkpad(workpadId, true, getRedirectPath)); try { await waitFor(() => expect(mockRedirectLegacyUrl).toHaveBeenCalled()); expect(mockRedirectLegacyUrl).toBeCalledWith({ diff --git a/x-pack/plugins/cases/public/components/actions/delete/use_delete_action.test.tsx b/x-pack/plugins/cases/public/components/actions/delete/use_delete_action.test.tsx index 9730783f39af6..e6ed9ebd3383c 100644 --- a/x-pack/plugins/cases/public/components/actions/delete/use_delete_action.test.tsx +++ b/x-pack/plugins/cases/public/components/actions/delete/use_delete_action.test.tsx @@ -7,7 +7,8 @@ import type { AppMockRenderer } from '../../../common/mock'; import { createAppMockRenderer } from '../../../common/mock'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { useDeleteAction } from './use_delete_action'; import * as api from '../../../containers/api'; @@ -84,7 +85,7 @@ describe('useDeleteAction', () => { it('deletes the selected cases', async () => { const deleteSpy = jest.spyOn(api, 'deleteCases'); - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useDeleteAction({ onAction, onActionSuccess, isDisabled: false }), { wrapper: appMockRender.AppWrapper, @@ -112,7 +113,7 @@ describe('useDeleteAction', () => { }); it('closes the modal', async () => { - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useDeleteAction({ onAction, onActionSuccess, isDisabled: false }), { wrapper: appMockRender.AppWrapper, @@ -137,7 +138,7 @@ describe('useDeleteAction', () => { }); it('shows the success toaster correctly when delete one case', async () => { - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useDeleteAction({ onAction, onActionSuccess, isDisabled: false }), { wrapper: appMockRender.AppWrapper, @@ -163,7 +164,7 @@ describe('useDeleteAction', () => { }); it('shows the success toaster correctly when delete multiple case', async () => { - const { result, waitFor } = renderHook( + const { result } = renderHook( () => useDeleteAction({ onAction, onActionSuccess, isDisabled: false }), { wrapper: appMockRender.AppWrapper, diff --git a/x-pack/plugins/cases/public/components/use_push_to_service/index.test.tsx b/x-pack/plugins/cases/public/components/use_push_to_service/index.test.tsx index fccca04bb278f..8110cdb617d74 100644 --- a/x-pack/plugins/cases/public/components/use_push_to_service/index.test.tsx +++ b/x-pack/plugins/cases/public/components/use_push_to_service/index.test.tsx @@ -6,7 +6,8 @@ */ import React from 'react'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import type { ReturnUsePushToService, UsePushToService } from '.'; import { usePushToService } from '.'; @@ -231,7 +232,7 @@ describe('usePushToService', () => { }); it('refresh case view page after push', async () => { - const { result, waitFor } = renderHook< + const { result } = renderHook< React.PropsWithChildren, ReturnUsePushToService >(() => usePushToService(defaultArgs), { diff --git a/x-pack/plugins/cases/public/containers/use_get_cases.test.tsx b/x-pack/plugins/cases/public/containers/use_get_cases.test.tsx index 53900a6920f20..56099c9f1547c 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { DEFAULT_FILTER_OPTIONS, DEFAULT_QUERY_PARAMS } from './constants'; import { useGetCases } from './use_get_cases'; import * as api from './api'; @@ -31,7 +32,7 @@ describe('useGetCases', () => { it('calls getCases with correct arguments', async () => { const spyOnGetCases = jest.spyOn(api, 'getCases'); - const { waitFor } = renderHook(() => useGetCases(), { + renderHook(() => useGetCases(), { wrapper: appMockRender.AppWrapper, }); @@ -55,7 +56,7 @@ describe('useGetCases', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess, addError }); - const { waitFor } = renderHook(() => useGetCases(), { + renderHook(() => useGetCases(), { wrapper: appMockRender.AppWrapper, }); @@ -90,7 +91,7 @@ describe('useGetCases', () => { }; const spyOnGetCases = jest.spyOn(api, 'getCases'); - const { waitFor } = renderHook(() => useGetCases(), { + renderHook(() => useGetCases(), { wrapper: appMockRender.AppWrapper, }); @@ -109,7 +110,7 @@ describe('useGetCases', () => { appMockRender = createAppMockRenderer({ owner: [] }); const spyOnGetCases = jest.spyOn(api, 'getCases'); - const { waitFor } = renderHook(() => useGetCases(), { + renderHook(() => useGetCases(), { wrapper: appMockRender.AppWrapper, }); @@ -128,7 +129,7 @@ describe('useGetCases', () => { appMockRender = createAppMockRenderer({ owner: ['observability'] }); const spyOnGetCases = jest.spyOn(api, 'getCases'); - const { waitFor } = renderHook(() => useGetCases(), { + renderHook(() => useGetCases(), { wrapper: appMockRender.AppWrapper, }); @@ -147,7 +148,7 @@ describe('useGetCases', () => { appMockRender = createAppMockRenderer({ owner: ['observability'] }); const spyOnGetCases = jest.spyOn(api, 'getCases'); - const { waitFor } = renderHook(() => useGetCases({ filterOptions: { owner: ['my-owner'] } }), { + renderHook(() => useGetCases({ filterOptions: { owner: ['my-owner'] } }), { wrapper: appMockRender.AppWrapper, }); diff --git a/x-pack/plugins/observability_solution/apm/public/hooks/use_fetcher.test.tsx b/x-pack/plugins/observability_solution/apm/public/hooks/use_fetcher.test.tsx index 14c58ab3977ee..604d85699b3e3 100644 --- a/x-pack/plugins/observability_solution/apm/public/hooks/use_fetcher.test.tsx +++ b/x-pack/plugins/observability_solution/apm/public/hooks/use_fetcher.test.tsx @@ -5,8 +5,9 @@ * 2.0. */ -import { renderHook, RenderHookResult } from '@testing-library/react-hooks'; +import { renderHook, type RenderHookResult } from '@testing-library/react-hooks'; import React, { ReactNode } from 'react'; +import { waitFor, act } from '@testing-library/react'; import { CoreStart } from '@kbn/core/public'; import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public'; import { delay } from '../utils/test_helpers'; @@ -54,7 +55,9 @@ describe('useFetcher', () => { }); it('should still show loading spinner after 100ms', async () => { - jest.advanceTimersByTime(100); + act(() => { + jest.advanceTimersByTime(100); + }); expect(hook.result.current).toEqual({ data: undefined, @@ -65,8 +68,11 @@ describe('useFetcher', () => { }); it('should show success after 1 second', async () => { - jest.advanceTimersByTime(1000); - await hook.waitForNextUpdate(); + act(() => { + jest.advanceTimersByTime(1000); + }); + + await waitFor(() => null); expect(hook.result.current).toEqual({ data: 'response from hook', @@ -104,7 +110,9 @@ describe('useFetcher', () => { }); it('should still show loading spinner after 100ms', async () => { - jest.advanceTimersByTime(100); + act(() => { + jest.advanceTimersByTime(100); + }); expect(hook.result.current).toEqual({ data: undefined, @@ -115,8 +123,11 @@ describe('useFetcher', () => { }); it('should show error after 1 second', async () => { - jest.advanceTimersByTime(1000); - await hook.waitForNextUpdate(); + act(() => { + jest.advanceTimersByTime(1000); + }); + + await waitFor(() => null); expect(hook.result.current).toEqual({ data: undefined, @@ -149,7 +160,7 @@ describe('useFetcher', () => { status: 'loading', }); - await hook.waitForNextUpdate(); + await waitFor(() => null); // assert: first response has loaded and should be rendered expect(hook.result.current).toEqual({ @@ -168,7 +179,11 @@ describe('useFetcher', () => { args: ['b'], }); - jest.advanceTimersByTime(100); + act(() => { + jest.advanceTimersByTime(100); + }); + + await waitFor(() => null); // assert: while loading new data the previous data should still be rendered expect(hook.result.current).toEqual({ @@ -178,8 +193,11 @@ describe('useFetcher', () => { status: 'loading', }); - jest.advanceTimersByTime(500); - await hook.waitForNextUpdate(); + act(() => { + jest.advanceTimersByTime(500); + }); + + await waitFor(() => null); // assert: "second response" has loaded and should be rendered expect(hook.result.current).toEqual({ @@ -216,7 +234,7 @@ describe('useFetcher', () => { }, args: ['b'], }); - await hook.waitForNextUpdate(); + await waitFor(() => null); const thirdResult = hook.result.current; // assert: rerender with different data returns a new object 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..7d552653de7c9 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 @@ -7,6 +7,7 @@ import * as redux from 'react-redux'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } 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'; @@ -182,7 +183,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/search_inference_endpoints/public/hooks/use_delete_endpoint.test.tsx b/x-pack/plugins/search_inference_endpoints/public/hooks/use_delete_endpoint.test.tsx index 7f2c2157a3609..8c0e81e597cd4 100644 --- a/x-pack/plugins/search_inference_endpoints/public/hooks/use_delete_endpoint.test.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/hooks/use_delete_endpoint.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useKibana } from './use_kibana'; import { useDeleteEndpoint } from './use_delete_endpoint'; @@ -43,7 +44,7 @@ describe('useDeleteEndpoint', () => { }; it('should call delete endpoint and show success toast on success', async () => { - const { result, waitFor } = renderHook(() => useDeleteEndpoint(), { wrapper }); + const { result } = renderHook(() => useDeleteEndpoint(), { wrapper }); result.current.mutate({ type: 'text_embedding', id: 'in-1' }); @@ -60,7 +61,7 @@ describe('useDeleteEndpoint', () => { it('should show error toast on failure', async () => { const error = { body: { message: 'error' } }; mockDelete.mockRejectedValue(error); - const { result, waitFor } = renderHook(() => useDeleteEndpoint(), { wrapper }); + const { result } = renderHook(() => useDeleteEndpoint(), { wrapper }); result.current.mutate({ type: 'model', id: '123' }); diff --git a/x-pack/plugins/security_solution/public/common/components/discover_in_timeline/use_discover_in_timeline_actions.test.tsx b/x-pack/plugins/security_solution/public/common/components/discover_in_timeline/use_discover_in_timeline_actions.test.tsx index 6e9936b5f1b41..7efa6d5c6efb0 100644 --- a/x-pack/plugins/security_solution/public/common/components/discover_in_timeline/use_discover_in_timeline_actions.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/discover_in_timeline/use_discover_in_timeline_actions.test.tsx @@ -9,6 +9,7 @@ import { discoverPluginMock } from '@kbn/discover-plugin/public/mocks'; import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; import type { SavedSearch } from '@kbn/saved-search-plugin/common'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor, act } from '@testing-library/react'; import { createMockStore, mockGlobalState, TestProviders } from '../../mock'; import { useDiscoverInTimelineActions } from './use_discover_in_timeline_actions'; import type { Filter } from '@kbn/es-query'; @@ -20,9 +21,6 @@ import * as timelineActions from '../../../timelines/store/actions'; import type { ComponentType, FC, PropsWithChildren } from 'react'; import React from 'react'; import type { DataView } from '@kbn/data-views-plugin/common'; -import TestRenderer from 'react-test-renderer'; - -const { act } = TestRenderer; let mockDiscoverStateContainerRef = { current: discoverPluginMock.getDiscoverStateMock({}), @@ -148,7 +146,7 @@ describe('useDiscoverInTimelineActions', () => { }); describe('getAppStateFromSavedSearch', () => { it('should reach out to discover to convert app state from saved search', async () => { - const { result, waitFor } = renderTestHook(); + const { result } = renderTestHook(); const { appState } = result.current.getAppStateFromSavedSearch(savedSearchMock); await waitFor(() => { expect(appState).toMatchObject( @@ -178,7 +176,7 @@ describe('useDiscoverInTimelineActions', () => { describe('resetDiscoverAppState', () => { it('should reset Discover AppState to a default state', async () => { - const { result, waitFor } = renderTestHook(); + const { result } = renderTestHook(); await result.current.resetDiscoverAppState(); await waitFor(() => { const appState = mockDiscoverStateContainerRef.current.appState.getState(); @@ -186,7 +184,7 @@ describe('useDiscoverInTimelineActions', () => { }); }); it('should reset Discover time to a default state', async () => { - const { result, waitFor } = renderTestHook(); + const { result } = renderTestHook(); await result.current.resetDiscoverAppState(); await waitFor(() => { const globalState = mockDiscoverStateContainerRef.current.globalState.get(); @@ -197,6 +195,15 @@ describe('useDiscoverInTimelineActions', () => { describe('updateSavedSearch', () => { it('should add defaults to the savedSearch before updating saved search', async () => { const { result } = renderTestHook(); + + await waitFor(() => + expect(result.current).toEqual( + expect.objectContaining({ + updateSavedSearch: expect.any(Function), + }) + ) + ); + await act(async () => { await result.current.updateSavedSearch(savedSearchMock, TimelineId.active); }); @@ -216,6 +223,7 @@ describe('useDiscoverInTimelineActions', () => { }) ); }); + it('should initialize saved search when it is not set on the timeline model yet', async () => { const localMockState: State = { ...mockGlobalState, @@ -235,6 +243,13 @@ describe('useDiscoverInTimelineActions', () => { const LocalTestProvider = getTestProviderWithCustomState(localMockState); const { result } = renderTestHook(LocalTestProvider); + await waitFor(() => + expect(result.current).toEqual( + expect.objectContaining({ + updateSavedSearch: expect.any(Function), + }) + ) + ); await act(async () => { await result.current.updateSavedSearch(savedSearchMock, TimelineId.active); }); @@ -269,6 +284,13 @@ describe('useDiscoverInTimelineActions', () => { const LocalTestProvider = getTestProviderWithCustomState(localMockState); const { result } = renderTestHook(LocalTestProvider); + await waitFor(() => + expect(result.current).toEqual( + expect.objectContaining({ + updateSavedSearch: expect.any(Function), + }) + ) + ); await act(async () => { await result.current.updateSavedSearch(changedSavedSearchMock, TimelineId.active); }); diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.test.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.test.tsx index c5bc4a01f5140..e82bcf1e4c369 100644 --- a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.test.tsx @@ -87,8 +87,7 @@ describe('useHostIsolationAction', () => { }); } - const { result, waitForValueToChange } = render(); - await waitForValueToChange(() => result.current); + const { result } = render(); expect(result.current).toEqual([ buildExpectedMenuItemResult({ @@ -99,8 +98,8 @@ describe('useHostIsolationAction', () => { ); it('should call `closePopover` callback when menu item `onClick` is called', async () => { - const { result, waitForValueToChange } = render(); - await waitForValueToChange(() => result.current); + const { result } = render(); + await appContextMock.waitFor(() => result.current); result.current[0].onClick!({} as unknown as React.MouseEvent); expect(hookProps.closePopover).toHaveBeenCalled(); @@ -156,8 +155,8 @@ describe('useHostIsolationAction', () => { if (type === 'non-endpoint') { hookProps.detailsData = endpointAlertDataMock.generateSentinelOneAlertDetailsItemData(); } - const { result, waitForValueToChange } = render(); - await waitForValueToChange(() => result.current); + const { result } = render(); + await appContextMock.waitFor(() => result.current); expect(result.current).toEqual([ buildExpectedMenuItemResult({ @@ -170,8 +169,8 @@ describe('useHostIsolationAction', () => { ); it('should call isolate API when agent is currently NOT isolated', async () => { - const { result, waitForValueToChange } = render(); - await waitForValueToChange(() => result.current); + const { result } = render(); + await appContextMock.waitFor(() => result.current); result.current[0].onClick!({} as unknown as React.MouseEvent); expect(hookProps.onAddIsolationStatusClick).toHaveBeenCalledWith('isolateHost'); @@ -183,8 +182,8 @@ describe('useHostIsolationAction', () => { data: { 'abfe4a35-d5b4-42a0-a539-bd054c791769': { isolated: true } }, }) ); - const { result, waitForValueToChange } = render(); - await waitForValueToChange(() => result.current); + const { result } = render(); + await appContextMock.waitFor(() => result.current); result.current[0].onClick!({} as unknown as React.MouseEvent); expect(hookProps.onAddIsolationStatusClick).toHaveBeenCalledWith('unisolateHost'); diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_data.test.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_data.test.ts index aef471f814210..9693e62aab3b4 100644 --- a/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_data.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/responder/from_alerts/use_responder_action_data.test.ts @@ -96,7 +96,9 @@ describe('use responder action data hooks', () => { it('should call `onClick()` function prop when is pass to the hook', () => { alertDetailItemData = endpointAlertDataMock.generateSentinelOneAlertDetailsItemData(); const { result } = renderHook(); - result.current.handleResponseActionsClick(); + act(() => { + result.current.handleResponseActionsClick(); + }); expect(onClickMock).toHaveBeenCalled(); }); @@ -104,7 +106,9 @@ describe('use responder action data hooks', () => { it('should NOT call `onClick` if the action is disabled', () => { alertDetailItemData = endpointAlertDataMock.generateAlertDetailsItemDataForAgentType('foo'); const { result } = renderHook(); - result.current.handleResponseActionsClick(); + act(() => { + result.current.handleResponseActionsClick(); + }); expect(onClickMock).not.toHaveBeenCalled(); }); @@ -171,7 +175,7 @@ describe('use responder action data hooks', () => { it('should show action enabled if host metadata was retrieved and host is enrolled', async () => { const { result } = renderHook(); - await waitFor(() => expect(result.current.isDisabled).toBe(true)); + await waitFor(() => expect(result.current.isDisabled).toBe(false)); expect(result.current).toEqual(getExpectedResponderActionData()); }); @@ -182,9 +186,10 @@ describe('use responder action data hooks', () => { statusCode: 404, }); }); + const { result } = renderHook(); - await waitFor(() => null); + await waitFor(() => expect(result.current.tooltip).not.toEqual('Loading')); expect(result.current).toEqual( getExpectedResponderActionData({ @@ -201,8 +206,8 @@ describe('use responder action data hooks', () => { }; metadataApiMocks.responseProvider.metadataDetails.mockReturnValue(hostMetadata); - const { result, waitForValueToChange } = renderHook(); - await waitForValueToChange(() => result.current.tooltip); + const { result } = renderHook(); + await waitFor(() => expect(result.current.tooltip).not.toEqual('Loading')); expect(result.current).toEqual( getExpectedResponderActionData({ @@ -218,8 +223,8 @@ describe('use responder action data hooks', () => { statusCode: 500, }); }); - const { result, waitForValueToChange } = renderHook(); - await waitForValueToChange(() => result.current.tooltip); + const { result } = renderHook(); + await waitFor(() => expect(result.current.tooltip).not.toEqual('Loading')); expect(result.current).toEqual( getExpectedResponderActionData({ @@ -250,8 +255,8 @@ describe('use responder action data hooks', () => { }); it('should show action enabled when agentType is Endpoint and host is enabled', async () => { - const { result, waitForValueToChange } = renderHook(); - await waitForValueToChange(() => result.current.isDisabled); + const { result } = renderHook(); + await waitFor(() => expect(result.current.isDisabled).toBe(false)); expect(result.current).toEqual(getExpectedResponderActionData()); }); diff --git a/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx b/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx index b42dbc3b7a0b8..de846ec8bfd77 100644 --- a/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx +++ b/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx @@ -10,7 +10,7 @@ import React from 'react'; import type { MemoryHistory } from 'history'; import { createMemoryHistory } from 'history'; import type { RenderOptions, RenderResult } from '@testing-library/react'; -import { render as reactRender } from '@testing-library/react'; +import { render as reactRender, waitFor } from '@testing-library/react'; import type { Action, Reducer, Store } from 'redux'; import { QueryClient } from '@tanstack/react-query'; import { coreMock } from '@kbn/core/public/mocks'; @@ -152,6 +152,11 @@ export interface AppContextTestRender { */ renderHook: ReactHooksRenderer['renderHook']; + /** + * Waits the return value of the callback provided to is truthy + */ + waitFor: typeof waitFor; + /** * A helper utility for rendering specifically hooks that wrap ReactQuery */ @@ -323,7 +328,7 @@ export const createAppRootMockRenderer = (): AppContextTestRender => { waitForHook: WaitForReactHookState = 'isSuccess', options: RenderHookOptions = {} ) => { - const { result: hookResult, waitFor } = renderHook(hookFn, options); + const { result: hookResult } = renderHook(hookFn, options); if (waitForHook) { await waitFor(() => { @@ -400,6 +405,7 @@ export const createAppRootMockRenderer = (): AppContextTestRender => { setExperimentalFlag, getUserPrivilegesMockSetter, queryClient, + waitFor, }; }; diff --git a/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_risk_score.test.tsx b/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_risk_score.test.tsx index 60fdb04dffa96..a0c57ded3516e 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_risk_score.test.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_risk_score.test.tsx @@ -5,6 +5,8 @@ * 2.0. */ import { renderHook } from '@testing-library/react-hooks'; + +import { waitFor } from '@testing-library/react'; import { useRiskScore } from './use_risk_score'; import { TestProviders } from '../../../common/mock'; @@ -218,7 +220,7 @@ describe.each([RiskScoreEntity.host, RiskScoreEntity.user])( totalCount: 0, }, }); - const { result, waitFor } = renderHook(() => useRiskScore({ riskEntity }), { + const { result } = renderHook(() => useRiskScore({ riskEntity }), { wrapper: TestProviders, }); await waitFor(() => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx index 05eb29c666360..df4d64e5be133 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; -import { fireEvent, render, act, waitFor } from '@testing-library/react'; +import { fireEvent, render, act, waitFor, screen } from '@testing-library/react'; import type { UseTimelineTypesArgs, UseTimelineTypesResult } from './use_timeline_types'; import { useTimelineTypes } from './use_timeline_types'; import { TestProviders } from '../../../common/mock'; @@ -49,7 +49,7 @@ jest.mock('@kbn/kibana-react-plugin/public', () => { describe('useTimelineTypes', () => { it('init', async () => { - const { result } = renderHook( + const { result } = renderHook( () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { wrapper: TestProviders, @@ -65,7 +65,7 @@ describe('useTimelineTypes', () => { describe('timelineTabs', () => { it('render timelineTabs', async () => { - const { result } = renderHook( + const { result } = renderHook( () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { wrapper: TestProviders, @@ -83,13 +83,14 @@ describe('useTimelineTypes', () => { }); it('set timelineTypes correctly', async () => { - const { result } = renderHook( + const { result } = renderHook( () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { wrapper: TestProviders, } ); - await waitFor(() => null); + + await waitFor(() => expect(result.current.timelineTabs).toBeDefined()); const { container } = render(result.current.timelineTabs); @@ -103,17 +104,18 @@ describe('useTimelineTypes', () => { ); }); - await waitFor(() => null); + await waitFor(() => expect(result.current.timelineType).toEqual('template')); - expect(result.current).toEqual({ - timelineType: 'template', - timelineTabs: result.current.timelineTabs, - timelineFilters: result.current.timelineFilters, - }); + expect(result.current).toEqual( + expect.objectContaining({ + timelineTabs: result.current.timelineTabs, + timelineFilters: result.current.timelineFilters, + }) + ); }); it('stays in the same tab if clicking again on current tab', async () => { - const { result } = renderHook( + const { result } = renderHook( () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { wrapper: TestProviders, @@ -145,7 +147,7 @@ describe('useTimelineTypes', () => { describe('timelineFilters', () => { it('render timelineFilters', async () => { - const { result } = renderHook( + const { result } = renderHook( () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { wrapper: TestProviders, @@ -164,37 +166,33 @@ describe('useTimelineTypes', () => { }); it('set timelineTypes correctly', async () => { - const { result } = renderHook( + const { result } = renderHook( () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { wrapper: TestProviders, } ); - await waitFor(() => null); - const { container } = render(<>{result.current.timelineFilters}); + await waitFor(() => expect(result.current.timelineFilters).toBeDefined()); - act(() => { - fireEvent( - container.querySelector('[data-test-subj="open-timeline-modal-body-filter-template"]')!, - new MouseEvent('click', { - bubbles: true, - cancelable: true, - }) - ); - }); + render(<>{result.current.timelineFilters}); await waitFor(() => null); - expect(result.current).toEqual({ - timelineType: 'template', - timelineTabs: result.current.timelineTabs, - timelineFilters: result.current.timelineFilters, - }); + fireEvent.click(screen.getByTestId('open-timeline-modal-body-filter-template')); + + await waitFor(() => expect(result.current.timelineType).toEqual('template')); + + expect(result.current).toEqual( + expect.objectContaining({ + timelineTabs: result.current.timelineTabs, + timelineFilters: result.current.timelineFilters, + }) + ); }); it('stays in the same tab if clicking again on current tab', async () => { - const { result } = renderHook( + const { result } = renderHook( () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { wrapper: TestProviders, diff --git a/x-pack/plugins/threat_intelligence/public/modules/block_list/hooks/use_policies.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/block_list/hooks/use_policies.test.tsx index a01b7da64b684..0d8eb0cadc9b1 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/block_list/hooks/use_policies.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/block_list/hooks/use_policies.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query'; const createWrapper = () => { @@ -24,9 +25,7 @@ const renderUseQuery = (result: { items: any[] }) => describe('usePolicies', () => { it('should have undefined data during loading state', async () => { const mockPolicies = { items: [] }; - const { result, waitFor } = renderUseQuery(mockPolicies); - - await waitFor(() => result.current.isLoading); + const { result } = renderUseQuery(mockPolicies); expect(result.current.isLoading).toBeTruthy(); expect(result.current.data).toBeUndefined(); @@ -41,9 +40,9 @@ describe('usePolicies', () => { }, ], }; - const { result, waitFor } = renderUseQuery(mockPolicies); + const { result } = renderUseQuery(mockPolicies); - await waitFor(() => result.current.isSuccess); + await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); expect(result.current.isLoading).toBeFalsy(); expect(result.current.data).toEqual(mockPolicies); diff --git a/x-pack/plugins/threat_intelligence/public/modules/cases/hooks/use_indicator_by_id.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/cases/hooks/use_indicator_by_id.test.tsx index 0c23962ccaa46..a3593def63b40 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/cases/hooks/use_indicator_by_id.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/cases/hooks/use_indicator_by_id.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useIndicatorById, UseIndicatorByIdValue } from './use_indicator_by_id'; import { TestProvidersComponent } from '../../../mocks/test_providers'; import { createFetchIndicatorById } from '../services/fetch_indicator_by_id'; @@ -49,8 +50,7 @@ describe('useIndicatorById()', () => { expect(indicatorsQuery).toHaveBeenCalledTimes(1); // isLoading should turn to false eventually - await hookResult.waitFor(() => !hookResult.result.current.isLoading); - expect(hookResult.result.current.isLoading).toEqual(false); + await waitFor(() => expect(hookResult.result.current.isLoading).toBe(false)); }); }); }); From 906f7cddfe916c76cd286e03fb96d4f35d5f8cb1 Mon Sep 17 00:00:00 2001 From: Eyo Okon Eyo Date: Tue, 1 Oct 2024 14:15:16 +0100 Subject: [PATCH 05/18] more test fixes --- .../use_filters_sync_to_local_storage.test.ts | 23 +- .../get_search_embeddable_factory.test.tsx | 8 +- .../use_delete_knowledge_base.test.tsx | 33 +-- .../chat_send/use_chat_send.test.tsx | 12 +- .../components/add_comment/index.test.tsx | 2 +- .../use_user_actions_last_page.test.tsx | 7 +- .../use_suggest_user_profiles.test.ts | 5 +- ..._failed_transactions_correlations.test.tsx | 45 ++-- .../use_latency_correlations.test.tsx | 6 +- .../apm/public/hooks/use_fetcher.test.tsx | 27 ++- .../hooks/use_locations_api.test.tsx | 2 +- .../events/last_event_time/index.test.ts | 39 ++-- .../common/hooks/use_fetch/use_fetch.test.tsx | 22 +- .../use_execution_results.test.tsx | 9 +- .../components/user_info/index.test.tsx | 8 +- .../alerts/use_signal_index.test.tsx | 219 +++++++++--------- .../console_manager.test.tsx | 16 +- .../use_cases_by_status.test.tsx | 30 +-- .../components/fields_browser/index.test.tsx | 4 +- .../open_timeline/use_timeline_types.test.tsx | 45 ++-- .../properties/use_notes_in_flyout.test.tsx | 3 +- .../public/app/hooks/use_index_data.test.tsx | 4 +- .../application/hooks/use_load_rules.test.tsx | 3 +- 23 files changed, 275 insertions(+), 297 deletions(-) diff --git a/packages/kbn-alerts-ui-shared/src/alert_filter_controls/hooks/use_filters_sync_to_local_storage.test.ts b/packages/kbn-alerts-ui-shared/src/alert_filter_controls/hooks/use_filters_sync_to_local_storage.test.ts index cb7a9b7f3c5c8..6a967614c4e1d 100644 --- a/packages/kbn-alerts-ui-shared/src/alert_filter_controls/hooks/use_filters_sync_to_local_storage.test.ts +++ b/packages/kbn-alerts-ui-shared/src/alert_filter_controls/hooks/use_filters_sync_to_local_storage.test.ts @@ -9,6 +9,7 @@ import type { ControlGroupRuntimeState } from '@kbn/controls-plugin/public'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useControlGroupSyncToLocalStorage } from './use_control_group_sync_to_local_storage'; import { Storage } from '@kbn/kibana-utils-plugin/public'; @@ -39,30 +40,34 @@ describe('Filters Sync to Local Storage', () => { }); it('should not be undefined if localStorage has initial value', () => { global.localStorage.setItem(TEST_STORAGE_KEY, JSON.stringify(DEFAULT_STORED_VALUE)); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useControlGroupSyncToLocalStorage({ Storage, storageKey: TEST_STORAGE_KEY, shouldSync: true, }) ); - waitForNextUpdate(); - expect(result.current.controlGroupState).toMatchObject(DEFAULT_STORED_VALUE); + waitFor(() => expect(result.current.controlGroupState).toMatchObject(DEFAULT_STORED_VALUE)); }); it('should be undefined if localstorage as NO initial value', () => { - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useControlGroupSyncToLocalStorage({ Storage, storageKey: TEST_STORAGE_KEY, shouldSync: true, }) ); - waitForNextUpdate(); - expect(result.current.controlGroupState).toBeUndefined(); - expect(result.current.setControlGroupState).toBeTruthy(); + waitFor(() => + expect(result.current).toBe( + expect.objectContaining({ + controlGroupState: undefined, + setControlGroupState: expect.any(Function), + }) + ) + ); }); it('should be update values to local storage when sync is ON', () => { - const { result, waitFor } = renderHook(() => + const { result } = renderHook(() => useControlGroupSyncToLocalStorage({ Storage, storageKey: TEST_STORAGE_KEY, @@ -82,7 +87,7 @@ describe('Filters Sync to Local Storage', () => { }); }); it('should not update values to local storage when sync is OFF', () => { - const { waitFor, result, rerender } = renderHook(() => + const { result, rerender } = renderHook(() => useControlGroupSyncToLocalStorage({ Storage, storageKey: TEST_STORAGE_KEY, diff --git a/src/plugins/discover/public/embeddable/get_search_embeddable_factory.test.tsx b/src/plugins/discover/public/embeddable/get_search_embeddable_factory.test.tsx index 1c8b77982fb24..9f90db81c1e0f 100644 --- a/src/plugins/discover/public/embeddable/get_search_embeddable_factory.test.tsx +++ b/src/plugins/discover/public/embeddable/get_search_embeddable_factory.test.tsx @@ -18,7 +18,7 @@ import { BuildReactEmbeddableApiRegistration } from '@kbn/embeddable-plugin/publ import { PresentationContainer } from '@kbn/presentation-containers'; import { PhaseEvent, PublishesUnifiedSearch, StateComparators } from '@kbn/presentation-publishing'; import { VIEW_MODE } from '@kbn/saved-search-plugin/common'; -import { act, render } from '@testing-library/react'; +import { act, render, waitFor } from '@testing-library/react'; import { AggregateQuery, Filter, Query, TimeRange } from '@kbn/es-query'; import { createDataViewDataSource } from '../../common/data_sources'; @@ -143,8 +143,10 @@ describe('saved search embeddable', () => { expect(api.dataLoading.getValue()).toBe(false); expect(discoverComponent.queryByTestId('embeddedSavedSearchDocTable')).toBeInTheDocument(); - expect(discoverComponent.getByTestId('embeddedSavedSearchDocTable').textContent).toEqual( - 'No results found' + await waitFor(() => + expect(discoverComponent.getByTestId('embeddedSavedSearchDocTable').textContent).toEqual( + 'No results found' + ) ); }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.test.tsx index 10ce8bab59c6e..31fd23e950764 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.test.tsx @@ -6,7 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; -import { act, waitFor } from '@testing-library/react'; +import { waitFor } from '@testing-library/react'; import { useDeleteKnowledgeBase, UseDeleteKnowledgeBaseParams } from './use_delete_knowledge_base'; import { deleteKnowledgeBase as _deleteKnowledgeBase } from './api'; import { useMutation as _useMutation } from '@tanstack/react-query'; @@ -51,10 +51,8 @@ describe('useDeleteKnowledgeBase', () => { jest.clearAllMocks(); }); it('should call api to delete knowledge base', async () => { - await act(async () => { - renderHook(() => useDeleteKnowledgeBase(defaultProps)); - await waitFor(() => null); - + renderHook(() => useDeleteKnowledgeBase(defaultProps)); + await waitFor(() => { expect(defaultProps.http.fetch).toHaveBeenCalledWith( '/internal/elastic_assistant/knowledge_base/', { @@ -75,10 +73,9 @@ describe('useDeleteKnowledgeBase', () => { opts.onError(e); } }); - await act(async () => { - renderHook(() => useDeleteKnowledgeBase(defaultProps)); - await waitFor(() => null); + renderHook(() => useDeleteKnowledgeBase(defaultProps)); + await waitFor(() => expect(defaultProps.http.fetch).toHaveBeenCalledWith( '/internal/elastic_assistant/knowledge_base/something', { @@ -86,26 +83,20 @@ describe('useDeleteKnowledgeBase', () => { signal: undefined, version: '1', } - ); - }); + ) + ); }); it('should return delete response', async () => { - await act(async () => { - renderHook(() => useDeleteKnowledgeBase(defaultProps)); - await waitFor(() => null); + const { result } = renderHook(() => useDeleteKnowledgeBase(defaultProps)); + await waitFor(() => null); - await expect(result.current).resolves.toStrictEqual(statusResponse); - }); + await expect(result.current).resolves.toStrictEqual(statusResponse); }); it('should display error toast when api throws error', async () => { deleteKnowledgeBaseMock.mockRejectedValue(new Error('this is an error')); - await act(async () => { - renderHook(() => useDeleteKnowledgeBase(defaultProps)); - await waitFor(() => null); - - expect(toasts.addError).toHaveBeenCalled(); - }); + renderHook(() => useDeleteKnowledgeBase(defaultProps)); + await waitFor(() => expect(toasts.addError).toHaveBeenCalled()); }); }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.test.tsx index 0de7adc484fc1..5a3e035019cb4 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.test.tsx @@ -61,10 +61,10 @@ describe('use chat send', () => { }); it('handleOnChatCleared clears the conversation', async () => { (clearConversation as jest.Mock).mockReturnValueOnce(testProps.currentConversation); - const { result, waitForNextUpdate } = renderHook(() => useChatSend(testProps), { + const { result } = renderHook(() => useChatSend(testProps), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => null); act(() => { result.current.handleOnChatCleared(); }); @@ -96,7 +96,7 @@ describe('use chat send', () => { }); }); it('handleRegenerateResponse removes the last message of the conversation, resends the convo to GenAI, and appends the message received', async () => { - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => useChatSend({ ...testProps, currentConversation: { ...welcomeConvo, id: 'welcome-id' } }), { @@ -104,7 +104,7 @@ describe('use chat send', () => { } ); - await waitForNextUpdate(); + await waitFor(() => null); act(() => { result.current.handleRegenerateResponse(); }); @@ -118,10 +118,10 @@ describe('use chat send', () => { }); it('sends telemetry events for both user and assistant', async () => { const promptText = 'prompt text'; - const { result, waitForNextUpdate } = renderHook(() => useChatSend(testProps), { + const { result } = renderHook(() => useChatSend(testProps), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => null); act(() => { result.current.handleChatSend(promptText); }); 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..092b716dd3b61 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 @@ -79,8 +79,8 @@ describe('AddComment ', () => { }); fireEvent.click(screen.getByTestId('submit-comment')); + await waitFor(() => expect(screen.getByTestId('loading-spinner')).toBeInTheDocument()); - expect(await screen.findByTestId('loading-spinner')).toBeInTheDocument(); expect(screen.getByTestId('submit-comment')).toHaveAttribute('disabled'); }); diff --git a/x-pack/plugins/cases/public/components/user_actions/use_user_actions_last_page.test.tsx b/x-pack/plugins/cases/public/components/user_actions/use_user_actions_last_page.test.tsx index 3207e4ffb13fe..92c485d01d7d8 100644 --- a/x-pack/plugins/cases/public/components/user_actions/use_user_actions_last_page.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/use_user_actions_last_page.test.tsx @@ -6,6 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useLastPageUserActions } from './use_user_actions_last_page'; import type { UserActivityParams } from '../user_actions_activity_bar/types'; @@ -32,7 +33,7 @@ describe('useLastPageUserActions', () => { }); it('renders correctly', async () => { - const { result, waitFor } = renderHook(() => + const { result } = renderHook(() => useLastPageUserActions({ lastPage: 5, userActivityQueryParams, @@ -79,7 +80,7 @@ describe('useLastPageUserActions', () => { it('returns loading state correctly', async () => { useFindCaseUserActionsMock.mockReturnValue({ isLoading: true }); - const { result, waitFor } = renderHook(() => + const { result } = renderHook(() => useLastPageUserActions({ lastPage: 2, userActivityQueryParams, @@ -108,7 +109,7 @@ describe('useLastPageUserActions', () => { it('returns empty array when data is undefined', async () => { useFindCaseUserActionsMock.mockReturnValue({ isLoading: false, data: undefined }); - const { result, waitFor } = renderHook(() => + const { result } = renderHook(() => useLastPageUserActions({ lastPage: 2, userActivityQueryParams, diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.test.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.test.ts index 7daf1d1d5cf62..4357f6231a7a4 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.test.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.test.ts @@ -7,6 +7,7 @@ import { GENERAL_CASES_OWNER } from '../../../common/constants'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useToasts } from '../../common/lib/kibana'; import type { AppMockRenderer } from '../../common/mock'; import { createAppMockRenderer } from '../../common/mock'; @@ -34,7 +35,7 @@ describe('useSuggestUserProfiles', () => { it('calls suggestUserProfiles with correct arguments', async () => { const spyOnSuggestUserProfiles = jest.spyOn(api, 'suggestUserProfiles'); - const { result, waitFor } = renderHook(() => useSuggestUserProfiles(props), { + const { result } = renderHook(() => useSuggestUserProfiles(props), { wrapper: appMockRender.AppWrapper, }); @@ -58,7 +59,7 @@ describe('useSuggestUserProfiles', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess, addError }); - const { result, waitFor } = renderHook(() => useSuggestUserProfiles(props), { + const { result } = renderHook(() => useSuggestUserProfiles(props), { wrapper: appMockRender.AppWrapper, }); diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/correlations/use_failed_transactions_correlations.test.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/correlations/use_failed_transactions_correlations.test.tsx index 79d32177bf909..52f0e7e063fe3 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/correlations/use_failed_transactions_correlations.test.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/correlations/use_failed_transactions_correlations.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { ReactNode } from 'react'; +import React, { PropsWithChildren } from 'react'; import { merge } from 'lodash'; import { createMemoryHistory } from 'history'; import { renderHook } from '@testing-library/react-hooks'; @@ -24,7 +24,7 @@ import { fromQuery } from '../../shared/links/url_helpers'; import { useFailedTransactionsCorrelations } from './use_failed_transactions_correlations'; import type { APIEndpoint } from '../../../../server'; -function wrapper({ children, error = false }: { children?: ReactNode; error: boolean }) { +function wrapper({ children, error = false }: PropsWithChildren<{ error?: boolean }>) { const getHttpMethodMock = (method: 'GET' | 'POST') => jest.fn().mockImplementation(async (pathname) => { await delay(100); @@ -109,17 +109,18 @@ describe('useFailedTransactionsCorrelations', () => { wrapper, }); - try { + await waitFor(() => expect(result.current.progress).toEqual({ isRunning: true, loaded: 0, - }); - expect(result.current.response).toEqual({ ccsWarning: false }); - expect(typeof result.current.startFetch).toEqual('function'); - expect(typeof result.current.cancelFetch).toEqual('function'); - } finally { - unmount(); - } + }) + ); + + expect(result.current.response).toEqual({ ccsWarning: false }); + expect(result.current.startFetch).toEqual(expect.any(Function)); + expect(result.current.cancelFetch).toEqual(expect.any(Function)); + + unmount(); }); it('should not have received any results after 50ms', async () => { @@ -127,17 +128,17 @@ describe('useFailedTransactionsCorrelations', () => { wrapper, }); - try { - jest.advanceTimersByTime(50); + jest.advanceTimersByTime(50); + await waitFor(() => expect(result.current.progress).toEqual({ isRunning: true, loaded: 0, - }); - expect(result.current.response).toEqual({ ccsWarning: false }); - } finally { - unmount(); - } + }) + ); + + expect(result.current.response).toEqual({ ccsWarning: false }); + unmount(); }); it('should receive partial updates and finish running', async () => { @@ -262,14 +263,14 @@ describe('useFailedTransactionsCorrelations', () => { }, }); - try { + await waitFor(() => expect(result.current.progress).toEqual({ isRunning: true, loaded: 0, - }); - } finally { - unmount(); - } + }) + ); + + unmount(); }); it('should still be running after 50ms', async () => { diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/correlations/use_latency_correlations.test.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/correlations/use_latency_correlations.test.tsx index 616f92466fb44..ab7bf866cc922 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/correlations/use_latency_correlations.test.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/correlations/use_latency_correlations.test.tsx @@ -5,10 +5,10 @@ * 2.0. */ -import React, { ReactNode } from 'react'; +import React, { PropsWithChildren } from 'react'; import { merge } from 'lodash'; import { createMemoryHistory } from 'history'; -import { act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; import { act, waitFor } from '@testing-library/react'; @@ -24,7 +24,7 @@ import { fromQuery } from '../../shared/links/url_helpers'; import { useLatencyCorrelations } from './use_latency_correlations'; import type { APIEndpoint } from '../../../../server'; -function wrapper({ children, error = false }: { children?: ReactNode; error: boolean }) { +function wrapper({ children, error = false }: PropsWithChildren<{ error?: boolean }>) { const getHttpMethodMock = (method: 'GET' | 'POST') => jest.fn().mockImplementation(async (pathname) => { await delay(100); diff --git a/x-pack/plugins/observability_solution/apm/public/hooks/use_fetcher.test.tsx b/x-pack/plugins/observability_solution/apm/public/hooks/use_fetcher.test.tsx index 604d85699b3e3..ce3902b5f31a5 100644 --- a/x-pack/plugins/observability_solution/apm/public/hooks/use_fetcher.test.tsx +++ b/x-pack/plugins/observability_solution/apm/public/hooks/use_fetcher.test.tsx @@ -72,7 +72,7 @@ describe('useFetcher', () => { jest.advanceTimersByTime(1000); }); - await waitFor(() => null); + await waitFor(() => expect(hook.result.current.status).toBe('success')); expect(hook.result.current).toEqual({ data: 'response from hook', @@ -100,7 +100,7 @@ describe('useFetcher', () => { hook = renderHook(() => useFetcher(() => fn(), []), { wrapper }); }); - it('should have loading spinner initally', async () => { + it('should have loading spinner initially', async () => { expect(hook.result.current).toEqual({ data: undefined, error: undefined, @@ -127,7 +127,8 @@ describe('useFetcher', () => { jest.advanceTimersByTime(1000); }); - await waitFor(() => null); + // @ts-ignore + await waitFor(() => expect(hook.result.current.status).toBe('failure')); expect(hook.result.current).toEqual({ data: undefined, @@ -160,7 +161,8 @@ describe('useFetcher', () => { status: 'loading', }); - await waitFor(() => null); + // @ts-ignore + await waitFor(() => expect(hook.result.current.status).toBe('success')); // assert: first response has loaded and should be rendered expect(hook.result.current).toEqual({ @@ -197,7 +199,7 @@ describe('useFetcher', () => { jest.advanceTimersByTime(500); }); - await waitFor(() => null); + await waitFor(() => expect(hook.result.current.status).toBe('success')); // assert: "second response" has loaded and should be rendered expect(hook.result.current).toEqual({ @@ -209,20 +211,23 @@ describe('useFetcher', () => { }); it('should return the same object reference when data is unchanged between rerenders', async () => { + const initialProps = { + callback: async () => 'data response', + args: ['a'], + }; + const hook = renderHook( /* eslint-disable-next-line react-hooks/exhaustive-deps */ ({ callback, args }) => useFetcher(callback, args), { - initialProps: { - callback: async () => 'data response', - args: ['a'], - }, + initialProps, wrapper, } ); - await hook.waitForNextUpdate(); + + await waitFor(() => expect(hook.result.current.status).toBe('success')); const firstResult = hook.result.current; - hook.rerender(); + hook.rerender(initialProps); const secondResult = hook.result.current; // assert: subsequent rerender returns the same object reference 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 1c23fdaaba200..c29269dff7b1d 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,7 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; import { act, waitFor } from '@testing-library/react'; import { WrappedHelper } from '../../../../utils/testing'; import { getServiceLocations } from '../../../../state/service_locations'; diff --git a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.test.ts b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.test.ts index 1ed7edc6f7531..7111822faebec 100644 --- a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.test.ts +++ b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.test.ts @@ -7,32 +7,19 @@ import { renderHook } from '@testing-library/react-hooks'; import { waitFor } from '@testing-library/react'; -import { noop } from 'lodash/fp'; +import { BehaviorSubject } from 'rxjs'; import type { UseTimelineLastEventTimeArgs } from '.'; import { useTimelineLastEventTime } from '.'; import { LastEventIndexKey } from '../../../../../common/search_strategy'; import { useKibana } from '../../../lib/kibana'; const mockSearchStrategy = jest.fn(); + const mockUseKibana = { services: { data: { search: { - search: mockSearchStrategy.mockReturnValue({ - unsubscribe: jest.fn(), - subscribe: jest.fn(({ next, error }) => { - const mockData = { - lastSeen: '1 minute ago', - }; - try { - next(mockData); - /* eslint-disable no-empty */ - } catch (e) {} - return { - unsubscribe: jest.fn(), - }; - }), - }), + search: mockSearchStrategy, }, }, notifications: { @@ -54,11 +41,23 @@ jest.mock('../../../lib/kibana', () => ({ })); describe('useTimelineLastEventTime', () => { + let searchStrategy$: BehaviorSubject<{ lastSeen: string | null; errorMessage?: string }>; + beforeEach(() => { - jest.clearAllMocks(); + jest.useFakeTimers({ legacyFakeTimers: true }); + searchStrategy$ = new BehaviorSubject<{ lastSeen: string | null; errorMessage?: string }>({ + lastSeen: null, + }); + + mockSearchStrategy.mockReturnValue(searchStrategy$.asObservable()); + (useKibana as jest.Mock).mockReturnValue(mockUseKibana); }); + afterEach(() => { + jest.clearAllMocks(); + }); + it('should init', async () => { const { result } = renderHook(() => useTimelineLastEventTime({ @@ -70,7 +69,7 @@ describe('useTimelineLastEventTime', () => { expect(result.current).toEqual([ false, - { errorMessage: undefined, lastSeen: null, refetch: noop }, + { errorMessage: undefined, lastSeen: null, refetch: expect.any(Function) }, ]); }); @@ -92,6 +91,10 @@ describe('useTimelineLastEventTime', () => { }); it('should set response', async () => { + searchStrategy$.next({ + lastSeen: '1 minute ago', + }); + const { result } = renderHook(() => useTimelineLastEventTime({ indexKey: LastEventIndexKey.hostDetails, diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.test.tsx b/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.test.tsx index 6178caee1b0ad..0b338d083b2eb 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.test.tsx +++ b/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.test.tsx @@ -66,10 +66,9 @@ describe('useFetch', () => { result.current.fetch(parameters); }); - await waitFor(() => null); + await waitFor(() => expect(result.current.isLoading).toEqual(false)); expect(result.current.data).toEqual(response); - expect(result.current.isLoading).toEqual(false); expect(result.current.error).toEqual(undefined); expect(mockFetchFn).toHaveBeenCalledWith(parameters, abortController.signal); }); @@ -83,10 +82,9 @@ describe('useFetch', () => { expect(mockFetchFn).toHaveBeenCalledWith(parameters, abortController.signal); - await waitFor(() => null); + await waitFor(() => expect(result.current.isLoading).toEqual(false)); expect(result.current.data).toEqual(response); - expect(result.current.isLoading).toEqual(false); expect(result.current.error).toEqual(undefined); }); @@ -100,9 +98,7 @@ describe('useFetch', () => { result.current.refetch(); }); - await waitFor(() => null); - - expect(mockFetchFn).toHaveBeenCalledTimes(1); + await waitFor(() => expect(mockFetchFn).toHaveBeenCalledTimes(1)); expect(mockFetchFn).toHaveBeenCalledWith(parameters, abortController.signal); }); @@ -121,10 +117,10 @@ describe('useFetch', () => { await act(async () => { result.current.fetch(parameters); }); - await waitFor(() => null); + + await waitFor(() => expect(result.current.isLoading).toEqual(true)); expect(result.current.data).toEqual(undefined); - expect(result.current.isLoading).toEqual(true); expect(result.current.error).toEqual(undefined); expect(mockFetchFn).not.toHaveBeenCalled(); }); @@ -200,7 +196,7 @@ describe('useFetch', () => { result.current.fetch(parameters); }); - await waitFor(() => null); + await waitFor(() => expect(firstAbortCtrl.signal.aborted).toEqual(true)); expect(firstAbortCtrl.signal.aborted).toEqual(true); @@ -215,9 +211,8 @@ describe('useFetch', () => { result.current.fetch(parameters); }); - await waitFor(() => null); + await waitFor(() => expect(mockStartTracking).toHaveBeenCalledTimes(1)); - expect(mockStartTracking).toHaveBeenCalledTimes(1); expect(mockStartTracking).toHaveBeenCalledWith({ name: requestName }); }); @@ -237,9 +232,8 @@ describe('useFetch', () => { result.current.fetch(parameters); }); - await waitFor(() => null); + await waitFor(() => expect(mockFetchFn).toHaveBeenCalledTimes(2)); - expect(mockFetchFn).toHaveBeenCalledTimes(2); expect(mockStartTracking).toHaveBeenCalledTimes(2); expect(mockEndTracking).toHaveBeenCalledTimes(2); }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring/components/execution_results_table/use_execution_results.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring/components/execution_results_table/use_execution_results.test.tsx index 07010105cdb25..19967ac7f31ad 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring/components/execution_results_table/use_execution_results.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring/components/execution_results_table/use_execution_results.test.tsx @@ -51,9 +51,8 @@ describe('useExecutionResults', () => { render(); - await waitFor(() => null); + await waitFor(() => expect(fetchRuleExecutionResults).toHaveBeenCalledTimes(1)); - expect(fetchRuleExecutionResults).toHaveBeenCalledTimes(1); expect(fetchRuleExecutionResults).toHaveBeenLastCalledWith( expect.objectContaining({ ruleId: SOME_RULE_ID }) ); @@ -68,10 +67,9 @@ describe('useExecutionResults', () => { expect(result.current.isError).toEqual(false); // When fetchRuleExecutionEvents returns - await waitFor(() => null); + await waitFor(() => expect(result.current.isLoading).toEqual(false)); // It switches to a success state - expect(result.current.isLoading).toEqual(false); expect(result.current.isSuccess).toEqual(true); expect(result.current.isError).toEqual(false); expect(result.current.data).toEqual({ @@ -116,10 +114,9 @@ describe('useExecutionResults', () => { expect(result.current.isError).toEqual(false); // When fetchRuleExecutionEvents throws - await waitFor(() => null); + await waitFor(() => expect(result.current.isLoading).toEqual(false)); // It switches to an error state - expect(result.current.isLoading).toEqual(false); expect(result.current.isSuccess).toEqual(false); expect(result.current.isError).toEqual(true); expect(result.current.error).toEqual(exception); diff --git a/x-pack/plugins/security_solution/public/detections/components/user_info/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/user_info/index.test.tsx index 080aad1dd2700..429a6a8856f4f 100644 --- a/x-pack/plugins/security_solution/public/detections/components/user_info/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/user_info/index.test.tsx @@ -79,9 +79,9 @@ describe('useUserInfo', () => { ); renderHook(() => useUserInfo(), { wrapper }); - await waitFor(() => null); - - expect(spyOnGetSignalIndex).toHaveBeenCalledTimes(2); - expect(spyOnCreateSignalIndex).toHaveBeenCalledTimes(1); + await waitFor(() => { + expect(spyOnGetSignalIndex).toHaveBeenCalledTimes(2); + expect(spyOnCreateSignalIndex).toHaveBeenCalledTimes(1); + }); }); }); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx index 7fed5e84b5320..4453209de741f 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ import type { PropsWithChildren } from 'react'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { TestProvidersWithPrivileges } from '../../../../common/mock'; import type { ReturnSignalIndex } from './use_signal_index'; import { useSignalIndex } from './use_signal_index'; @@ -31,88 +32,78 @@ describe('useSignalIndex', () => { }); test('init', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook, ReturnSignalIndex>( - () => useSignalIndex(), - { - wrapper: TestProvidersWithPrivileges, - } - ); - await waitForNextUpdate(); + const { result } = renderHook(() => useSignalIndex(), { + wrapper: TestProvidersWithPrivileges, + }); + + await waitFor(() => expect(result.current).toEqual({ createDeSignalIndex: null, loading: true, signalIndexExists: null, signalIndexName: null, signalIndexMappingOutdated: null, - }); - }); + }) + ); }); test('fetch alerts info', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook, ReturnSignalIndex>( - () => useSignalIndex(), - { - wrapper: TestProvidersWithPrivileges, - } - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - createDeSignalIndex: result.current.createDeSignalIndex, - loading: false, - signalIndexExists: true, - signalIndexName: 'mock-signal-index', - signalIndexMappingOutdated: false, - }); + const { result } = renderHook, ReturnSignalIndex>( + () => useSignalIndex(), + { + wrapper: TestProvidersWithPrivileges, + } + ); + + await waitFor(() => expect(result.current.loading).toBe(false)); + + expect(result.current).toEqual({ + createDeSignalIndex: result.current.createDeSignalIndex, + loading: false, + signalIndexExists: true, + signalIndexName: 'mock-signal-index', + signalIndexMappingOutdated: false, }); }); test('make sure that createSignalIndex is giving back the signal info', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook, ReturnSignalIndex>( - () => useSignalIndex(), - { - wrapper: TestProvidersWithPrivileges, - } - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - await waitForNextUpdate(); - if (result.current.createDeSignalIndex != null) { - await result.current.createDeSignalIndex(); + const { result } = renderHook, ReturnSignalIndex>( + () => useSignalIndex(), + { + wrapper: TestProvidersWithPrivileges, } - await waitForNextUpdate(); - expect(result.current).toEqual({ - createDeSignalIndex: result.current.createDeSignalIndex, - loading: false, - signalIndexExists: true, - signalIndexName: 'mock-signal-index', - signalIndexMappingOutdated: false, - }); + ); + await waitFor(() => expect(result.current.createDeSignalIndex).toBeDefined()); + + await act(async () => { + await result.current.createDeSignalIndex(); + }); + + expect(result.current).toEqual({ + createDeSignalIndex: result.current.createDeSignalIndex, + loading: false, + signalIndexExists: true, + signalIndexName: 'mock-signal-index', + signalIndexMappingOutdated: false, }); }); test('make sure that createSignalIndex have been called when trying to create signal index', async () => { const spyOnCreateSignalIndex = jest.spyOn(api, 'createSignalIndex'); - await act(async () => { - const { result, waitForNextUpdate } = renderHook, ReturnSignalIndex>( - () => useSignalIndex(), - { - wrapper: TestProvidersWithPrivileges, - } - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - await waitForNextUpdate(); - if (result.current.createDeSignalIndex != null) { - await result.current.createDeSignalIndex(); + + const { result } = renderHook, ReturnSignalIndex>( + () => useSignalIndex(), + { + wrapper: TestProvidersWithPrivileges, } - await waitForNextUpdate(); - expect(spyOnCreateSignalIndex).toHaveBeenCalledTimes(1); + ); + await waitFor(() => expect(result.current.createDeSignalIndex).toBeDefined()); + + await act(async () => { + await result.current.createDeSignalIndex(); }); + + await waitFor(() => expect(spyOnCreateSignalIndex).toHaveBeenCalledTimes(1)); }); test('if there is an error during createSignalIndex, we should get back signalIndexExists === false && signalIndexName == null', async () => { @@ -120,26 +111,25 @@ describe('useSignalIndex', () => { spyOnCreateSignalIndex.mockImplementation(() => { throw new Error('Something went wrong, let see what happen'); }); - await act(async () => { - const { result, waitForNextUpdate } = renderHook, ReturnSignalIndex>( - () => useSignalIndex(), - { - wrapper: TestProvidersWithPrivileges, - } - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - await waitForNextUpdate(); - if (result.current.createDeSignalIndex != null) { - await result.current.createDeSignalIndex(); + const { result } = renderHook, ReturnSignalIndex>( + () => useSignalIndex(), + { + wrapper: TestProvidersWithPrivileges, } - expect(result.current).toEqual({ - createDeSignalIndex: result.current.createDeSignalIndex, - loading: false, - signalIndexExists: false, - signalIndexName: null, - signalIndexMappingOutdated: null, - }); + ); + + await waitFor(() => expect(result.current.createDeSignalIndex).toBeDefined()); + + await act(async () => { + await result.current.createDeSignalIndex(); + }); + + expect(result.current).toEqual({ + createDeSignalIndex: result.current.createDeSignalIndex, + loading: false, + signalIndexExists: false, + signalIndexName: null, + signalIndexMappingOutdated: null, }); }); @@ -148,23 +138,25 @@ describe('useSignalIndex', () => { spyOnGetSignalIndex.mockImplementation(() => { throw new Error('Something went wrong, let see what happen'); }); + const { result } = renderHook, ReturnSignalIndex>( + () => useSignalIndex(), + { + wrapper: TestProvidersWithPrivileges, + } + ); + + await waitFor(() => expect(result.current.createDeSignalIndex).toBeDefined()); + await act(async () => { - const { result, waitForNextUpdate } = renderHook, ReturnSignalIndex>( - () => useSignalIndex(), - { - wrapper: TestProvidersWithPrivileges, - } - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(result.current).toEqual({ - createDeSignalIndex: result.current.createDeSignalIndex, - loading: false, - signalIndexExists: false, - signalIndexName: null, - signalIndexMappingOutdated: null, - }); + await result.current.createDeSignalIndex(); + }); + + expect(result.current).toEqual({ + createDeSignalIndex: result.current.createDeSignalIndex, + loading: false, + signalIndexExists: false, + signalIndexName: null, + signalIndexMappingOutdated: null, }); }); @@ -175,24 +167,21 @@ describe('useSignalIndex', () => { .mockReturnValue('mock-signal-index-from-sourcerer'); jest.spyOn(sourcererSelectors, 'signalIndexMappingOutdated').mockReturnValue(false); - await act(async () => { - const { result, waitForNextUpdate } = renderHook, ReturnSignalIndex>( - () => useSignalIndex(), - { - wrapper: TestProvidersWithPrivileges, - } - ); - await waitForNextUpdate(); - await waitForNextUpdate(); - await waitForNextUpdate(); - expect(spyOnGetSignalIndex).not.toHaveBeenCalled(); - expect(result.current).toEqual({ - createDeSignalIndex: result.current.createDeSignalIndex, - loading: false, - signalIndexExists: true, - signalIndexName: 'mock-signal-index-from-sourcerer', - signalIndexMappingOutdated: false, - }); + const { result } = renderHook, ReturnSignalIndex>( + () => useSignalIndex(), + { + wrapper: TestProvidersWithPrivileges, + } + ); + + await waitFor(() => expect(spyOnGetSignalIndex).not.toHaveBeenCalled()); + + expect(result.current).toEqual({ + createDeSignalIndex: result.current.createDeSignalIndex, + loading: false, + signalIndexExists: true, + signalIndexName: 'mock-signal-index-from-sourcerer', + signalIndexMappingOutdated: false, }); }); }); diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/console_manager/integration_tests/console_manager.test.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/console_manager/integration_tests/console_manager.test.tsx index 8cf7b94f9bcd8..7f0d3597c9fd2 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/console_manager/integration_tests/console_manager.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/console_manager/integration_tests/console_manager.test.tsx @@ -6,7 +6,7 @@ */ import type { RenderHookResult } from '@testing-library/react-hooks'; -import { renderHook as _renderHook, act } from '@testing-library/react-hooks'; +import { renderHook as _renderHook, act, waitFor } from '@testing-library/react-hooks'; import { useConsoleManager } from '../console_manager'; import React from 'react'; import type { @@ -179,26 +179,20 @@ describe('When using ConsoleManager', () => { it('should display the console when `.show()` is called', async () => { registeredConsole.show(); - await renderResult.waitForNextUpdate(); - - expect(registeredConsole.isVisible()).toBe(true); + await waitFor(() => expect(registeredConsole.isVisible()).toBe(true)); }); it('should hide the console when `.hide()` is called', async () => { registeredConsole.show(); - await renderResult.waitForNextUpdate(); - expect(registeredConsole.isVisible()).toBe(true); + await waitFor(() => expect(registeredConsole.isVisible()).toBe(true)); registeredConsole.hide(); - await renderResult.waitForNextUpdate(); - expect(registeredConsole.isVisible()).toBe(false); + await waitFor(() => expect(registeredConsole.isVisible()).toBe(false)); }); it('should un-register the console when `.terminate() is called', async () => { registeredConsole.terminate(); - await renderResult.waitForNextUpdate(); - - expect(renderResult.result.current.getOne(consoleId)).toBeUndefined(); + await waitFor(() => expect(renderResult.result.current.getOne(consoleId)).toBeUndefined()); }); }); }); diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/use_cases_by_status.test.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/use_cases_by_status.test.tsx index 5821dd349749d..02bf34a39bc42 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/use_cases_by_status.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/use_cases_by_status.test.tsx @@ -6,7 +6,8 @@ */ import type { PropsWithChildren } from 'react'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { mockCasesContract } from '@kbn/cases-plugin/public/mocks'; import { useKibana } from '../../../../common/lib/kibana'; import { TestProviders } from '../../../../common/mock'; @@ -81,13 +82,13 @@ describe('useCasesByStatus', () => { }); test('fetch data', async () => { - const { result, waitForNextUpdate } = renderHook< + const { result } = renderHook< PropsWithChildren, UseCasesByStatusResults >(() => useCasesByStatus({ skip: false }), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => expect(result.current.isLoading).toBe(false)); expect(result.current).toEqual({ closed: 3, inProgress: 2, @@ -99,24 +100,23 @@ describe('useCasesByStatus', () => { }); test('it should call setQuery when fetching', async () => { - const { waitForNextUpdate } = renderHook< - PropsWithChildren, - UseCasesByStatusResults - >(() => useCasesByStatus({ skip: false }), { - wrapper: TestProviders, - }); - await waitForNextUpdate(); - expect(mockSetQuery).toHaveBeenCalled(); + renderHook, UseCasesByStatusResults>( + () => useCasesByStatus({ skip: false }), + { + wrapper: TestProviders, + } + ); + await waitFor(() => expect(mockSetQuery).toHaveBeenCalled()); }); test('it should call deleteQuery when unmounting', async () => { - const { waitForNextUpdate, unmount } = renderHook< + const { unmount } = renderHook< PropsWithChildren, UseCasesByStatusResults >(() => useCasesByStatus({ skip: false }), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => null); unmount(); @@ -127,13 +127,13 @@ describe('useCasesByStatus', () => { const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); const localProps = { skip: false }; - const { rerender, waitForNextUpdate } = renderHook< + const { rerender } = renderHook< PropsWithChildren, UseCasesByStatusResults >(() => useCasesByStatus(localProps), { wrapper: TestProviders, }); - await waitForNextUpdate(); + await waitFor(() => null); localProps.skip = true; act(() => rerender()); diff --git a/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.test.tsx index 67094a18cf327..03892b101d443 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { render, act } from '@testing-library/react'; +import { render, act, waitFor } from '@testing-library/react'; import type { Store } from 'redux'; import type { UseFieldBrowserOptionsProps, UseFieldBrowserOptions, FieldEditorActionsRef } from '.'; import { useFieldBrowserOptions } from '.'; @@ -76,7 +76,7 @@ const renderUpdatedUseFieldBrowserOptions = async ( > | null = null; await act(async () => { renderHookResult = renderUseFieldBrowserOptions(props); - await renderHookResult.waitForNextUpdate(); + await waitFor(() => null); }); return renderHookResult!; }; diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx index df4d64e5be133..ffa30f08ec809 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx @@ -31,12 +31,14 @@ jest.mock('../../../common/components/link_to', () => { }; }); +const mockNavigateToUrl = jest.fn(); + jest.mock('@kbn/kibana-react-plugin/public', () => { const originalModule = jest.requireActual('@kbn/kibana-react-plugin/public'); const useKibana = jest.fn().mockImplementation(() => ({ services: { application: { - navigateToUrl: jest.fn(), + navigateToUrl: mockNavigateToUrl, }, }, })); @@ -48,6 +50,10 @@ jest.mock('@kbn/kibana-react-plugin/public', () => { }); describe('useTimelineTypes', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + it('init', async () => { const { result } = renderHook( () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), @@ -55,7 +61,7 @@ describe('useTimelineTypes', () => { wrapper: TestProviders, } ); - await waitFor(() => null); + expect(result.current).toEqual({ timelineType: 'default', timelineTabs: result.current.timelineTabs, @@ -73,13 +79,9 @@ describe('useTimelineTypes', () => { ); await waitFor(() => null); - const { container } = render(result.current.timelineTabs); - expect(container.querySelector('[data-test-subj="timeline-tab-default"]')).toHaveTextContent( - 'Timelines' - ); - expect(container.querySelector('[data-test-subj="timeline-tab-template"]')).toHaveTextContent( - 'Templates' - ); + render(result.current.timelineTabs); + expect(screen.getByTestId('timeline-tab-default')).toHaveTextContent('Timelines'); + expect(screen.getByTestId('timeline-tab-template')).toHaveTextContent('Templates'); }); it('set timelineTypes correctly', async () => { @@ -104,14 +106,7 @@ describe('useTimelineTypes', () => { ); }); - await waitFor(() => expect(result.current.timelineType).toEqual('template')); - - expect(result.current).toEqual( - expect.objectContaining({ - timelineTabs: result.current.timelineTabs, - timelineFilters: result.current.timelineFilters, - }) - ); + expect(mockNavigateToUrl).toHaveBeenCalled(); }); it('stays in the same tab if clicking again on current tab', async () => { @@ -125,15 +120,13 @@ describe('useTimelineTypes', () => { const { container } = render(result.current.timelineTabs); - act(() => { - fireEvent( - container.querySelector('[data-test-subj="timeline-tab-default"]')!, - new MouseEvent('click', { - bubbles: true, - cancelable: true, - }) - ); - }); + fireEvent( + screen.getByTestId('timeline-tab-default'), + new MouseEvent('click', { + bubbles: true, + cancelable: true, + }) + ); waitFor(() => null); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_notes_in_flyout.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_notes_in_flyout.test.tsx index 81c9f1febdeb5..b6d4ec9c05265 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_notes_in_flyout.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_notes_in_flyout.test.tsx @@ -7,7 +7,8 @@ import React from 'react'; import { TimelineId, TimelineTabs } from '../../../../../common/types'; -import { renderHook, act, waitFor } from '@testing-library/react'; +import { act, waitFor } from '@testing-library/react'; +import { renderHook } from '@testing-library/react-hooks'; import { createMockStore, mockGlobalState, TestProviders } from '../../../../common/mock'; import type { UseNotesInFlyoutArgs } from './use_notes_in_flyout'; import { useNotesInFlyout } from './use_notes_in_flyout'; diff --git a/x-pack/plugins/transform/public/app/hooks/use_index_data.test.tsx b/x-pack/plugins/transform/public/app/hooks/use_index_data.test.tsx index 37e8096f355ed..c9c5083002b04 100644 --- a/x-pack/plugins/transform/public/app/hooks/use_index_data.test.tsx +++ b/x-pack/plugins/transform/public/app/hooks/use_index_data.test.tsx @@ -78,7 +78,7 @@ describe('Transform: useIndexData()', () => { ); - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => useIndexData({ dataView: { @@ -108,7 +108,7 @@ describe('Transform: useIndexData()', () => { const IndexObj: UseIndexDataReturnType = result.current; - await waitForNextUpdate(); + await waitFor(() => null); expect(IndexObj.errorMessage).toBe(''); expect(IndexObj.status).toBe(INDEX_STATUS.LOADING); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.test.tsx index 06050b25040d0..2af0906ab4632 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ import React from 'react'; -import { renderHook, waitFor } from '@testing-library/react'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useLoadRulesQuery as useLoadRules } from './use_load_rules_query'; import { RuleExecutionStatusErrorReasons, From bab99425f3830079197696f43a7a8beb9acd5015 Mon Sep 17 00:00:00 2001 From: Eyo Okon Eyo Date: Thu, 10 Oct 2024 09:28:09 +0100 Subject: [PATCH 06/18] fix sourcerer --- ...use_data_grid_column_cell_actions.test.tsx | 10 +- .../index.test.ts | 243 +++++++----------- .../use_delete_knowledge_base.test.tsx | 4 +- .../assistant/use_conversation/index.test.tsx | 8 +- .../configure/use_action_types.test.tsx | 4 +- ...t_supported_action_connectors.tsx.test.tsx | 14 +- .../use_delete_file_attachment.test.tsx | 19 +- .../use_get_action_license.test.tsx | 4 +- .../use_get_case_user_actions_stats.test.tsx | 14 +- .../containers/use_get_case_users.test.tsx | 8 +- .../public/containers/use_get_tags.test.tsx | 3 +- ...e_infinite_find_case_user_actions.test.tsx | 21 +- .../hooks/use_agent_soft_limit.test.tsx | 16 +- .../hooks/use_fetch_agents_data.test.tsx | 12 +- .../hooks/use_fleet_server_unhealthy.test.tsx | 13 +- .../hooks/persist_exception_item.test.ts | 51 ++-- .../hooks/use_metrics_explorer_data.test.tsx | 8 +- .../public/hooks/use_fetch_alert_data.test.ts | 52 ++-- .../hooks/use_locations_api.test.tsx | 46 ++-- .../public/assistant/overlay.test.tsx | 9 +- .../hooks/use_installed_security_jobs.test.ts | 10 +- .../common/hooks/use_fetch/use_fetch.test.tsx | 50 ++-- .../utils/global_query_string/index.test.tsx | 10 +- .../alerts/use_query.test.tsx | 59 +++-- .../hooks/use_critical_alerts.test.tsx | 232 +++++++++-------- .../sourcerer/containers/hooks.test.tsx | 53 ++-- .../open_timeline/use_timeline_types.test.tsx | 2 +- .../hooks/use_load_rule_aggregations.test.tsx | 51 ++-- .../application/hooks/use_load_rules.test.tsx | 59 ++--- .../use_bulk_get_maintenance_windows.test.ts | 4 +- 30 files changed, 517 insertions(+), 572 deletions(-) diff --git a/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.test.tsx b/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.test.tsx index 6459a38310fc3..30afebb0b98a4 100644 --- a/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.test.tsx +++ b/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.test.tsx @@ -78,10 +78,10 @@ describe('useDataGridColumnsCellActions', () => { expect(result.current).toHaveLength(0); - await waitFor(() => null); - - expect(result.current).toHaveLength(columns.length); - expect(result.current[0]).toHaveLength(actions.length); + await waitFor(() => { + expect(result.current).toHaveLength(columns.length); + expect(result.current[0]).toHaveLength(actions.length); + }); }); it('should call getCellValue with the proper params', async () => { @@ -131,7 +131,7 @@ describe('useDataGridColumnsCellActions', () => { cellAction.getByTestId(`dataGridColumnCellAction-${action1.id}`).click(); - waitFor(() => { + await waitFor(() => { expect(action1.execute).toHaveBeenCalled(); }); }); diff --git a/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts b/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts index 5e101e4ceb51c..10c99b3d6f2c2 100644 --- a/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts +++ b/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react-hooks'; import { waitFor } from '@testing-library/react'; import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; @@ -47,11 +47,8 @@ describe('use_field_value_autocomplete', () => { }); test('initializes hook', async () => { - await act(async () => { - const { result } = renderHook< - UseFieldValueAutocompleteProps, - UseFieldValueAutocompleteReturn - >(() => + const { result } = renderHook( + () => useFieldValueAutocomplete({ autocompleteService: { ...autocompleteStartMock, @@ -63,19 +60,13 @@ describe('use_field_value_autocomplete', () => { query: '', selectedField: undefined, }) - ); - await waitFor(() => null); - - expect(result.current).toEqual([false, true, [], result.current[3]]); - }); + ); + await waitFor(() => expect(result.current).toEqual([false, true, [], result.current[3]])); }); test('does not call autocomplete service if "operatorType" is "exists"', async () => { - await act(async () => { - const { result } = renderHook< - UseFieldValueAutocompleteProps, - UseFieldValueAutocompleteReturn - >(() => + const { result } = renderHook( + () => useFieldValueAutocomplete({ autocompleteService: { ...autocompleteStartMock, @@ -87,22 +78,18 @@ describe('use_field_value_autocomplete', () => { query: '', selectedField: getField('machine.os'), }) - ); - await waitFor(() => null); + ); + + const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; - const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; + await waitFor(() => expect(getValueSuggestionsMock).not.toHaveBeenCalled()); - expect(getValueSuggestionsMock).not.toHaveBeenCalled(); - expect(result.current).toEqual(expectedResult); - }); + expect(result.current).toEqual(expectedResult); }); test('does not call autocomplete service if "selectedField" is undefined', async () => { - await act(async () => { - const { result } = renderHook< - UseFieldValueAutocompleteProps, - UseFieldValueAutocompleteReturn - >(() => + const { result } = renderHook( + () => useFieldValueAutocomplete({ autocompleteService: { ...autocompleteStartMock, @@ -114,22 +101,17 @@ describe('use_field_value_autocomplete', () => { query: '', selectedField: undefined, }) - ); - await waitFor(() => null); + ); - const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; + const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; + await waitFor(() => expect(getValueSuggestionsMock).not.toHaveBeenCalled()); - expect(getValueSuggestionsMock).not.toHaveBeenCalled(); - expect(result.current).toEqual(expectedResult); - }); + expect(result.current).toEqual(expectedResult); }); test('does not call autocomplete service if "indexPattern" is undefined', async () => { - await act(async () => { - const { result } = renderHook< - UseFieldValueAutocompleteProps, - UseFieldValueAutocompleteReturn - >(() => + const { result } = renderHook( + () => useFieldValueAutocomplete({ autocompleteService: { ...autocompleteStartMock, @@ -141,42 +123,38 @@ describe('use_field_value_autocomplete', () => { query: '', selectedField: getField('machine.os'), }) - ); - await waitFor(() => null); + ); - const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; + const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; - expect(getValueSuggestionsMock).not.toHaveBeenCalled(); - expect(result.current).toEqual(expectedResult); - }); + await waitFor(() => expect(getValueSuggestionsMock).not.toHaveBeenCalled()); + expect(result.current).toEqual(expectedResult); }); test('it uses full path name for nested fields to fetch suggestions', async () => { const suggestionsMock = jest.fn().mockResolvedValue([]); - await act(async () => { - const selectedField: DataViewFieldBase | undefined = getField('nestedField.child'); - if (selectedField == null) { - throw new TypeError('selectedField for this test should always be defined'); - } - - const { signal } = new AbortController(); - renderHook(() => - useFieldValueAutocomplete({ - autocompleteService: { - ...autocompleteStartMock, - getValueSuggestions: suggestionsMock, - }, - fieldValue: '', - indexPattern: stubIndexPatternWithFields, - operatorType: OperatorTypeEnum.MATCH, - query: '', - selectedField: { ...selectedField, name: 'child' }, - }) - ); - // Note: initial `waitFor` is hook initialization - await waitFor(() => null); + const selectedField: DataViewFieldBase | undefined = getField('nestedField.child'); + if (selectedField == null) { + throw new TypeError('selectedField for this test should always be defined'); + } + + const { signal } = new AbortController(); + renderHook(() => + useFieldValueAutocomplete({ + autocompleteService: { + ...autocompleteStartMock, + getValueSuggestions: suggestionsMock, + }, + fieldValue: '', + indexPattern: stubIndexPatternWithFields, + operatorType: OperatorTypeEnum.MATCH, + query: '', + selectedField: { ...selectedField, name: 'child' }, + }) + ); + await waitFor(() => expect(suggestionsMock).toHaveBeenCalledWith({ field: { ...getField('nestedField.child'), name: 'nestedField.child' }, indexPattern: { @@ -196,16 +174,13 @@ describe('use_field_value_autocomplete', () => { query: '', signal, useTimeRange: false, - }); - }); + }) + ); }); test('returns "isSuggestingValues" of false if field type is boolean', async () => { - await act(async () => { - const { result } = renderHook< - UseFieldValueAutocompleteProps, - UseFieldValueAutocompleteReturn - >(() => + const { result } = renderHook( + () => useFieldValueAutocomplete({ autocompleteService: { ...autocompleteStartMock, @@ -217,25 +192,19 @@ describe('use_field_value_autocomplete', () => { query: '', selectedField: getField('ssl'), }) - ); - - await waitFor(() => null); + ); - const expectedResult: UseFieldValueAutocompleteReturn = [false, false, [], result.current[3]]; + const expectedResult: UseFieldValueAutocompleteReturn = [false, false, [], result.current[3]]; + await waitFor(() => expect(getValueSuggestionsMock).not.toHaveBeenCalled()); - expect(getValueSuggestionsMock).not.toHaveBeenCalled(); - expect(result.current).toEqual(expectedResult); - }); + expect(result.current).toEqual(expectedResult); }); test('returns "isSuggestingValues" of false to note that autocomplete service is not in use if no autocomplete suggestions available', async () => { const suggestionsMock = jest.fn().mockResolvedValue([]); - await act(async () => { - const { result } = renderHook< - UseFieldValueAutocompleteProps, - UseFieldValueAutocompleteReturn - >(() => + const { result } = renderHook( + () => useFieldValueAutocomplete({ autocompleteService: { ...autocompleteStartMock, @@ -247,24 +216,18 @@ describe('use_field_value_autocomplete', () => { query: '', selectedField: getField('bytes'), }) - ); - - await waitFor(() => null); + ); - const expectedResult: UseFieldValueAutocompleteReturn = [false, false, [], result.current[3]]; + const expectedResult: UseFieldValueAutocompleteReturn = [false, false, [], result.current[3]]; - expect(suggestionsMock).toHaveBeenCalled(); - expect(result.current).toEqual(expectedResult); - }); + await waitFor(() => expect(suggestionsMock).toHaveBeenCalled()); + expect(result.current).toEqual(expectedResult); }); test('returns suggestions', async () => { - await act(async () => { - const { signal } = new AbortController(); - const { result } = renderHook< - UseFieldValueAutocompleteProps, - UseFieldValueAutocompleteReturn - >(() => + const { signal } = new AbortController(); + const { result } = renderHook( + () => useFieldValueAutocomplete({ autocompleteService: { ...autocompleteStartMock, @@ -276,33 +239,31 @@ describe('use_field_value_autocomplete', () => { query: '', selectedField: getField('@tags'), }) - ); - await waitFor(() => null); + ); - const expectedResult: UseFieldValueAutocompleteReturn = [ - false, - true, - ['value 1', 'value 2'], - result.current[3], - ]; + const expectedResult: UseFieldValueAutocompleteReturn = [ + false, + true, + ['value 1', 'value 2'], + result.current[3], + ]; + await waitFor(() => expect(getValueSuggestionsMock).toHaveBeenCalledWith({ field: getField('@tags'), indexPattern: stubIndexPatternWithFields, query: '', signal, useTimeRange: false, - }); - expect(result.current).toEqual(expectedResult); - }); + }) + ); + + expect(result.current).toEqual(expectedResult); }); test('returns new suggestions on subsequent calls', async () => { - await act(async () => { - const { result } = renderHook< - UseFieldValueAutocompleteProps, - UseFieldValueAutocompleteReturn - >(() => + const { result } = renderHook( + () => useFieldValueAutocomplete({ autocompleteService: { ...autocompleteStartMock, @@ -314,34 +275,30 @@ describe('use_field_value_autocomplete', () => { query: '', selectedField: getField('@tags'), }) - ); - - await waitFor(() => null); - - expect(result.current[3]).not.toBeNull(); - - // Added check for typescripts sake, if null, - // would not reach below logic as test would stop above - if (result.current[3] != null) { - result.current[3]({ - fieldSelected: getField('@tags'), - patterns: stubIndexPatternWithFields, - searchQuery: '', - value: 'hello', - }); - } - - await waitFor(() => null); - - const expectedResult: UseFieldValueAutocompleteReturn = [ - false, - true, - ['value 1', 'value 2'], - result.current[3], - ]; - - expect(getValueSuggestionsMock).toHaveBeenCalledTimes(2); - expect(result.current).toEqual(expectedResult); - }); + ); + + await waitFor(() => expect(result.current[3]).not.toBeNull()); + + // Added check for typescripts sake, if null, + // would not reach below logic as test would stop above + if (result.current[3] != null) { + result.current[3]({ + fieldSelected: getField('@tags'), + patterns: stubIndexPatternWithFields, + searchQuery: '', + value: 'hello', + }); + } + + const expectedResult: UseFieldValueAutocompleteReturn = [ + false, + true, + ['value 1', 'value 2'], + result.current[3], + ]; + + await waitFor(() => expect(getValueSuggestionsMock).toHaveBeenCalledTimes(2)); + + expect(result.current).toEqual(expectedResult); }); }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.test.tsx index 31fd23e950764..1428eb322871d 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/api/knowledge_base/use_delete_knowledge_base.test.tsx @@ -89,9 +89,7 @@ describe('useDeleteKnowledgeBase', () => { it('should return delete response', async () => { const { result } = renderHook(() => useDeleteKnowledgeBase(defaultProps)); - await waitFor(() => null); - - await expect(result.current).resolves.toStrictEqual(statusResponse); + await waitFor(async () => expect(result.current).resolves.toStrictEqual(statusResponse)); }); it('should display error toast when api throws error', async () => { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.test.tsx index 4fc8e64ca8525..6cabb7aa2f46c 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.test.tsx @@ -67,7 +67,7 @@ describe('useConversation', () => { let createResult; - act(async () => { + await act(async () => { createResult = await result.current.createConversation({ ...mockConvo, replacements: {}, @@ -88,7 +88,7 @@ describe('useConversation', () => { await waitFor(() => null); - act(async () => { + await act(async () => { await result.current.deleteConversation('new-convo'); }); @@ -106,7 +106,7 @@ describe('useConversation', () => { }); await waitFor(() => null); - act(async () => { + await act(async () => { await result.current.setApiConfig({ conversation: WELCOME_CONVERSATION, apiConfig: mockConvo.apiConfig, @@ -131,7 +131,7 @@ describe('useConversation', () => { let removeResult; - act(async () => { + await act(async () => { removeResult = await result.current.removeLastMessage('new-convo'); }); diff --git a/x-pack/plugins/cases/public/containers/configure/use_action_types.test.tsx b/x-pack/plugins/cases/public/containers/configure/use_action_types.test.tsx index 01f2585ec3818..06c0a3c4fe793 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_action_types.test.tsx +++ b/x-pack/plugins/cases/public/containers/configure/use_action_types.test.tsx @@ -47,7 +47,7 @@ describe('useActionTypes', () => { renderHook(() => useGetActionTypes(), { wrapper: appMockRenderer.AppWrapper, }); - await waitFor(() => null, { timeout: 2000 }); - expect(addErrorMock).toHaveBeenCalled(); + + await waitFor(() => expect(addErrorMock).toHaveBeenCalled()); }); }); diff --git a/x-pack/plugins/cases/public/containers/configure/use_get_supported_action_connectors.tsx.test.tsx b/x-pack/plugins/cases/public/containers/configure/use_get_supported_action_connectors.tsx.test.tsx index cebbd3bb5c924..d28054396665e 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_get_supported_action_connectors.tsx.test.tsx +++ b/x-pack/plugins/cases/public/containers/configure/use_get_supported_action_connectors.tsx.test.tsx @@ -31,9 +31,7 @@ describe('useConnectors', () => { wrapper: ({ children }) => {children}, }); - await waitFor(() => null); - - expect(spy).toHaveBeenCalledWith({ signal: expect.any(AbortSignal) }); + await waitFor(() => expect(spy).toHaveBeenCalledWith({ signal: expect.any(AbortSignal) })); }); it('shows a toast error when the API returns error', async () => { @@ -48,9 +46,8 @@ describe('useConnectors', () => { renderHook(() => useGetSupportedActionConnectors(), { wrapper: ({ children }) => {children}, }); - await waitFor(() => null); - expect(addError).toHaveBeenCalled(); + await waitFor(() => expect(addError).toHaveBeenCalled()); }); it('does not fetch connectors when the user does not has access to actions', async () => { @@ -61,9 +58,7 @@ describe('useConnectors', () => { wrapper: ({ children }) => {children}, }); - await waitFor(() => null); - - expect(spyOnFetchConnectors).not.toHaveBeenCalled(); + await waitFor(() => expect(spyOnFetchConnectors).not.toHaveBeenCalled()); expect(result.current.data).toEqual([]); }); @@ -77,9 +72,8 @@ describe('useConnectors', () => { ), }); - await waitFor(() => null); + await waitFor(() => expect(spyOnFetchConnectors).not.toHaveBeenCalled()); - expect(spyOnFetchConnectors).not.toHaveBeenCalled(); expect(result.current.data).toEqual([]); }); }); diff --git a/x-pack/plugins/cases/public/containers/use_delete_file_attachment.test.tsx b/x-pack/plugins/cases/public/containers/use_delete_file_attachment.test.tsx index fc6749ffc999a..a8c66993f6c44 100644 --- a/x-pack/plugins/cases/public/containers/use_delete_file_attachment.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_delete_file_attachment.test.tsx @@ -66,9 +66,7 @@ describe('useDeleteFileAttachment', () => { }) ); - await waitFor(() => null); - - expect(useRefreshCaseViewPage()).toBeCalled(); + await waitFor(() => expect(useRefreshCaseViewPage()).toBeCalled()); }); it('shows a success toaster correctly', async () => { @@ -83,12 +81,12 @@ describe('useDeleteFileAttachment', () => { }) ); - await waitFor(() => null); - - expect(addSuccess).toHaveBeenCalledWith({ - title: 'File deleted successfully', - className: 'eui-textBreakWord', - }); + await waitFor(() => + expect(addSuccess).toHaveBeenCalledWith({ + title: 'File deleted successfully', + className: 'eui-textBreakWord', + }) + ); }); it('sets isError when fails to delete a file attachment', async () => { @@ -106,7 +104,7 @@ describe('useDeleteFileAttachment', () => { }) ); - await waitFor(() => null); + await waitFor(() => expect(result.current.isError).toBe(true)); expect(spyOnDeleteFileAttachments).toBeCalledWith({ caseId: basicCaseId, @@ -114,6 +112,5 @@ describe('useDeleteFileAttachment', () => { }); expect(addError).toHaveBeenCalled(); - expect(result.current.isError).toBe(true); }); }); diff --git a/x-pack/plugins/cases/public/containers/use_get_action_license.test.tsx b/x-pack/plugins/cases/public/containers/use_get_action_license.test.tsx index d708164ac1171..c9edc2ab354dd 100644 --- a/x-pack/plugins/cases/public/containers/use_get_action_license.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_action_license.test.tsx @@ -46,8 +46,6 @@ describe('useGetActionLicense', () => { renderHook(() => useGetActionLicense(), { wrapper: appMockRenderer.AppWrapper, }); - await waitFor(() => null); - - expect(addError).toHaveBeenCalled(); + await waitFor(() => expect(addError).toHaveBeenCalled()); }); }); diff --git a/x-pack/plugins/cases/public/containers/use_get_case_user_actions_stats.test.tsx b/x-pack/plugins/cases/public/containers/use_get_case_user_actions_stats.test.tsx index 9a2b14527ff87..50e4cf7c9ecb8 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_user_actions_stats.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_user_actions_stats.test.tsx @@ -37,7 +37,7 @@ describe('useGetCaseUserActionsStats', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); + await waitFor(() => expect(result.current.isLoading).toBe(false)); expect(result.current).toEqual( expect.objectContaining({ @@ -66,10 +66,10 @@ describe('useGetCaseUserActionsStats', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - - expect(spy).toHaveBeenCalledWith(basicCase.id, expect.any(AbortSignal)); - expect(addError).toHaveBeenCalled(); + await waitFor(() => { + expect(spy).toHaveBeenCalledWith(basicCase.id, expect.any(AbortSignal)); + expect(addError).toHaveBeenCalled(); + }); }); it('calls the api when invoked with the correct parameters', async () => { @@ -79,8 +79,6 @@ describe('useGetCaseUserActionsStats', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - - expect(spy).toHaveBeenCalledWith(basicCase.id, expect.any(AbortSignal)); + await waitFor(() => expect(spy).toHaveBeenCalledWith(basicCase.id, expect.any(AbortSignal))); }); }); diff --git a/x-pack/plugins/cases/public/containers/use_get_case_users.test.tsx b/x-pack/plugins/cases/public/containers/use_get_case_users.test.tsx index 39d8bb21207ba..659b7723ce5e5 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_users.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_users.test.tsx @@ -45,9 +45,9 @@ describe('useGetCaseUsers', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - - expect(spy).toHaveBeenCalledWith({ caseId: 'case-1', signal: expect.any(AbortSignal) }); - expect(addError).toHaveBeenCalled(); + await waitFor(() => { + expect(spy).toHaveBeenCalledWith({ caseId: 'case-1', signal: expect.any(AbortSignal) }); + expect(addError).toHaveBeenCalled(); + }); }); }); diff --git a/x-pack/plugins/cases/public/containers/use_get_tags.test.tsx b/x-pack/plugins/cases/public/containers/use_get_tags.test.tsx index 60205588e807d..7d388fc0bde74 100644 --- a/x-pack/plugins/cases/public/containers/use_get_tags.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_tags.test.tsx @@ -45,7 +45,6 @@ describe('useGetTags', () => { renderHook(() => useGetTags(), { wrapper: ({ children }) => {children}, }); - await waitFor(() => null); - expect(addError).toBeCalled(); + await waitFor(() => expect(addError).toBeCalled()); }); }); diff --git a/x-pack/plugins/cases/public/containers/use_infinite_find_case_user_actions.test.tsx b/x-pack/plugins/cases/public/containers/use_infinite_find_case_user_actions.test.tsx index a6dff220fa1eb..d57614507cdd3 100644 --- a/x-pack/plugins/cases/public/containers/use_infinite_find_case_user_actions.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_infinite_find_case_user_actions.test.tsx @@ -48,7 +48,7 @@ describe('UseInfiniteFindCaseUserActions', () => { { wrapper: appMockRender.AppWrapper } ); - await waitFor(() => null); + await waitFor(() => expect(result.current.isLoading).toBe(false)); expect(result.current).toEqual( expect.objectContaining({ @@ -127,14 +127,15 @@ describe('UseInfiniteFindCaseUserActions', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); + await waitFor(() => { + expect(spy).toHaveBeenCalledWith( + basicCase.id, + { type: filterActionType, sortOrder, page: 1, perPage: 10 }, + expect.any(AbortSignal) + ); + expect(addError).toHaveBeenCalled(); + }); - expect(spy).toHaveBeenCalledWith( - basicCase.id, - { type: filterActionType, sortOrder, page: 1, perPage: 10 }, - expect.any(AbortSignal) - ); - expect(addError).toHaveBeenCalled(); spy.mockRestore(); }); @@ -146,7 +147,7 @@ describe('UseInfiniteFindCaseUserActions', () => { { wrapper: appMockRender.AppWrapper } ); - await waitFor(() => result.current.isSuccess); + await waitFor(() => expect(result.current.isSuccess).toBe(true)); expect(result.current.data?.pages).toStrictEqual([findCaseUserActionsResponse]); @@ -163,7 +164,7 @@ describe('UseInfiniteFindCaseUserActions', () => { expect.any(AbortSignal) ); }); - await waitFor(() => result.current.data?.pages.length === 2); + await waitFor(() => expect(result.current.data?.pages).toHaveLength(2)); }); it('returns hasNextPage correctly', async () => { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_agent_soft_limit.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_agent_soft_limit.test.tsx index d37f81ea79485..46c72c9c5213c 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_agent_soft_limit.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_agent_soft_limit.test.tsx @@ -38,10 +38,12 @@ describe('useAgentSoftLimit', () => { total: 5, }, } as any); - const { result } = renderer.renderHook(() => useAgentSoftLimit()); - await renderer.waitFor(() => null); + const { result, rerender } = renderer.renderHook(() => useAgentSoftLimit()); + await renderer.waitFor(() => expect(mockedSendGetAgents).toBeCalled()); + + // re-render so cache is updated to value from most recent call + rerender(); - expect(mockedSendGetAgents).toBeCalled(); expect(result.current.shouldDisplayAgentSoftLimit).toEqual(false); }); @@ -53,10 +55,12 @@ describe('useAgentSoftLimit', () => { total: 15, }, } as any); - const { result } = renderer.renderHook(() => useAgentSoftLimit()); - await renderer.waitFor(() => null); + const { result, rerender } = renderer.renderHook(() => useAgentSoftLimit()); + await renderer.waitFor(() => expect(mockedSendGetAgents).toBeCalled()); + + // re-render so cache is updated to value from most recent call + rerender(); - expect(mockedSendGetAgents).toBeCalled(); expect(result.current.shouldDisplayAgentSoftLimit).toEqual(true); }); }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_fetch_agents_data.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_fetch_agents_data.test.tsx index 6b8ca1702b79b..519c219977081 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_fetch_agents_data.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_fetch_agents_data.test.tsx @@ -155,26 +155,20 @@ describe('useFetchAgentsData', () => { const renderer = createFleetTestRendererMock(); const { result } = renderer.renderHook(() => useFetchAgentsData()); - await waitFor(() => null); - - expect(renderer.history.location.search).toEqual(''); + await waitFor(() => expect(renderer.history.location.search).toEqual('')); // Set search await act(async () => { result.current.setSearch('active:true'); }); - await waitFor(() => null); - - expect(renderer.history.location.search).toEqual('?kuery=active%3Atrue'); + await waitFor(() => expect(renderer.history.location.search).toEqual('?kuery=active%3Atrue')); // Clear search await act(async () => { result.current.setSearch(''); }); - await waitFor(() => null); - - expect(renderer.history.location.search).toEqual(''); + await waitFor(() => expect(renderer.history.location.search).toEqual('')); }); }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy.test.tsx index 34af261fde382..c4caa7e47c07b 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/hooks/use_fleet_server_unhealthy.test.tsx @@ -22,7 +22,7 @@ jest.mock('../../../../../hooks/use_authz', () => ({ describe('useFleetServerUnhealthy', () => { const testRenderer = createFleetTestRendererMock(); - it('should return isUnHealthy:false with an online fleet slerver', async () => { + it('should return isUnHealthy:false with an online fleet server', async () => { jest.mocked(sendGetEnrollmentSettings).mockResolvedValueOnce({ error: null, data: { @@ -47,12 +47,11 @@ describe('useFleetServerUnhealthy', () => { }); const { result } = testRenderer.renderHook(() => useFleetServerUnhealthy()); - await testRenderer.waitFor(() => null); - expect(result.current.isLoading).toBeFalsy(); + await testRenderer.waitFor(() => expect(result.current.isLoading).toBeFalsy()); expect(result.current.isUnhealthy).toBeFalsy(); }); - it('should return isUnHealthy:true with only one offline fleet slerver', async () => { + it('should return isUnHealthy:true with only one offline fleet server', async () => { jest.mocked(sendGetEnrollmentSettings).mockResolvedValue({ error: null, data: { @@ -63,8 +62,7 @@ describe('useFleetServerUnhealthy', () => { }, }); const { result } = testRenderer.renderHook(() => useFleetServerUnhealthy()); - await testRenderer.waitFor(() => null); - expect(result.current.isLoading).toBeFalsy(); + await testRenderer.waitFor(() => expect(result.current.isLoading).toBeFalsy()); expect(result.current.isUnhealthy).toBeTruthy(); }); @@ -74,8 +72,7 @@ describe('useFleetServerUnhealthy', () => { data: null, }); const { result } = testRenderer.renderHook(() => useFleetServerUnhealthy()); - await testRenderer.waitFor(() => null); - expect(result.current.isLoading).toBeFalsy(); + await testRenderer.waitFor(() => expect(result.current.isLoading).toBeFalsy()); expect(result.current.isUnhealthy).toBeFalsy(); expect(testRenderer.startServices.notifications.toasts.addError).toBeCalled(); }); diff --git a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts b/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts index bb929609f8d95..7cbc3477c4a77 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts +++ b/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts @@ -52,10 +52,13 @@ describe('usePersistExceptionItem', () => { await act(async () => { result.current[1](getCreateExceptionListItemSchemaMock()); - rerender(); }); - expect(result.current).toEqual([{ isLoading: true, isSaved: false }, result.current[1]]); + rerender(); + + await waitFor(() => + expect(result.current).toEqual([{ isLoading: true, isSaved: false }, result.current[1]]) + ); }); test('"isSaved" is "true" when exception item saved successfully', async () => { @@ -67,7 +70,9 @@ describe('usePersistExceptionItem', () => { result.current[1](getCreateExceptionListItemSchemaMock()); }); - expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); + await waitFor(() => + expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]) + ); }); test('it invokes "updateExceptionListItem" when payload has "id"', async () => { @@ -86,14 +91,14 @@ describe('usePersistExceptionItem', () => { result.current[1]({ ...getUpdateExceptionListItemSchemaMock(), entries: ENTRIES_WITH_IDS }); }); - await waitFor(() => null); - - expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); - expect(addExceptionListItem).not.toHaveBeenCalled(); - expect(updateExceptionListItem).toHaveBeenCalledWith({ - http: mockKibanaHttpService, - listItem: getUpdateExceptionListItemSchemaMock(), - signal: new AbortController().signal, + await waitFor(() => { + expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); + expect(addExceptionListItem).not.toHaveBeenCalled(); + expect(updateExceptionListItem).toHaveBeenCalledWith({ + http: mockKibanaHttpService, + listItem: getUpdateExceptionListItemSchemaMock(), + signal: new AbortController().signal, + }); }); }); @@ -111,14 +116,14 @@ describe('usePersistExceptionItem', () => { // before the call goes through result.current[1]({ ...getCreateExceptionListItemSchemaMock(), entries: ENTRIES_WITH_IDS }); }); - await waitFor(() => null); - - expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); - expect(updateExceptionListItem).not.toHaveBeenCalled(); - expect(addExceptionListItem).toHaveBeenCalledWith({ - http: mockKibanaHttpService, - listItem: getCreateExceptionListItemSchemaMock(), - signal: new AbortController().signal, + await waitFor(() => { + expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); + expect(updateExceptionListItem).not.toHaveBeenCalled(); + expect(addExceptionListItem).toHaveBeenCalledWith({ + http: mockKibanaHttpService, + listItem: getCreateExceptionListItemSchemaMock(), + signal: new AbortController().signal, + }); }); }); @@ -133,9 +138,9 @@ describe('usePersistExceptionItem', () => { await act(async () => { result.current[1](getCreateExceptionListItemSchemaMock()); }); - await waitFor(() => null); - - expect(result.current).toEqual([{ isLoading: false, isSaved: false }, result.current[1]]); - expect(onError).toHaveBeenCalledWith(error); + await waitFor(() => { + expect(result.current).toEqual([{ isLoading: false, isSaved: false }, result.current[1]]); + expect(onError).toHaveBeenCalledWith(error); + }); }); }); diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.test.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.test.tsx index 2bc0d30af7a3a..404bdbde15acd 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.test.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.test.tsx @@ -136,8 +136,8 @@ describe('useMetricsExplorerData Hook', () => { pageInfo: { total: 10, afterKey: 'host-06' }, series: [createSeries('host-04'), createSeries('host-05'), createSeries('host-06')], } as any); - act(() => { - result.current.fetchNextPage(); + await act(async () => { + await result.current.fetchNextPage(); }); await waitFor(() => expect(result.current.isLoading).toBe(false)); const { series: nextSeries } = result.current.data!.pages[1]; @@ -156,8 +156,8 @@ describe('useMetricsExplorerData Hook', () => { expect(result.current.data).toBeUndefined(); expect(result.current.error).toEqual(error); mockedFetch.mockResolvedValue(resp as any); - act(() => { - result.current.refetch(); + await act(async () => { + await result.current.refetch(); }); await waitFor(() => expect(result.current.isLoading).toBe(false)); expect(result.current.data!.pages[0]).toEqual(resp); 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 08a20b1bb4813..6237e751ad1f0 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 @@ -41,15 +41,11 @@ describe('useFetchAlertData', () => { }); it('initially is not loading and does not have data', async () => { - await act(async () => { - const { result } = renderHook]>(() => - useFetchAlertData(testIds) - ); + const { result } = renderHook]>(() => + useFetchAlertData(testIds) + ); - await waitFor(() => null); - - expect(result.current).toEqual([false, {}]); - }); + expect(result.current).toEqual([false, {}]); }); it('returns no data when an error occurs', async () => { @@ -57,43 +53,35 @@ describe('useFetchAlertData', () => { throw new Error('an http error'); }); - await act(async () => { - const { result } = renderHook]>(() => - useFetchAlertData(testIds) - ); + const { result } = renderHook]>(() => + useFetchAlertData(testIds) + ); - await waitFor(() => null); - - expect(result.current).toEqual([false, {}]); - }); + await waitFor(() => expect(result.current).toEqual([false, {}])); }); it('retrieves the alert data', async () => { - await act(async () => { - const { result } = renderHook]>(() => - useFetchAlertData(testIds) - ); - - await waitFor(() => null); - await waitFor(() => null); + 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, unmount } = renderHook]>(() => - useFetchAlertData(testIds) - ); + const { result, unmount } = renderHook]>(() => + useFetchAlertData(testIds) + ); - await waitFor(() => null); + act(() => { unmount(); - - expect(result.current).toEqual([false, {}]); }); + + expect(result.current).toEqual([false, {}]); }); }); 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 c29269dff7b1d..509bfb96e9de6 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 @@ -54,13 +54,13 @@ describe('usePrivateLocationsAPI', () => { }) ); - await waitFor(() => null); - - expect(result.current).toEqual( - expect.objectContaining({ - loading: false, - privateLocations: [], - }) + await waitFor(() => + expect(result.current).toEqual( + expect.objectContaining({ + loading: false, + privateLocations: [], + }) + ) ); }); @@ -82,18 +82,18 @@ describe('usePrivateLocationsAPI', () => { }); }); - await waitFor(() => null); - - 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 () => { @@ -107,10 +107,10 @@ describe('usePrivateLocationsAPI', () => { result.current.onDelete('Test'); }); - await waitFor(() => null); - - 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/security_solution/public/assistant/overlay.test.tsx b/x-pack/plugins/security_solution/public/assistant/overlay.test.tsx index ca90d72b37157..eb9adf234e9fd 100644 --- a/x-pack/plugins/security_solution/public/assistant/overlay.test.tsx +++ b/x-pack/plugins/security_solution/public/assistant/overlay.test.tsx @@ -22,7 +22,14 @@ jest.mock('@kbn/elastic-assistant', () => ({ jest.mock('../common/hooks/use_experimental_features'); describe('AssistantOverlay', () => { - const queryClient = new QueryClient(); + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + cacheTime: Infinity, + retry: false, + }, + }, + }); beforeEach(() => { jest.clearAllMocks(); diff --git a/x-pack/plugins/security_solution/public/common/components/ml/hooks/use_installed_security_jobs.test.ts b/x-pack/plugins/security_solution/public/common/components/ml/hooks/use_installed_security_jobs.test.ts index 52ada32c6c791..31ecfda9b8d00 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/hooks/use_installed_security_jobs.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/ml/hooks/use_installed_security_jobs.test.ts @@ -87,11 +87,11 @@ describe('useInstalledSecurityJobs', () => { wrapper: TestProviders, }); - await waitFor(() => null); - - expect(appToastsMock.addError).toHaveBeenCalledWith('whoops', { - title: 'Security job fetch failure', - }); + await waitFor(() => + expect(appToastsMock.addError).toHaveBeenCalledWith('whoops', { + title: 'Security job fetch failure', + }) + ); }); }); diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.test.tsx b/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.test.tsx index 0b338d083b2eb..035c89f46d846 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.test.tsx +++ b/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.test.tsx @@ -139,9 +139,7 @@ describe('useFetch', () => { result.current.fetch(parameters); }); - await waitFor(() => null); - - expect(result.current.data).toEqual(undefined); + await waitFor(() => expect(result.current.data).toEqual(undefined)); }); it('should ignore state change if error but component is unmounted', async () => { @@ -158,9 +156,7 @@ describe('useFetch', () => { result.current.fetch(parameters); }); - await waitFor(() => null); - - expect(result.current.error).toEqual(undefined); + await waitFor(() => expect(result.current.error).toEqual(undefined)); }); it('should abort initial request if fetch is called', async () => { @@ -174,9 +170,9 @@ describe('useFetch', () => { return response; }); - await waitFor(() => null); - - expect(firstAbortCtrl.signal.aborted).toEqual(true); + await waitFor(() => { + expect(firstAbortCtrl.signal.aborted).toEqual(true); + }); abortSpy.mockRestore(); }); @@ -221,12 +217,12 @@ describe('useFetch', () => { initialParameters: parameters, }); - await waitFor(() => null); - - expect(mockFetchFn).toHaveBeenCalledTimes(1); - expect(mockStartTracking).toHaveBeenCalledTimes(1); - expect(mockEndTracking).toHaveBeenCalledTimes(1); - expect(mockStartTracking).toHaveBeenCalledWith({ name: requestName }); + await waitFor(() => { + expect(mockFetchFn).toHaveBeenCalledTimes(1); + expect(mockStartTracking).toHaveBeenCalledTimes(1); + expect(mockEndTracking).toHaveBeenCalledTimes(1); + expect(mockStartTracking).toHaveBeenCalledWith({ name: requestName }); + }); await act(async () => { result.current.fetch(parameters); @@ -245,10 +241,10 @@ describe('useFetch', () => { result.current.fetch(parameters); }); - await waitFor(() => null); - - expect(mockEndTracking).toHaveBeenCalledTimes(1); - expect(mockEndTracking).toHaveBeenCalledWith('success'); + await waitFor(() => { + expect(mockEndTracking).toHaveBeenCalledTimes(1); + expect(mockEndTracking).toHaveBeenCalledWith('success'); + }); }); it('should end aborted', async () => { @@ -266,10 +262,10 @@ describe('useFetch', () => { result.current.fetch(parameters); }); - await waitFor(() => null); - - expect(mockEndTracking).toHaveBeenCalledTimes(1); - expect(mockEndTracking).toHaveBeenCalledWith('aborted'); + await waitFor(() => { + expect(mockEndTracking).toHaveBeenCalledTimes(1); + expect(mockEndTracking).toHaveBeenCalledWith('aborted'); + }); abortSpy.mockRestore(); }); @@ -285,10 +281,10 @@ describe('useFetch', () => { result.current.fetch(parameters); }); - await waitFor(() => null); - - expect(mockEndTracking).toHaveBeenCalledTimes(1); - expect(mockEndTracking).toHaveBeenCalledWith('error'); + await waitFor(() => { + expect(mockEndTracking).toHaveBeenCalledTimes(1); + expect(mockEndTracking).toHaveBeenCalledWith('error'); + }); }); }); }); diff --git a/x-pack/plugins/security_solution/public/common/utils/global_query_string/index.test.tsx b/x-pack/plugins/security_solution/public/common/utils/global_query_string/index.test.tsx index 0bc3f652c3e1c..2c409a0881106 100644 --- a/x-pack/plugins/security_solution/public/common/utils/global_query_string/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/utils/global_query_string/index.test.tsx @@ -319,11 +319,11 @@ describe('global query string', () => { store.dispatch(globalUrlParamActions.deregisterUrlParam({ key: urlParamKey })); }); - waitFor(() => null); - - expect(mockHistory.replace).toHaveBeenCalledWith({ - search: ``, - }); + waitFor(() => + expect(mockHistory.replace).toHaveBeenCalledWith({ + search: ``, + }) + ); }); }); }); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_query.test.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_query.test.tsx index 98cc307e7488c..7f6e4d1b6229a 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_query.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_query.test.tsx @@ -29,7 +29,7 @@ describe('useQueryAlerts', () => { }); test('init', async () => { - const { result } = renderHook, [object, string]>(() => + const { result } = renderHook<[object, string], ReturnQueryAlerts>(() => useQueryAlerts(defaultProps) ); expect(result.current).toEqual({ @@ -43,7 +43,7 @@ describe('useQueryAlerts', () => { }); test('fetch alerts data', async () => { - const { result } = renderHook, [object, string]>(() => + const { result } = renderHook<[object, string], ReturnQueryAlerts>(() => useQueryAlerts(defaultProps) ); await waitFor(() => null); @@ -59,20 +59,19 @@ describe('useQueryAlerts', () => { test('re-fetch alerts data', async () => { const spyOnfetchQueryAlerts = jest.spyOn(api, 'fetchQueryAlerts'); - const { result } = renderHook, [object, string]>(() => + const { result } = renderHook<[object, string], ReturnQueryAlerts>(() => useQueryAlerts(defaultProps) ); - await waitFor(() => null); - if (result.current.refetch) { - result.current.refetch(); - } - await waitFor(() => null); - expect(spyOnfetchQueryAlerts).toHaveBeenCalledTimes(2); + await waitFor(() => expect(result.current.refetch).toBeDefined()); + + result.current.refetch(); + + await waitFor(() => expect(spyOnfetchQueryAlerts).toHaveBeenCalledTimes(2)); }); test('fetch alert when index name changed', async () => { const spyOnfetchRules = jest.spyOn(api, 'fetchQueryAlerts'); - const { rerender } = renderHook, [object, string]>( + const { rerender } = renderHook<[object, string], ReturnQueryAlerts>( (args) => useQueryAlerts({ ...defaultProps, query: args[0], indexName: args[1] }), { initialProps: [mockAlertsQuery, indexName], @@ -80,24 +79,22 @@ describe('useQueryAlerts', () => { ); await waitFor(() => null); rerender([mockAlertsQuery, 'new-mock-index-name']); - await waitFor(() => null); - expect(spyOnfetchRules).toHaveBeenCalledTimes(2); + await waitFor(() => expect(spyOnfetchRules).toHaveBeenCalledTimes(2)); }); test('fetch alert when query object changed', async () => { const spyOnfetchRules = jest.spyOn(api, 'fetchQueryAlerts'); - const { result } = renderHook, [object, string]>( + const { result } = renderHook<[object, string], ReturnQueryAlerts>( (args) => useQueryAlerts({ ...defaultProps, query: args[0], indexName: args[1] }), { initialProps: [mockAlertsQuery, indexName], } ); - await waitFor(() => null); - if (result.current.setQuery) { - result.current.setQuery({ ...mockAlertsQuery }); - } - await waitFor(() => null); - expect(spyOnfetchRules).toHaveBeenCalledTimes(2); + await waitFor(() => expect(result.current.setQuery).toBeDefined()); + + result.current.setQuery({ ...mockAlertsQuery }); + + await waitFor(() => expect(spyOnfetchRules).toHaveBeenCalledTimes(2)); }); test('if there is an error when fetching data, we should get back the init value for every properties', async () => { @@ -105,26 +102,28 @@ describe('useQueryAlerts', () => { spyOnGetUserPrivilege.mockImplementation(() => { throw new Error('Something went wrong, let see what happen'); }); - const { result } = renderHook, void>(() => + const { result } = renderHook>(() => useQueryAlerts(defaultProps) ); - await waitFor(() => null); - expect(result.current).toEqual({ - loading: false, - data: null, - response: '', - request: '', - setQuery: result.current.setQuery, - refetch: result.current.refetch, - }); + await waitFor(() => + expect(result.current).toEqual({ + loading: false, + data: null, + response: '', + request: '', + setQuery: result.current.setQuery, + refetch: result.current.refetch, + }) + ); }); test('skip', async () => { const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); const localProps = { ...defaultProps, skip: false }; - const { rerender } = renderHook, [object, string]>(() => + const { rerender } = renderHook<[object, string], ReturnQueryAlerts>(() => useQueryAlerts(localProps) ); + await waitFor(() => null); localProps.skip = true; diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_critical_alerts.test.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_critical_alerts.test.tsx index 0576891c32d1a..3b962343bbe3a 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_critical_alerts.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_critical_alerts.test.tsx @@ -71,6 +71,8 @@ describe('useCriticalAlerts', () => { wrapper: wrapperContainer, }); + await waitFor(() => expect(result.current.isLoading).toBe(true)); + expect(result.current).toEqual({ stat: '-', isLoading: true, @@ -97,22 +99,23 @@ describe('useCriticalAlerts', () => { const { result } = renderHook(() => useCriticalAlerts(props), { wrapper: wrapperContainer, }); - await waitFor(() => null); - expect(result.current).toEqual({ - stat: '100', - isLoading: false, - percentage: { - percent: '+100.0%', - color: 'danger', - note: i18n.STAT_DIFFERENCE({ - upOrDown: 'up', - percentageChange: '100.0%', - stat: '50', - statType: 'open critical alert count', - }), - }, - ...basicData, - }); + await waitFor(() => + expect(result.current).toEqual({ + stat: '100', + isLoading: false, + percentage: { + percent: '+100.0%', + color: 'danger', + note: i18n.STAT_DIFFERENCE({ + upOrDown: 'up', + percentageChange: '100.0%', + stat: '50', + statType: 'open critical alert count', + }), + }, + ...basicData, + }) + ); }); it('finds negative percentage change', async () => { mockUseQueryAlerts.mockImplementation((args) => @@ -129,22 +132,23 @@ describe('useCriticalAlerts', () => { const { result } = renderHook(() => useCriticalAlerts(props), { wrapper: wrapperContainer, }); - await waitFor(() => null); - expect(result.current).toEqual({ - stat: '50', - isLoading: false, - percentage: { - percent: '-50.0%', - color: 'success', - note: i18n.STAT_DIFFERENCE({ - upOrDown: 'down', - percentageChange: '50.0%', - stat: '100', - statType: 'open critical alert count', - }), - }, - ...basicData, - }); + await waitFor(() => + expect(result.current).toEqual({ + stat: '50', + isLoading: false, + percentage: { + percent: '-50.0%', + color: 'success', + note: i18n.STAT_DIFFERENCE({ + upOrDown: 'down', + percentageChange: '50.0%', + stat: '100', + statType: 'open critical alert count', + }), + }, + ...basicData, + }) + ); }); it('finds zero percentage change', async () => { mockUseQueryAlerts.mockImplementation((args) => ({ @@ -154,17 +158,18 @@ describe('useCriticalAlerts', () => { const { result } = renderHook(() => useCriticalAlerts(props), { wrapper: wrapperContainer, }); - await waitFor(() => null); - expect(result.current).toEqual({ - stat: '100', - isLoading: false, - percentage: { - percent: '0.0%', - color: 'hollow', - note: i18n.NO_CHANGE('open critical alert count'), - }, - ...basicData, - }); + await waitFor(() => + expect(result.current).toEqual({ + stat: '100', + isLoading: false, + percentage: { + percent: '0.0%', + color: 'hollow', + note: i18n.NO_CHANGE('open critical alert count'), + }, + ...basicData, + }) + ); }); it('handles null data - current time range', async () => { mockUseQueryAlerts.mockImplementation((args) => @@ -181,17 +186,18 @@ describe('useCriticalAlerts', () => { const { result } = renderHook(() => useCriticalAlerts(props), { wrapper: wrapperContainer, }); - await waitFor(() => null); - expect(result.current).toEqual({ - stat: '-', - isLoading: false, - percentage: { - percent: null, - color: 'hollow', - note: i18n.NO_DATA_CURRENT('alerts'), - }, - ...basicData, - }); + await waitFor(() => + expect(result.current).toEqual({ + stat: '-', + isLoading: false, + percentage: { + percent: null, + color: 'hollow', + note: i18n.NO_DATA_CURRENT('alerts'), + }, + ...basicData, + }) + ); }); it('handles null data - compare time range', async () => { mockUseQueryAlerts.mockImplementation((args) => @@ -208,17 +214,18 @@ describe('useCriticalAlerts', () => { const { result } = renderHook(() => useCriticalAlerts(props), { wrapper: wrapperContainer, }); - await waitFor(() => null); - expect(result.current).toEqual({ - stat: '100', - isLoading: false, - percentage: { - percent: null, - color: 'hollow', - note: i18n.NO_DATA_COMPARE('alerts'), - }, - ...basicData, - }); + await waitFor(() => + expect(result.current).toEqual({ + stat: '100', + isLoading: false, + percentage: { + percent: null, + color: 'hollow', + note: i18n.NO_DATA_COMPARE('alerts'), + }, + ...basicData, + }) + ); }); it('handles null data - current & compare time range', async () => { mockUseQueryAlerts.mockImplementation((args) => @@ -237,18 +244,20 @@ describe('useCriticalAlerts', () => { const { result, rerender } = renderHook(() => useCriticalAlerts(ourProps), { wrapper: wrapperContainer, }); - await waitFor(() => null); - await waitFor(() => null); - expect(result.current).toEqual({ - stat: '100', - isLoading: false, - percentage: { - percent: '0.0%', - color: 'hollow', - note: i18n.NO_CHANGE('open critical alert count'), - }, - ...basicData, - }); + + await waitFor(() => + expect(result.current).toEqual({ + stat: '100', + isLoading: false, + percentage: { + percent: '0.0%', + color: 'hollow', + note: i18n.NO_CHANGE('open critical alert count'), + }, + ...basicData, + }) + ); + ourProps = { ...props, from: '2020-09-08T08:20:18.966Z', @@ -257,17 +266,18 @@ describe('useCriticalAlerts', () => { toCompare: '2020-09-08T08:20:18.966Z', }; rerender(); - await waitFor(() => null); - expect(result.current).toEqual({ - stat: '-', - isLoading: false, - percentage: { - percent: null, - color: 'hollow', - note: i18n.NO_DATA('alerts'), - }, - ...basicData, - }); + await waitFor(() => + expect(result.current).toEqual({ + stat: '-', + isLoading: false, + percentage: { + percent: null, + color: 'hollow', + note: i18n.NO_DATA('alerts'), + }, + ...basicData, + }) + ); }); it('handles undefined data - current & compare time range', async () => { mockUseQueryAlerts.mockImplementation((args) => @@ -286,17 +296,18 @@ describe('useCriticalAlerts', () => { const { result, rerender } = renderHook(() => useCriticalAlerts(ourProps), { wrapper: wrapperContainer, }); - await waitFor(() => null); - expect(result.current).toEqual({ - stat: '100', - isLoading: false, - percentage: { - percent: '0.0%', - color: 'hollow', - note: i18n.NO_CHANGE('open critical alert count'), - }, - ...basicData, - }); + await waitFor(() => + expect(result.current).toEqual({ + stat: '100', + isLoading: false, + percentage: { + percent: '0.0%', + color: 'hollow', + note: i18n.NO_CHANGE('open critical alert count'), + }, + ...basicData, + }) + ); ourProps = { ...props, from: '2020-09-08T08:20:18.966Z', @@ -305,16 +316,17 @@ describe('useCriticalAlerts', () => { toCompare: '2020-09-08T08:20:18.966Z', }; rerender(); - await waitFor(() => null); - expect(result.current).toEqual({ - stat: '-', - isLoading: false, - percentage: { - percent: null, - color: 'hollow', - note: i18n.NO_DATA('alerts'), - }, - ...basicData, - }); + await waitFor(() => + expect(result.current).toEqual({ + stat: '-', + isLoading: false, + percentage: { + percent: null, + color: 'hollow', + note: i18n.NO_DATA('alerts'), + }, + ...basicData, + }) + ); }); }); diff --git a/x-pack/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx b/x-pack/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx index 214426fe20d4d..fbacdd4970f68 100644 --- a/x-pack/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx +++ b/x-pack/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx @@ -6,8 +6,8 @@ */ import React from 'react'; -import { act, renderHook } from '@testing-library/react-hooks'; -import { waitFor } from '@testing-library/react'; +import { renderHook } from '@testing-library/react-hooks'; +import { act, waitFor } from '@testing-library/react'; import { Provider } from 'react-redux'; import { useSourcererDataView } from '.'; @@ -137,8 +137,12 @@ jest.mock('../../common/lib/kibana', () => ({ type: 'keyword', }, }), + toSpec: () => ({ + id: dataViewId, + }), }) ), + getExistingIndices: jest.fn(() => [] as string[]), }, indexPatterns: { getTitles: jest.fn().mockImplementation(() => Promise.resolve(mockPatterns)), @@ -164,7 +168,6 @@ describe('Sourcerer Hooks', () => { }); await waitFor(() => null); rerender(); - expect(mockDispatch).toBeCalledTimes(3); expect(mockDispatch.mock.calls[0][0]).toEqual({ type: 'x-pack/security_solution/local/sourcerer/SET_DATA_VIEW_LOADING', payload: { id: 'security-solution', loading: true }, @@ -202,7 +205,7 @@ describe('Sourcerer Hooks', () => { loading: false, signalIndexName: mockSourcererState.signalIndexName, })); - const { rerender } = renderHook(() => useInitSourcerer(), { + const { rerender } = renderHook, void>(() => useInitSourcerer(), { wrapper: ({ children }) => {children}, }); await waitFor(() => null); @@ -231,7 +234,7 @@ describe('Sourcerer Hooks', () => { type: 'x-pack/security_solution/local/sourcerer/SET_SOURCERER_SCOPE_LOADING', payload: { loading: false }, }); - expect(mockDispatch).toHaveBeenCalledTimes(8); + expect(mockSearch).toHaveBeenCalledTimes(2); }); }); @@ -248,7 +251,7 @@ describe('Sourcerer Hooks', () => { }) ); - renderHook>(() => useInitSourcerer(), { + renderHook, void>(() => useInitSourcerer(), { wrapper: ({ children }) => {children}, }); @@ -268,7 +271,7 @@ describe('Sourcerer Hooks', () => { onInitialize(null) ); - renderHook>(() => useInitSourcerer(), { + renderHook, void>(() => useInitSourcerer(), { wrapper: ({ children }) => {children}, }); @@ -292,7 +295,7 @@ describe('Sourcerer Hooks', () => { }, }, }); - renderHook>(() => useInitSourcerer(), { + renderHook, void>(() => useInitSourcerer(), { wrapper: ({ children }) => {children}, }); @@ -328,7 +331,7 @@ describe('Sourcerer Hooks', () => { signalIndexName: mockSourcererState.signalIndexName, })); - const { rerender } = renderHook(() => useInitSourcerer(), { + const { rerender } = renderHook, void>(() => useInitSourcerer(), { wrapper: ({ children }) => {children}, }); @@ -366,7 +369,7 @@ describe('Sourcerer Hooks', () => { loading: false, signalIndexName: mockSourcererState.signalIndexName, })); - const { rerender } = renderHook(() => useInitSourcerer(), { + const { rerender } = renderHook, void>(() => useInitSourcerer(), { wrapper: ({ children }) => {children}, }); @@ -384,7 +387,7 @@ describe('Sourcerer Hooks', () => { signalIndexName: mockSourcererState.signalIndexName, isSignalIndexExists: true, })); - const { rerender } = renderHook( + const { rerender } = renderHook, void>( () => useInitSourcerer(SourcererScopeName.detections), { wrapper: ({ children }) => {children}, @@ -402,7 +405,7 @@ describe('Sourcerer Hooks', () => { }); }); it('index field search is not repeated when default and timeline have same dataViewId', async () => { - const { rerender } = renderHook(() => useInitSourcerer(), { + const { rerender } = renderHook, void>(() => useInitSourcerer(), { wrapper: ({ children }) => {children}, }); await waitFor(() => null); @@ -425,7 +428,7 @@ describe('Sourcerer Hooks', () => { }, }, }); - const { rerender } = renderHook(() => useInitSourcerer(), { + const { rerender } = renderHook, void>(() => useInitSourcerer(), { wrapper: ({ children }) => {children}, }); await waitFor(() => null); @@ -445,7 +448,7 @@ describe('Sourcerer Hooks', () => { })); }); it('does not needToBeInit if scope is default and selectedPatterns/missingPatterns have values', async () => { - const { rerender } = renderHook(() => useInitSourcerer(), { + const { rerender } = renderHook, void>(() => useInitSourcerer(), { wrapper: ({ children }) => {children}, }); await waitFor(() => null); @@ -474,7 +477,7 @@ describe('Sourcerer Hooks', () => { }, }, }); - const { rerender } = renderHook(() => useInitSourcerer(), { + const { rerender } = renderHook, void>(() => useInitSourcerer(), { wrapper: ({ children }) => {children}, }); await waitFor(() => null); @@ -508,7 +511,7 @@ describe('Sourcerer Hooks', () => { }, }, }); - const { rerender } = renderHook(() => useInitSourcerer(), { + const { rerender } = renderHook, void>(() => useInitSourcerer(), { wrapper: ({ children }) => {children}, }); await waitFor(() => null); @@ -543,7 +546,7 @@ describe('Sourcerer Hooks', () => { }, }, }); - const { rerender } = renderHook(() => useInitSourcerer(), { + const { rerender } = renderHook, void>(() => useInitSourcerer(), { wrapper: ({ children }) => {children}, }); await waitFor(() => null); @@ -582,7 +585,7 @@ describe('Sourcerer Hooks', () => { }, }, }); - const { rerender } = renderHook(() => useInitSourcerer(), { + const { rerender } = renderHook, void>(() => useInitSourcerer(), { wrapper: ({ children }) => {children}, }); await waitFor(() => null); @@ -622,12 +625,12 @@ describe('Sourcerer Hooks', () => { }, }, }); - const { result, rerender } = renderHook( - () => useSourcererDataView(), - { - wrapper: ({ children }) => {children}, - } - ); + const { result, rerender } = renderHook< + React.PropsWithChildren, + SelectedDataView + >(() => useSourcererDataView(), { + wrapper: ({ children }) => {children}, + }); await waitFor(() => null); rerender(); expect(result.current.selectedPatterns).toEqual([ @@ -645,7 +648,7 @@ describe('Sourcerer Hooks', () => { }); it('should update the title and name of the data view according to the selected patterns', async () => { - const { result, rerender } = renderHook>( + const { result, rerender } = renderHook, SelectedDataView>( () => useSourcererDataView(), { wrapper: ({ children }) => {children}, diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx index ffa30f08ec809..8ba1664b496eb 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx @@ -118,7 +118,7 @@ describe('useTimelineTypes', () => { ); await waitFor(() => null); - const { container } = render(result.current.timelineTabs); + render(result.current.timelineTabs); fireEvent( screen.getByTestId('timeline-tab-default'), diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations.test.tsx index 8585e1ab5d1d7..cf2df1fd37ded 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ import React from 'react'; -import { renderHook, waitFor } from '@testing-library/react'; +import { waitFor } from '@testing-library/react'; +import { renderHook } from '@testing-library/react-hooks'; import { useLoadRuleAggregationsQuery as useLoadRuleAggregations } from './use_load_rule_aggregations_query'; import { RuleStatus } from '../../types'; import { useKibana } from '../../common/lib/kibana'; @@ -82,19 +83,21 @@ describe('useLoadRuleAggregations', () => { ); rerender(); - await waitFor(() => null); - expect(loadRuleAggregationsWithKueryFilter).toBeCalledWith( - expect.objectContaining({ - searchText: '', - typesFilter: [], - actionTypesFilter: [], - ruleExecutionStatusesFilter: [], - ruleLastRunOutcomesFilter: [], - ruleStatusesFilter: [], - tagsFilter: [], - }) + await waitFor(() => + expect(loadRuleAggregationsWithKueryFilter).toBeCalledWith( + expect.objectContaining({ + searchText: '', + typesFilter: [], + actionTypesFilter: [], + ruleExecutionStatusesFilter: [], + ruleLastRunOutcomesFilter: [], + ruleStatusesFilter: [], + tagsFilter: [], + }) + ) ); + expect(result.current.rulesStatusesTotal).toEqual(MOCK_AGGS.ruleExecutionStatus); }); @@ -119,19 +122,21 @@ describe('useLoadRuleAggregations', () => { }); rerender(); - await waitFor(() => null); - expect(loadRuleAggregationsWithKueryFilter).toBeCalledWith( - expect.objectContaining({ - searchText: 'test', - typesFilter: ['type1', 'type2'], - actionTypesFilter: ['action1', 'action2'], - ruleExecutionStatusesFilter: ['status1', 'status2'], - ruleStatusesFilter: ['enabled', 'snoozed'] as RuleStatus[], - tagsFilter: ['tag1', 'tag2'], - ruleLastRunOutcomesFilter: ['outcome1', 'outcome2'], - }) + await waitFor(() => + expect(loadRuleAggregationsWithKueryFilter).toBeCalledWith( + expect.objectContaining({ + searchText: 'test', + typesFilter: ['type1', 'type2'], + actionTypesFilter: ['action1', 'action2'], + ruleExecutionStatusesFilter: ['status1', 'status2'], + ruleStatusesFilter: ['enabled', 'snoozed'] as RuleStatus[], + tagsFilter: ['tag1', 'tag2'], + ruleLastRunOutcomesFilter: ['outcome1', 'outcome2'], + }) + ) ); + expect(result.current.rulesStatusesTotal).toEqual(MOCK_AGGS.ruleExecutionStatus); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.test.tsx index 2af0906ab4632..225a1d0e5f057 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.test.tsx @@ -291,11 +291,10 @@ describe('useLoadRules', () => { expect(result.current.rulesState.isLoading).toBeTruthy(); rerender(); - await waitFor(() => null); + await waitFor(() => expect(result.current.rulesState.isLoading).toBeFalsy()); expect(result.current.rulesState.initialLoad).toBeFalsy(); expect(result.current.hasData).toBeTruthy(); - expect(result.current.rulesState.isLoading).toBeFalsy(); expect(onPage).toBeCalledTimes(0); expect(loadRulesWithKueryFilter).toBeCalledWith( @@ -344,24 +343,24 @@ describe('useLoadRules', () => { }); rerender(); - await waitFor(() => null); - - expect(loadRulesWithKueryFilter).toBeCalledWith( - expect.objectContaining({ - page: { - index: 0, - size: 25, - }, - searchText: 'test', - typesFilter: ['type1', 'type2'], - actionTypesFilter: ['action1', 'action2'], - ruleExecutionStatusesFilter: ['status1', 'status2'], - ruleLastRunOutcomesFilter: ['outcome1', 'outcome2'], - ruleParamsFilter: {}, - ruleStatusesFilter: ['enabled', 'snoozed'], - tagsFilter: ['tag1', 'tag2'], - sort: { field: 'name', direction: 'asc' }, - }) + await waitFor(() => + expect(loadRulesWithKueryFilter).toBeCalledWith( + expect.objectContaining({ + page: { + index: 0, + size: 25, + }, + searchText: 'test', + typesFilter: ['type1', 'type2'], + actionTypesFilter: ['action1', 'action2'], + ruleExecutionStatusesFilter: ['status1', 'status2'], + ruleLastRunOutcomesFilter: ['outcome1', 'outcome2'], + ruleParamsFilter: {}, + ruleStatusesFilter: ['enabled', 'snoozed'], + tagsFilter: ['tag1', 'tag2'], + sort: { field: 'name', direction: 'asc' }, + }) + ) ); }); @@ -399,12 +398,12 @@ describe('useLoadRules', () => { ); rerender(); - await waitFor(() => null); - - expect(onPage).toHaveBeenCalledWith({ - index: 0, - size: 25, - }); + await waitFor(() => + expect(onPage).toHaveBeenCalledWith({ + index: 0, + size: 25, + }) + ); }); it('should call onError if API fails', async () => { @@ -466,9 +465,7 @@ describe('useLoadRules', () => { expect(result.current.hasData).toBeFalsy(); rerender(); - await waitFor(() => null); - - expect(result.current.hasData).toBeFalsy(); + await waitFor(() => expect(result.current.hasData).toBeFalsy()); }); it('hasData should be false, if there is rule types filter and no rules with hasDefaultRuleTypesFiltersOn = true', async () => { @@ -501,9 +498,7 @@ describe('useLoadRules', () => { expect(result.current.hasData).toBeFalsy(); rerender(); - await waitFor(() => null); - - expect(result.current.hasData).toBeFalsy(); + await waitFor(() => expect(result.current.hasData).toBeFalsy()); }); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_get_maintenance_windows.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_get_maintenance_windows.test.ts index 7b5aaf87a9335..06cccd91af423 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_get_maintenance_windows.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_get_maintenance_windows.test.ts @@ -107,9 +107,7 @@ describe('useBulkGetMaintenanceWindows', () => { } ); - await waitFor(() => null); - - expect(result.current.data?.get('test-id')).toEqual(mockMaintenanceWindow); + await waitFor(() => expect(result.current.data?.get('test-id')).toEqual(mockMaintenanceWindow)); expect(spy).toHaveBeenCalledWith({ http: expect.anything(), From 59cd86aca8e5d7b6583609cafcce9f2b99b9659e Mon Sep 17 00:00:00 2001 From: Eyo Okon Eyo Date: Thu, 10 Oct 2024 09:52:53 +0100 Subject: [PATCH 07/18] fix issue with ftr test --- .../integration_tests/console_manager.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/console_manager/integration_tests/console_manager.test.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/console_manager/integration_tests/console_manager.test.tsx index 7f0d3597c9fd2..9797005cde7d8 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/console_manager/integration_tests/console_manager.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/console_manager/integration_tests/console_manager.test.tsx @@ -6,7 +6,7 @@ */ import type { RenderHookResult } from '@testing-library/react-hooks'; -import { renderHook as _renderHook, act, waitFor } from '@testing-library/react-hooks'; +import { renderHook as _renderHook } from '@testing-library/react-hooks'; import { useConsoleManager } from '../console_manager'; import React from 'react'; import type { @@ -22,7 +22,7 @@ import { getNewConsoleRegistrationMock, } from '../mocks'; import userEvent, { type UserEvent } from '@testing-library/user-event'; -import { waitFor } from '@testing-library/react'; +import { waitFor, act } from '@testing-library/react'; import { enterConsoleCommand } from '../../../mocks'; describe('When using ConsoleManager', () => { From 1279eafe85d3a181a466f140c92b379ab7888bf8 Mon Sep 17 00:00:00 2001 From: Eyo Okon Eyo Date: Mon, 30 Sep 2024 11:13:19 +0100 Subject: [PATCH 08/18] fix endpoint list related tests --- .../common/mock/endpoint/app_context_render.tsx | 7 ++++--- .../hooks/endpoint/use_get_endpoints_list.test.ts | 12 +++++++----- .../hooks/endpoint/use_get_endpoints_list.ts | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx b/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx index de846ec8bfd77..a07cddd1da3c0 100644 --- a/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx +++ b/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx @@ -325,15 +325,16 @@ export const createAppRootMockRenderer = (): AppContextTestRender => { TResult extends UseBaseQueryResult = UseBaseQueryResult >( hookFn: HookRendererFunction, + /** + * If defined (default is `isSuccess`), the renderer will wait for the given react query to be truthy + */ waitForHook: WaitForReactHookState = 'isSuccess', options: RenderHookOptions = {} ) => { const { result: hookResult } = renderHook(hookFn, options); if (waitForHook) { - await waitFor(() => { - return hookResult.current[waitForHook]; - }); + await waitFor(() => expect(hookResult.current[waitForHook]).toBe(true)); } return hookResult.current; diff --git a/x-pack/plugins/security_solution/public/management/hooks/endpoint/use_get_endpoints_list.test.ts b/x-pack/plugins/security_solution/public/management/hooks/endpoint/use_get_endpoints_list.test.ts index d7f073b2a8338..3c9ed815536df 100644 --- a/x-pack/plugins/security_solution/public/management/hooks/endpoint/use_get_endpoints_list.test.ts +++ b/x-pack/plugins/security_solution/public/management/hooks/endpoint/use_get_endpoints_list.test.ts @@ -7,7 +7,7 @@ import type { AppContextTestRender, ReactQueryHookRenderer } from '../../../common/mock/endpoint'; import { createAppRootMockRenderer } from '../../../common/mock/endpoint'; -import { useGetEndpointsList } from './use_get_endpoints_list'; +import { useGetEndpointsList, PAGING_PARAMS } from './use_get_endpoints_list'; import { HOST_METADATA_LIST_ROUTE } from '../../../../common/endpoint/constants'; import { useQuery as _useQuery } from '@tanstack/react-query'; import { endpointMetadataHttpMocks } from '../../pages/endpoint_hosts/mocks'; @@ -117,13 +117,15 @@ describe('useGetEndpointsList hook', () => { it('should also list inactive agents', async () => { const getApiResponse = apiMocks.responseProvider.metadataList.getMockImplementation(); + const inActiveIndex = [0, 1, 3]; + // set a few of the agents as inactive/unenrolled apiMocks.responseProvider.metadataList.mockImplementation(() => { if (getApiResponse) { return { ...getApiResponse(), data: getApiResponse().data.map((item, i) => { - const isInactiveIndex = [0, 1, 3].includes(i); + const isInactiveIndex = inActiveIndex.includes(i); return { ...item, host_status: isInactiveIndex ? HostStatus.INACTIVE : item.host_status, @@ -154,7 +156,7 @@ describe('useGetEndpointsList hook', () => { const res = await renderReactQueryHook(() => useGetEndpointsList({ searchString: 'inactive' })); expect( res.data?.map((host) => host.name.split('-')[2]).filter((name) => name === 'inactive').length - ).toEqual(3); + ).toEqual(inActiveIndex.length); }); it('should only list 50 agents when more than 50 in the metadata list API', async () => { @@ -192,7 +194,7 @@ describe('useGetEndpointsList hook', () => { // verify useGetEndpointsList hook returns all 50 agents in the list const res = await renderReactQueryHook(() => useGetEndpointsList({ searchString: '' })); - expect(res.data?.length).toEqual(50); + expect(res.data?.length).toEqual(PAGING_PARAMS.default); }); it('should only list 10 more agents when 50 or more agents are already selected', async () => { @@ -232,7 +234,7 @@ describe('useGetEndpointsList hook', () => { const agentIdsToSelect = apiMocks.responseProvider .metadataList() .data.map((d) => d.metadata.agent.id) - .slice(0, 50); + .slice(0, PAGING_PARAMS.default); // call useGetEndpointsList with all 50 agents selected const res = await renderReactQueryHook(() => diff --git a/x-pack/plugins/security_solution/public/management/hooks/endpoint/use_get_endpoints_list.ts b/x-pack/plugins/security_solution/public/management/hooks/endpoint/use_get_endpoints_list.ts index 632b7d8ff48ae..b0072d73b832e 100644 --- a/x-pack/plugins/security_solution/public/management/hooks/endpoint/use_get_endpoints_list.ts +++ b/x-pack/plugins/security_solution/public/management/hooks/endpoint/use_get_endpoints_list.ts @@ -18,7 +18,7 @@ type GetEndpointsListResponse = Array<{ selected: boolean; }>; -const PAGING_PARAMS = Object.freeze({ +export const PAGING_PARAMS = Object.freeze({ default: 50, all: 10000, }); From 03a832c20d92ebd784468febdb23a873d3f91747 Mon Sep 17 00:00:00 2001 From: Eyo Okon Eyo Date: Thu, 10 Oct 2024 14:09:14 +0100 Subject: [PATCH 09/18] use waitFor with assertion callbacks --- .../hooks/use_search_alerts_query.test.tsx | 212 +++++++++--------- .../use_virtual_data_view_query.test.tsx | 4 +- .../src/hooks/use_load_actions.test.ts | 75 +++---- .../index.test.ts | 83 ++++--- .../src/use_async/index.test.ts | 56 ++--- .../connectors/jira/use_get_issue.test.tsx | 16 +- .../use_markdown_session_storage.test.tsx | 13 -- .../use_get_all_case_configurations.test.ts | 94 ++++---- ...t_supported_action_connectors.tsx.test.tsx | 13 +- .../use_find_case_user_actions.test.tsx | 58 ++--- .../use_get_case_file_stats.test.tsx | 14 +- .../containers/use_get_cases_metrics.test.tsx | 20 +- .../containers/use_get_cases_status.test.tsx | 18 +- .../containers/use_get_categories.test.tsx | 16 +- .../hooks/use_action_status.test.tsx | 27 +-- .../hooks/persist_exception_list.test.ts | 63 +++--- .../hooks/use_fetch_alert_detail.test.ts | 4 - .../use_host_isolation_action.test.tsx | 61 ++--- .../use_execution_events.test.tsx | 66 +++--- .../alerts/use_signal_index.test.tsx | 98 ++++---- .../use_asset_criticality.test.ts | 16 +- .../public/management/hooks/test_utils.tsx | 4 +- .../timelines/containers/index.test.tsx | 55 ++--- .../hooks/use_load_rule_aggregations.test.tsx | 18 +- .../hooks/use_load_tags_query.test.tsx | 70 +++--- 25 files changed, 582 insertions(+), 592 deletions(-) diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.test.tsx index 1442b877766d4..d1c5f69845abd 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_search_alerts_query.test.tsx @@ -130,123 +130,125 @@ describe('useSearchAlertsQuery', () => { const { result } = renderHook(() => useSearchAlertsQuery(params), { wrapper, }); - await waitFor(() => result.current.data); - expect(result.current.data).toEqual( - expect.objectContaining({ - ...expectedResponse, - alerts: [ - { - _index: '.internal.alerts-security.alerts-default-000001', - _id: '38dd308706a127696cc63b8f142e8e4d66f8f79bc7d491dd79a42ea4ead62dd1', - '@timestamp': ['2022-03-22T16:48:07.518Z'], - 'host.name': ['Host-4dbzugdlqd'], - 'kibana.alert.reason': [ - 'registry event with process iexlorer.exe, by 5qcxz8o4j7 on Host-4dbzugdlqd created low alert test.', - ], - 'kibana.alert.risk_score': [21], - 'kibana.alert.rule.name': ['test'], - 'kibana.alert.severity': ['low'], - 'process.name': ['iexlorer.exe'], - 'user.name': ['5qcxz8o4j7'], - }, - { - _index: '.internal.alerts-security.alerts-default-000001', - _id: '8361363c0db6f30ca2dfb4aeb4835e7d6ec57bc195b96d9ee5a4ead1bb9f8b86', - '@timestamp': ['2022-03-22T16:17:50.769Z'], - 'host.name': ['Host-4dbzugdlqd'], - 'kibana.alert.reason': [ - 'network event with process iexlorer.exe, by hdgsmwj08h on Host-4dbzugdlqd created low alert test.', - ], - 'kibana.alert.risk_score': [21], - 'kibana.alert.rule.name': ['test'], - 'kibana.alert.severity': ['low'], - 'process.name': ['iexlorer.exe'], - 'user.name': ['hdgsmwj08h'], - }, - ], - total: 2, - ecsAlertsData: [ - { - kibana: { - alert: { - severity: ['low'], - risk_score: [21], - rule: { name: ['test'] }, - reason: [ - 'registry event with process iexlorer.exe, by 5qcxz8o4j7 on Host-4dbzugdlqd created low alert test.', - ], - }, - }, - process: { name: ['iexlorer.exe'] }, - '@timestamp': ['2022-03-22T16:48:07.518Z'], - user: { name: ['5qcxz8o4j7'] }, - host: { name: ['Host-4dbzugdlqd'] }, - _id: '38dd308706a127696cc63b8f142e8e4d66f8f79bc7d491dd79a42ea4ead62dd1', - _index: '.internal.alerts-security.alerts-default-000001', - }, - { - kibana: { - alert: { - severity: ['low'], - risk_score: [21], - rule: { name: ['test'] }, - reason: [ - 'network event with process iexlorer.exe, by hdgsmwj08h on Host-4dbzugdlqd created low alert test.', - ], - }, - }, - process: { name: ['iexlorer.exe'] }, - '@timestamp': ['2022-03-22T16:17:50.769Z'], - user: { name: ['hdgsmwj08h'] }, - host: { name: ['Host-4dbzugdlqd'] }, - _id: '8361363c0db6f30ca2dfb4aeb4835e7d6ec57bc195b96d9ee5a4ead1bb9f8b86', - _index: '.internal.alerts-security.alerts-default-000001', - }, - ], - oldAlertsData: [ - [ - { field: 'kibana.alert.severity', value: ['low'] }, - { field: 'process.name', value: ['iexlorer.exe'] }, - { field: '@timestamp', value: ['2022-03-22T16:48:07.518Z'] }, - { field: 'kibana.alert.risk_score', value: [21] }, - { field: 'kibana.alert.rule.name', value: ['test'] }, - { field: 'user.name', value: ['5qcxz8o4j7'] }, + await waitFor(() => { + expect(result.current.data).toBeDefined(); + expect(result.current.data).toEqual( + expect.objectContaining({ + ...expectedResponse, + alerts: [ { - field: 'kibana.alert.reason', - value: [ + _index: '.internal.alerts-security.alerts-default-000001', + _id: '38dd308706a127696cc63b8f142e8e4d66f8f79bc7d491dd79a42ea4ead62dd1', + '@timestamp': ['2022-03-22T16:48:07.518Z'], + 'host.name': ['Host-4dbzugdlqd'], + 'kibana.alert.reason': [ 'registry event with process iexlorer.exe, by 5qcxz8o4j7 on Host-4dbzugdlqd created low alert test.', ], + 'kibana.alert.risk_score': [21], + 'kibana.alert.rule.name': ['test'], + 'kibana.alert.severity': ['low'], + 'process.name': ['iexlorer.exe'], + 'user.name': ['5qcxz8o4j7'], }, - { field: 'host.name', value: ['Host-4dbzugdlqd'] }, { - field: '_id', - value: '38dd308706a127696cc63b8f142e8e4d66f8f79bc7d491dd79a42ea4ead62dd1', + _index: '.internal.alerts-security.alerts-default-000001', + _id: '8361363c0db6f30ca2dfb4aeb4835e7d6ec57bc195b96d9ee5a4ead1bb9f8b86', + '@timestamp': ['2022-03-22T16:17:50.769Z'], + 'host.name': ['Host-4dbzugdlqd'], + 'kibana.alert.reason': [ + 'network event with process iexlorer.exe, by hdgsmwj08h on Host-4dbzugdlqd created low alert test.', + ], + 'kibana.alert.risk_score': [21], + 'kibana.alert.rule.name': ['test'], + 'kibana.alert.severity': ['low'], + 'process.name': ['iexlorer.exe'], + 'user.name': ['hdgsmwj08h'], }, - { field: '_index', value: '.internal.alerts-security.alerts-default-000001' }, ], - [ - { field: 'kibana.alert.severity', value: ['low'] }, - { field: 'process.name', value: ['iexlorer.exe'] }, - { field: '@timestamp', value: ['2022-03-22T16:17:50.769Z'] }, - { field: 'kibana.alert.risk_score', value: [21] }, - { field: 'kibana.alert.rule.name', value: ['test'] }, - { field: 'user.name', value: ['hdgsmwj08h'] }, + total: 2, + ecsAlertsData: [ { - field: 'kibana.alert.reason', - value: [ - 'network event with process iexlorer.exe, by hdgsmwj08h on Host-4dbzugdlqd created low alert test.', - ], + kibana: { + alert: { + severity: ['low'], + risk_score: [21], + rule: { name: ['test'] }, + reason: [ + 'registry event with process iexlorer.exe, by 5qcxz8o4j7 on Host-4dbzugdlqd created low alert test.', + ], + }, + }, + process: { name: ['iexlorer.exe'] }, + '@timestamp': ['2022-03-22T16:48:07.518Z'], + user: { name: ['5qcxz8o4j7'] }, + host: { name: ['Host-4dbzugdlqd'] }, + _id: '38dd308706a127696cc63b8f142e8e4d66f8f79bc7d491dd79a42ea4ead62dd1', + _index: '.internal.alerts-security.alerts-default-000001', }, - { field: 'host.name', value: ['Host-4dbzugdlqd'] }, { - field: '_id', - value: '8361363c0db6f30ca2dfb4aeb4835e7d6ec57bc195b96d9ee5a4ead1bb9f8b86', + kibana: { + alert: { + severity: ['low'], + risk_score: [21], + rule: { name: ['test'] }, + reason: [ + 'network event with process iexlorer.exe, by hdgsmwj08h on Host-4dbzugdlqd created low alert test.', + ], + }, + }, + process: { name: ['iexlorer.exe'] }, + '@timestamp': ['2022-03-22T16:17:50.769Z'], + user: { name: ['hdgsmwj08h'] }, + host: { name: ['Host-4dbzugdlqd'] }, + _id: '8361363c0db6f30ca2dfb4aeb4835e7d6ec57bc195b96d9ee5a4ead1bb9f8b86', + _index: '.internal.alerts-security.alerts-default-000001', }, - { field: '_index', value: '.internal.alerts-security.alerts-default-000001' }, ], - ], - }) - ); + oldAlertsData: [ + [ + { field: 'kibana.alert.severity', value: ['low'] }, + { field: 'process.name', value: ['iexlorer.exe'] }, + { field: '@timestamp', value: ['2022-03-22T16:48:07.518Z'] }, + { field: 'kibana.alert.risk_score', value: [21] }, + { field: 'kibana.alert.rule.name', value: ['test'] }, + { field: 'user.name', value: ['5qcxz8o4j7'] }, + { + field: 'kibana.alert.reason', + value: [ + 'registry event with process iexlorer.exe, by 5qcxz8o4j7 on Host-4dbzugdlqd created low alert test.', + ], + }, + { field: 'host.name', value: ['Host-4dbzugdlqd'] }, + { + field: '_id', + value: '38dd308706a127696cc63b8f142e8e4d66f8f79bc7d491dd79a42ea4ead62dd1', + }, + { field: '_index', value: '.internal.alerts-security.alerts-default-000001' }, + ], + [ + { field: 'kibana.alert.severity', value: ['low'] }, + { field: 'process.name', value: ['iexlorer.exe'] }, + { field: '@timestamp', value: ['2022-03-22T16:17:50.769Z'] }, + { field: 'kibana.alert.risk_score', value: [21] }, + { field: 'kibana.alert.rule.name', value: ['test'] }, + { field: 'user.name', value: ['hdgsmwj08h'] }, + { + field: 'kibana.alert.reason', + value: [ + 'network event with process iexlorer.exe, by hdgsmwj08h on Host-4dbzugdlqd created low alert test.', + ], + }, + { field: 'host.name', value: ['Host-4dbzugdlqd'] }, + { + field: '_id', + value: '8361363c0db6f30ca2dfb4aeb4835e7d6ec57bc195b96d9ee5a4ead1bb9f8b86', + }, + { field: '_index', value: '.internal.alerts-security.alerts-default-000001' }, + ], + ], + }) + ); + }); }); it('returns empty placeholder data', () => { diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_virtual_data_view_query.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_virtual_data_view_query.test.tsx index ca8b0eebefb1e..419d963ec2c34 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_virtual_data_view_query.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_virtual_data_view_query.test.tsx @@ -102,10 +102,10 @@ describe('useVirtualDataViewQuery', () => { } ); - await waitFor(() => result.current.data); + await waitFor(() => expect(result.current.data).toBeDefined()); unmount(); - expect(mockDataViewsService.clearInstanceCache).toHaveBeenCalled(); + await waitFor(() => expect(mockDataViewsService.clearInstanceCache).toHaveBeenCalled()); }); }); diff --git a/packages/kbn-cell-actions/src/hooks/use_load_actions.test.ts b/packages/kbn-cell-actions/src/hooks/use_load_actions.test.ts index 1ef7d01ccf1a3..de10013f12c52 100644 --- a/packages/kbn-cell-actions/src/hooks/use_load_actions.test.ts +++ b/packages/kbn-cell-actions/src/hooks/use_load_actions.test.ts @@ -36,10 +36,10 @@ describe('loadActions hooks', () => { expect(mockGetActions).toHaveBeenCalledTimes(1); expect(mockGetActions).toHaveBeenCalledWith(actionContext); - await waitFor(() => null); - - expect(result.current.value).toEqual([action]); - expect(result.current.loading).toEqual(false); + await waitFor(() => { + expect(result.current.value).toEqual([action]); + expect(result.current.loading).toEqual(false); + }); }); it('should throw error when getAction is rejected', async () => { @@ -49,9 +49,7 @@ describe('loadActions hooks', () => { const { result } = renderHook(useLoadActions, { initialProps: actionContext, }); - await waitFor(() => null); - - expect(result.error?.message).toEqual(message); + await waitFor(() => expect(result.error?.message).toEqual(message)); }); it('filters out disabled actions', async () => { @@ -63,9 +61,7 @@ describe('loadActions hooks', () => { useLoadActions(actionContext, { disabledActionTypes: [actionDisabled.type] }) ); - await waitFor(() => null); - - expect(result.current.value).toEqual([actionEnabled]); + await waitFor(() => expect(result.current.value).toEqual([actionEnabled])); }); }); @@ -88,28 +84,26 @@ describe('loadActions hooks', () => { expect(mockGetActions).toHaveBeenCalledTimes(1); expect(mockGetActions).toHaveBeenCalledWith(actionContext); - await waitFor(() => null); - - const [{ value: valueAfterUpdate, loading: loadingAfterUpdate }] = result.current; - expect(valueAfterUpdate).toEqual([action]); - expect(loadingAfterUpdate).toEqual(false); + await waitFor(() => { + const [{ value: valueAfterUpdate, loading: loadingAfterUpdate }] = result.current; + expect(valueAfterUpdate).toEqual([action]); + expect(loadingAfterUpdate).toEqual(false); + }); }); it('should throw error when getAction is rejected', async () => { const message = 'some division by 0'; - mockGetActions.mockRejectedValueOnce(Error(message)); + mockGetActions.mockRejectedValueOnce(new Error(message)); const { result } = renderHook(useLoadActionsFn); const [_, loadActions] = result.current; - expect(result).toBeUndefined(); + expect(result.error).toBeUndefined(); act(() => { loadActions(actionContext); }); - await waitFor(() => null); - - expect(result.error?.message).toEqual(message); + await waitFor(() => expect(result.error?.message).toEqual(message)); }); it('filters out disabled actions types', async () => { @@ -125,10 +119,10 @@ describe('loadActions hooks', () => { act(() => { loadActions(actionContext); }); - await waitFor(() => null); - - const [{ value: valueAfterUpdate }] = result.current; - expect(valueAfterUpdate).toEqual([actionEnabled]); + await waitFor(() => { + const [{ value: valueAfterUpdate }] = result.current; + expect(valueAfterUpdate).toEqual([actionEnabled]); + }); }); }); @@ -147,10 +141,10 @@ describe('loadActions hooks', () => { expect(mockGetActions).toHaveBeenCalledWith(actionContext); expect(mockGetActions).toHaveBeenCalledWith(actionContext2); - await waitFor(() => null); - - expect(result.current.value).toEqual([[action], [action]]); - expect(result.current.loading).toEqual(false); + await waitFor(() => { + expect(result.current.value).toEqual([[action], [action]]); + expect(result.current.loading).toEqual(false); + }); }); it('should throw error when getAction is rejected', async () => { @@ -160,9 +154,7 @@ describe('loadActions hooks', () => { const { result } = renderHook(useBulkLoadActions, { initialProps: actionContexts, }); - await waitFor(() => null); - - expect(result.error?.message).toEqual(message); + await waitFor(() => expect(result.error?.message).toEqual(message)); }); it('filters out disabled actions types', async () => { @@ -174,9 +166,7 @@ describe('loadActions hooks', () => { useBulkLoadActions(actionContexts, { disabledActionTypes: [actionDisabled.type] }) ); - await waitFor(() => null); - - expect(result.current.value).toEqual([[actionEnabled], [actionEnabled]]); + await waitFor(() => expect(result.current.value).toEqual([[actionEnabled], [actionEnabled]])); }); it('should re-render when contexts is changed', async () => { @@ -184,22 +174,21 @@ describe('loadActions hooks', () => { initialProps: [actionContext], }); - await waitFor(() => null); - expect(mockGetActions).toHaveBeenCalledWith(actionContext); + await waitFor(() => expect(mockGetActions).toHaveBeenCalledWith(actionContext)); rerender([actionContext2]); - await waitFor(() => null); - expect(mockGetActions).toHaveBeenCalledWith(actionContext2); + await waitFor(() => expect(mockGetActions).toHaveBeenCalledWith(actionContext2)); mockGetActions.mockClear(); rerender([]); - await waitFor(() => null); - expect(mockGetActions).toHaveBeenCalledTimes(0); + await waitFor(() => { + expect(mockGetActions).toHaveBeenCalledTimes(0); - expect(result.current.value).toBeInstanceOf(Array); - expect(result.current.value).toHaveLength(0); - expect(result.current.loading).toBe(false); + expect(result.current.value).toBeInstanceOf(Array); + expect(result.current.value).toHaveLength(0); + expect(result.current.loading).toBe(false); + }); }); it('should return the same array after re-render when contexts is undefined', async () => { diff --git a/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts b/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts index 10c99b3d6f2c2..8e086991f27bc 100644 --- a/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts +++ b/packages/kbn-securitysolution-autocomplete/src/hooks/use_field_value_autocomplete/index.test.ts @@ -80,11 +80,12 @@ describe('use_field_value_autocomplete', () => { }) ); - const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; + await waitFor(() => { + const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; - await waitFor(() => expect(getValueSuggestionsMock).not.toHaveBeenCalled()); - - expect(result.current).toEqual(expectedResult); + expect(result.current).toEqual(expectedResult); + expect(getValueSuggestionsMock).not.toHaveBeenCalled(); + }); }); test('does not call autocomplete service if "selectedField" is undefined', async () => { @@ -103,10 +104,12 @@ describe('use_field_value_autocomplete', () => { }) ); - const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; - await waitFor(() => expect(getValueSuggestionsMock).not.toHaveBeenCalled()); + await waitFor(() => { + const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; - expect(result.current).toEqual(expectedResult); + expect(result.current).toEqual(expectedResult); + expect(getValueSuggestionsMock).not.toHaveBeenCalled(); + }); }); test('does not call autocomplete service if "indexPattern" is undefined', async () => { @@ -125,10 +128,12 @@ describe('use_field_value_autocomplete', () => { }) ); - const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; + await waitFor(() => { + const expectedResult: UseFieldValueAutocompleteReturn = [false, true, [], result.current[3]]; - await waitFor(() => expect(getValueSuggestionsMock).not.toHaveBeenCalled()); - expect(result.current).toEqual(expectedResult); + expect(result.current).toEqual(expectedResult); + expect(getValueSuggestionsMock).not.toHaveBeenCalled(); + }); }); test('it uses full path name for nested fields to fetch suggestions', async () => { @@ -194,10 +199,12 @@ describe('use_field_value_autocomplete', () => { }) ); - const expectedResult: UseFieldValueAutocompleteReturn = [false, false, [], result.current[3]]; - await waitFor(() => expect(getValueSuggestionsMock).not.toHaveBeenCalled()); + await waitFor(() => { + const expectedResult: UseFieldValueAutocompleteReturn = [false, false, [], result.current[3]]; - expect(result.current).toEqual(expectedResult); + expect(result.current).toEqual(expectedResult); + expect(getValueSuggestionsMock).not.toHaveBeenCalled(); + }); }); test('returns "isSuggestingValues" of false to note that autocomplete service is not in use if no autocomplete suggestions available', async () => { @@ -218,10 +225,12 @@ describe('use_field_value_autocomplete', () => { }) ); - const expectedResult: UseFieldValueAutocompleteReturn = [false, false, [], result.current[3]]; + await waitFor(() => { + const expectedResult: UseFieldValueAutocompleteReturn = [false, false, [], result.current[3]]; - await waitFor(() => expect(suggestionsMock).toHaveBeenCalled()); - expect(result.current).toEqual(expectedResult); + expect(suggestionsMock).toHaveBeenCalled(); + expect(result.current).toEqual(expectedResult); + }); }); test('returns suggestions', async () => { @@ -241,24 +250,23 @@ describe('use_field_value_autocomplete', () => { }) ); - const expectedResult: UseFieldValueAutocompleteReturn = [ - false, - true, - ['value 1', 'value 2'], - result.current[3], - ]; + await waitFor(() => { + const expectedResult: UseFieldValueAutocompleteReturn = [ + false, + true, + ['value 1', 'value 2'], + result.current[3], + ]; - await waitFor(() => expect(getValueSuggestionsMock).toHaveBeenCalledWith({ field: getField('@tags'), indexPattern: stubIndexPatternWithFields, query: '', signal, useTimeRange: false, - }) - ); - - expect(result.current).toEqual(expectedResult); + }); + expect(result.current).toEqual(expectedResult); + }); }); test('returns new suggestions on subsequent calls', async () => { @@ -290,15 +298,16 @@ describe('use_field_value_autocomplete', () => { }); } - const expectedResult: UseFieldValueAutocompleteReturn = [ - false, - true, - ['value 1', 'value 2'], - result.current[3], - ]; - - await waitFor(() => expect(getValueSuggestionsMock).toHaveBeenCalledTimes(2)); - - expect(result.current).toEqual(expectedResult); + await waitFor(() => { + const expectedResult: UseFieldValueAutocompleteReturn = [ + false, + true, + ['value 1', 'value 2'], + result.current[3], + ]; + + expect(getValueSuggestionsMock).toHaveBeenCalledTimes(2); + expect(result.current).toEqual(expectedResult); + }); }); }); diff --git a/packages/kbn-securitysolution-hook-utils/src/use_async/index.test.ts b/packages/kbn-securitysolution-hook-utils/src/use_async/index.test.ts index 35a190e938e0a..584cc0f822584 100644 --- a/packages/kbn-securitysolution-hook-utils/src/use_async/index.test.ts +++ b/packages/kbn-securitysolution-hook-utils/src/use_async/index.test.ts @@ -48,9 +48,7 @@ describe('useAsync', () => { act(() => { result.current.start(args); }); - await waitFor(() => null, { timeout }); - - expect(fn).toHaveBeenCalled(); + await waitFor(() => expect(fn).toHaveBeenCalled(), { timeout }); }, timeout ); @@ -62,9 +60,7 @@ describe('useAsync', () => { act(() => { result.current.start(args); }); - await waitFor(() => null, { timeout }); - - expect(fn).toHaveBeenCalledWith(expectedArgs); + await waitFor(() => expect(fn).toHaveBeenCalledWith(expectedArgs), { timeout }); }); it( @@ -76,10 +72,13 @@ describe('useAsync', () => { act(() => { result.current.start(args); }); - await waitFor(() => null, { timeout }); - - expect(result.current.result).toEqual({ resolved: 'value' }); - expect(result.current.error).toBeUndefined(); + await waitFor( + () => { + expect(result.current.result).toEqual({ resolved: 'value' }); + expect(result.current.error).toBeUndefined(); + }, + { timeout } + ); }, timeout ); @@ -94,10 +93,13 @@ describe('useAsync', () => { result.current.start(args); }); - await waitFor(() => null, { timeout }); - - expect(result.current.result).toBeUndefined(); - expect(result.current.error).toEqual(new Error('whoops')); + await waitFor( + () => { + expect(result.current.result).toBeUndefined(); + expect(result.current.error).toEqual(new Error('whoops')); + }, + { timeout } + ); }, timeout ); @@ -117,9 +119,7 @@ describe('useAsync', () => { expect(result.current.loading).toBe(true); act(() => resolve()); - await waitFor(() => null, { timeout }); - - expect(result.current.loading).toBe(false); + await waitFor(() => expect(result.current.loading).toBe(false), { timeout }); }, timeout ); @@ -139,10 +139,13 @@ describe('useAsync', () => { expect(result.current.loading).toBe(true); act(() => resolve('result')); - await waitFor(() => null, { timeout }); - - expect(result.current.loading).toBe(false); - expect(result.current.result).toBe('result'); + await waitFor( + () => { + expect(result.current.loading).toBe(false); + expect(result.current.result).toBe('result'); + }, + { timeout } + ); act(() => { result.current.start(args); @@ -151,10 +154,13 @@ describe('useAsync', () => { expect(result.current.loading).toBe(true); expect(result.current.result).toBe(undefined); act(() => resolve('result')); - await waitFor(() => null, { timeout }); - - expect(result.current.loading).toBe(false); - expect(result.current.result).toBe('result'); + await waitFor( + () => { + expect(result.current.loading).toBe(false); + expect(result.current.result).toBe('result'); + }, + { timeout } + ); }, timeout ); diff --git a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue.test.tsx b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue.test.tsx index ae8d3fded83a7..9b476363b0a55 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue.test.tsx @@ -41,7 +41,7 @@ describe('useGetIssue', () => { { wrapper: appMockRender.AppWrapper } ); - await waitFor(() => result.current.isSuccess); + await waitFor(() => expect(result.current.isSuccess).toBe(true)); expect(spy).toHaveBeenCalledWith({ http, @@ -99,9 +99,10 @@ describe('useGetIssue', () => { { wrapper: appMockRender.AppWrapper } ); - await waitFor(() => result.current.isError); - - expect(addError).toHaveBeenCalled(); + await waitFor(() => { + expect(result.current.isError).toBe(true); + expect(addError).toHaveBeenCalled(); + }); }); it('calls addError when the getIssue api returns successfully but contains an error', async () => { @@ -125,8 +126,9 @@ describe('useGetIssue', () => { { wrapper: appMockRender.AppWrapper } ); - await waitFor(() => result.current.isSuccess); - - expect(addError).toHaveBeenCalled(); + await waitFor(() => { + expect(result.current.isSuccess).toBe(true); + expect(addError).toHaveBeenCalled(); + }); }); }); diff --git a/x-pack/plugins/cases/public/components/markdown_editor/use_markdown_session_storage.test.tsx b/x-pack/plugins/cases/public/components/markdown_editor/use_markdown_session_storage.test.tsx index 4d50aabf380b8..6fb4d9743ce51 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/use_markdown_session_storage.test.tsx +++ b/x-pack/plugins/cases/public/components/markdown_editor/use_markdown_session_storage.test.tsx @@ -10,7 +10,6 @@ import { act, waitFor } from '@testing-library/react'; import type { FieldHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import type { SessionStorageType } from './use_markdown_session_storage'; import { useMarkdownSessionStorage } from './use_markdown_session_storage'; -import { waitForComponentToUpdate } from '../../common/test_utils'; describe('useMarkdownSessionStorage', () => { const field = { @@ -102,8 +101,6 @@ describe('useMarkdownSessionStorage', () => { jest.advanceTimersByTime(1000); }); - await waitForComponentToUpdate(); - await waitFor(() => { expect(result.current.hasConflicts).toBe(false); expect(sessionStorage.getItem(sessionKey)).toBe(specialCharsValue); @@ -130,8 +127,6 @@ describe('useMarkdownSessionStorage', () => { jest.advanceTimersByTime(1000); }); - await waitForComponentToUpdate(); - await waitFor(() => { expect(result.current.hasConflicts).toBe(false); expect(sessionStorage.getItem(sessionKey)).toBe('new value'); @@ -172,8 +167,6 @@ describe('useMarkdownSessionStorage', () => { } ); - await waitForComponentToUpdate(); - await waitFor(() => { expect(field.setValue).toHaveBeenCalled(); }); @@ -182,8 +175,6 @@ describe('useMarkdownSessionStorage', () => { jest.advanceTimersByTime(1000); }); - await waitForComponentToUpdate(); - await waitFor(() => { expect(result.current.hasConflicts).toBe(false); expect(field.value).toBe(sessionStorage.getItem(sessionKey)); @@ -200,8 +191,6 @@ describe('useMarkdownSessionStorage', () => { } ); - await waitForComponentToUpdate(); - await waitFor(() => { expect(field.setValue).toHaveBeenCalled(); }); @@ -216,8 +205,6 @@ describe('useMarkdownSessionStorage', () => { jest.advanceTimersByTime(1000); }); - await waitForComponentToUpdate(); - await waitFor(() => { expect(result.current.hasConflicts).toBe(false); expect(sessionStorage.getItem(sessionKey)).toBe('new value'); diff --git a/x-pack/plugins/cases/public/containers/configure/use_get_all_case_configurations.test.ts b/x-pack/plugins/cases/public/containers/configure/use_get_all_case_configurations.test.ts index a50aa3e53b3c2..049eb9cd8a149 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_get_all_case_configurations.test.ts +++ b/x-pack/plugins/cases/public/containers/configure/use_get_all_case_configurations.test.ts @@ -37,35 +37,35 @@ describe('Use get all case configurations hook', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); + await waitFor(() => { + /** + * Ensures that the initial data is returned≠ + * before fetching + */ + // @ts-expect-error: data is defined + expect(result.all[0].data).toEqual([ + { + closureType: 'close-by-user', + connector: { fields: null, id: 'none', name: 'none', type: '.none' }, + customFields: [], + templates: [], + id: '', + mappings: [], + version: '', + owner: '', + }, + ]); - /** - * Ensures that the initial data is returned≠ - * before fetching - */ - // @ts-expect-error: data is defined - expect(result.all[0].data).toEqual([ - { - closureType: 'close-by-user', - connector: { fields: null, id: 'none', name: 'none', type: '.none' }, - customFields: [], - templates: [], - id: '', - mappings: [], - version: '', - owner: '', - }, - ]); - - /** - * The response after fetching - */ - // @ts-expect-error: data is defined - expect(result.all[1].data).toEqual([ - { id: 'my-configuration-1', owner: '1' }, - { id: 'my-configuration-2', owner: '2' }, - { id: 'my-configuration-3', owner: '3' }, - ]); + /** + * The response after fetching + */ + // @ts-expect-error: data is defined + expect(result.all[1].data).toEqual([ + { id: 'my-configuration-1', owner: '1' }, + { id: 'my-configuration-2', owner: '2' }, + { id: 'my-configuration-3', owner: '3' }, + ]); + }); }); it('returns the initial configuration if none is available', async () => { @@ -76,24 +76,24 @@ describe('Use get all case configurations hook', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - - /** - * Ensures that the initial data is returned≠ - * before fetching - */ - // @ts-expect-error: data is defined - expect(result.all[0].data).toEqual([ - { - closureType: 'close-by-user', - connector: { fields: null, id: 'none', name: 'none', type: '.none' }, - customFields: [], - templates: [], - id: '', - mappings: [], - version: '', - owner: '', - }, - ]); + await waitFor(() => { + /** + * Ensures that the initial data is returned≠ + * before fetching + */ + // @ts-expect-error: data is defined + expect(result.all[0].data).toEqual([ + { + closureType: 'close-by-user', + connector: { fields: null, id: 'none', name: 'none', type: '.none' }, + customFields: [], + templates: [], + id: '', + mappings: [], + version: '', + owner: '', + }, + ]); + }); }); }); diff --git a/x-pack/plugins/cases/public/containers/configure/use_get_supported_action_connectors.tsx.test.tsx b/x-pack/plugins/cases/public/containers/configure/use_get_supported_action_connectors.tsx.test.tsx index d28054396665e..e69aa414483c0 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_get_supported_action_connectors.tsx.test.tsx +++ b/x-pack/plugins/cases/public/containers/configure/use_get_supported_action_connectors.tsx.test.tsx @@ -58,8 +58,10 @@ describe('useConnectors', () => { wrapper: ({ children }) => {children}, }); - await waitFor(() => expect(spyOnFetchConnectors).not.toHaveBeenCalled()); - expect(result.current.data).toEqual([]); + await waitFor(() => { + expect(spyOnFetchConnectors).not.toHaveBeenCalled(); + expect(result.current.data).toEqual([]); + }); }); it('does not fetch connectors when the user does not has access to connectors', async () => { @@ -72,8 +74,9 @@ describe('useConnectors', () => { ), }); - await waitFor(() => expect(spyOnFetchConnectors).not.toHaveBeenCalled()); - - expect(result.current.data).toEqual([]); + await waitFor(() => { + expect(spyOnFetchConnectors).not.toHaveBeenCalled(); + expect(result.current.data).toEqual([]); + }); }); }); diff --git a/x-pack/plugins/cases/public/containers/use_find_case_user_actions.test.tsx b/x-pack/plugins/cases/public/containers/use_find_case_user_actions.test.tsx index 6690a7f0be2f0..1d0339a086504 100644 --- a/x-pack/plugins/cases/public/containers/use_find_case_user_actions.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_find_case_user_actions.test.tsx @@ -48,21 +48,21 @@ describe('UseFindCaseUserActions', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - - expect(result.current).toEqual( - expect.objectContaining({ - ...initialData, - data: { - userActions: [...findCaseUserActionsResponse.userActions], - total: 30, - perPage: 10, - page: 1, - }, - isError: false, - isLoading: false, - isFetching: false, - }) + await waitFor(() => + expect(result.current).toEqual( + expect.objectContaining({ + ...initialData, + data: { + userActions: [...findCaseUserActionsResponse.userActions], + total: 30, + perPage: 10, + page: 1, + }, + isError: false, + isLoading: false, + isFetching: false, + }) + ) ); }); @@ -84,12 +84,12 @@ describe('UseFindCaseUserActions', () => { { wrapper: appMockRender.AppWrapper } ); - await waitFor(() => null); - - expect(spy).toHaveBeenCalledWith( - basicCase.id, - { type: 'user', sortOrder: 'desc', page: 1, perPage: 5 }, - expect.any(AbortSignal) + await waitFor(() => + expect(spy).toHaveBeenCalledWith( + basicCase.id, + { type: 'user', sortOrder: 'desc', page: 1, perPage: 5 }, + expect.any(AbortSignal) + ) ); }); @@ -124,13 +124,13 @@ describe('UseFindCaseUserActions', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - - expect(spy).toHaveBeenCalledWith( - basicCase.id, - { type: filterActionType, sortOrder, page: 1, perPage: 10 }, - expect.any(AbortSignal) - ); - expect(addError).toHaveBeenCalled(); + await waitFor(() => { + expect(spy).toHaveBeenCalledWith( + basicCase.id, + { type: filterActionType, sortOrder, page: 1, perPage: 10 }, + expect.any(AbortSignal) + ); + expect(addError).toHaveBeenCalled(); + }); }); }); diff --git a/x-pack/plugins/cases/public/containers/use_get_case_file_stats.test.tsx b/x-pack/plugins/cases/public/containers/use_get_case_file_stats.test.tsx index 3b1c91b810767..c0ec14353452c 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_file_stats.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_file_stats.test.tsx @@ -41,9 +41,9 @@ describe('useGetCaseFileStats', () => { renderHook(() => useGetCaseFileStats(hookParams), { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - - expect(appMockRender.getFilesClient().list).toHaveBeenCalledWith(expectedCallParams); + await waitFor(() => + expect(appMockRender.getFilesClient().list).toHaveBeenCalledWith(expectedCallParams) + ); }); it('shows an error toast when filesClient.list throws', async () => { @@ -57,9 +57,9 @@ describe('useGetCaseFileStats', () => { renderHook(() => useGetCaseFileStats(hookParams), { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - - expect(appMockRender.getFilesClient().list).toHaveBeenCalledWith(expectedCallParams); - expect(addError).toHaveBeenCalled(); + await waitFor(() => { + expect(appMockRender.getFilesClient().list).toHaveBeenCalledWith(expectedCallParams); + expect(addError).toHaveBeenCalled(); + }); }); }); diff --git a/x-pack/plugins/cases/public/containers/use_get_cases_metrics.test.tsx b/x-pack/plugins/cases/public/containers/use_get_cases_metrics.test.tsx index 553983f0bebb2..0a5007169e628 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases_metrics.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases_metrics.test.tsx @@ -38,13 +38,13 @@ describe('useGetCasesMetrics', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - - expect(spy).toHaveBeenCalledWith({ - http: expect.anything(), - signal: abortCtrl.signal, - query: { owner: [SECURITY_SOLUTION_OWNER], features: [CaseMetricsFeature.MTTR] }, - }); + await waitFor(() => + expect(spy).toHaveBeenCalledWith({ + http: expect.anything(), + signal: abortCtrl.signal, + query: { owner: [SECURITY_SOLUTION_OWNER], features: [CaseMetricsFeature.MTTR] }, + }) + ); }); it('shows a toast error when the api return an error', async () => { @@ -56,8 +56,8 @@ describe('useGetCasesMetrics', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - - expect(addError).toHaveBeenCalled(); + await waitFor(() => { + expect(addError).toHaveBeenCalled(); + }); }); }); diff --git a/x-pack/plugins/cases/public/containers/use_get_cases_status.test.tsx b/x-pack/plugins/cases/public/containers/use_get_cases_status.test.tsx index d2337b9728904..ae03644c7dc44 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases_status.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases_status.test.tsx @@ -37,13 +37,13 @@ describe('useGetCasesMetrics', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - - expect(spy).toHaveBeenCalledWith({ - http: expect.anything(), - signal: abortCtrl.signal, - query: { owner: [SECURITY_SOLUTION_OWNER] }, - }); + await waitFor(() => + expect(spy).toHaveBeenCalledWith({ + http: expect.anything(), + signal: abortCtrl.signal, + query: { owner: [SECURITY_SOLUTION_OWNER] }, + }) + ); }); it('shows a toast error when the api return an error', async () => { @@ -55,8 +55,6 @@ describe('useGetCasesMetrics', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - - expect(addError).toHaveBeenCalled(); + await waitFor(() => expect(addError).toHaveBeenCalled()); }); }); diff --git a/x-pack/plugins/cases/public/containers/use_get_categories.test.tsx b/x-pack/plugins/cases/public/containers/use_get_categories.test.tsx index 702715190876d..71ba68eb41834 100644 --- a/x-pack/plugins/cases/public/containers/use_get_categories.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_categories.test.tsx @@ -29,12 +29,12 @@ describe('useGetCategories', () => { wrapper: ({ children }) => {children}, }); - await waitFor(() => null); - - expect(spyOnGetCategories).toBeCalledWith({ - signal: abortCtrl.signal, - owner: [SECURITY_SOLUTION_OWNER], - }); + await waitFor(() => + expect(spyOnGetCategories).toBeCalledWith({ + signal: abortCtrl.signal, + owner: [SECURITY_SOLUTION_OWNER], + }) + ); }); it('displays an error toast when an error occurs', async () => { @@ -50,8 +50,6 @@ describe('useGetCategories', () => { wrapper: ({ children }) => {children}, }); - await waitFor(() => null); - - expect(addError).toBeCalled(); + await waitFor(() => expect(addError).toBeCalled()); }); }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_action_status.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_action_status.test.tsx index 040152d31fffa..86b097bac01d6 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_action_status.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_action_status.test.tsx @@ -6,7 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; -import { act } from '@testing-library/react'; +import { act, waitFor } from '@testing-library/react'; import { sendGetActionStatus, sendPostCancelAction, useStartServices } from '../../../../hooks'; @@ -64,20 +64,15 @@ describe('useActionStatus', () => { it('should refresh statuses on refresh flag', async () => { let refresh = false; - await act(async () => { - const result = renderHook(() => useActionStatus(mockOnAbortSuccess, refresh, 20, null)); - refresh = true; - result.rerender(); - }); - expect(mockSendGetActionStatus).toHaveBeenCalledTimes(5); + const result = renderHook(() => useActionStatus(mockOnAbortSuccess, refresh, 20, null)); + refresh = true; + result.rerender(); + await waitFor(() => expect(mockSendGetActionStatus).toHaveBeenCalled()); }); it('should post cancel and invoke callback on cancel upgrade', async () => { mockSendPostCancelAction.mockResolvedValue({}); - let result: any | undefined; - await act(async () => { - ({ result } = renderHook(() => useActionStatus(mockOnAbortSuccess, false, 20, null))); - }); + const { result } = renderHook(() => useActionStatus(mockOnAbortSuccess, false, 20, null)); await act(async () => { await result.current.abortUpgrade(mockActionStatuses[0]); }); @@ -90,10 +85,7 @@ describe('useActionStatus', () => { it('should post cancel and invoke callback on cancel upgrade - plural', async () => { mockSendPostCancelAction.mockResolvedValue({}); - let result: any | undefined; - await act(async () => { - ({ result } = renderHook(() => useActionStatus(mockOnAbortSuccess, false, 20, null))); - }); + const { result } = renderHook(() => useActionStatus(mockOnAbortSuccess, false, 20, null)); await act(async () => { await result.current.abortUpgrade({ ...mockActionStatuses[0], nbAgentsAck: 0 }); }); @@ -107,10 +99,7 @@ describe('useActionStatus', () => { it('should report error on cancel upgrade failure', async () => { const error = new Error('error'); mockSendPostCancelAction.mockRejectedValue(error); - let result: any | undefined; - await act(async () => { - ({ result } = renderHook(() => useActionStatus(mockOnAbortSuccess, false, 20, null))); - }); + const { result } = renderHook(() => useActionStatus(mockOnAbortSuccess, false, 20, null)); await act(async () => { await result.current.abortUpgrade(mockActionStatuses[0]); }); diff --git a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_list.test.ts b/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_list.test.ts index 6cb70feb49b68..e23edeeb52636 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_list.test.ts +++ b/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_list.test.ts @@ -46,43 +46,46 @@ describe('usePersistExceptionList', () => { }); test('"isLoading" is "true" when exception item is being saved', async () => { - await act(async () => { - const { result, rerender } = renderHook(() => - usePersistExceptionList({ http: mockKibanaHttpService, onError }) - ); - await waitFor(() => null); - result.current[1](getCreateExceptionListSchemaMock()); - rerender(); + const { result, rerender } = renderHook(() => + usePersistExceptionList({ http: mockKibanaHttpService, onError }) + ); + await waitFor(() => null); + result.current[1](getCreateExceptionListSchemaMock()); + rerender(); - expect(result.current).toEqual([{ isLoading: true, isSaved: false }, result.current[1]]); - }); + expect(result.current).toEqual([{ isLoading: true, isSaved: false }, result.current[1]]); }); test('"isSaved" is "true" when exception item saved successfully', async () => { - await act(async () => { - const { result } = renderHook(() => - usePersistExceptionList({ http: mockKibanaHttpService, onError }) - ); - await waitFor(() => null); - result.current[1](getCreateExceptionListSchemaMock()); - await waitFor(() => null); + const { result } = renderHook(() => + usePersistExceptionList({ http: mockKibanaHttpService, onError }) + ); - expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); + await waitFor(() => null); + + act(() => { + result.current[1](getCreateExceptionListSchemaMock()); }); + + await waitFor(() => + expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]) + ); }); test('it invokes "updateExceptionList" when payload has "id"', async () => { const addException = jest.spyOn(api, 'addExceptionList'); const updateException = jest.spyOn(api, 'updateExceptionList'); - await act(async () => { - const { result } = renderHook(() => - usePersistExceptionList({ http: mockKibanaHttpService, onError }) - ); + const { result } = renderHook(() => + usePersistExceptionList({ http: mockKibanaHttpService, onError }) + ); + + await waitFor(() => null); - await waitFor(() => null); + act(() => { result.current[1](getUpdateExceptionListSchemaMock()); - await waitFor(() => null); + }); + await waitFor(() => { expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); expect(addException).not.toHaveBeenCalled(); expect(updateException).toHaveBeenCalled(); @@ -93,14 +96,14 @@ describe('usePersistExceptionList', () => { const error = new Error('persist rule failed'); jest.spyOn(api, 'addExceptionList').mockRejectedValue(error); - await act(async () => { - const { result } = renderHook(() => - usePersistExceptionList({ http: mockKibanaHttpService, onError }) - ); - await waitFor(() => null); + const { result } = renderHook(() => + usePersistExceptionList({ http: mockKibanaHttpService, onError }) + ); + await waitFor(() => null); + act(() => { result.current[1](getCreateExceptionListSchemaMock()); - await waitFor(() => null); - + }); + await waitFor(() => { expect(result.current).toEqual([{ isLoading: false, isSaved: false }, result.current[1]]); expect(onError).toHaveBeenCalledWith(error); }); 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 8f65f8d22ef15..2e3ad3c371f37 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 @@ -172,14 +172,10 @@ describe('useFetchAlertDetail', () => { }); it('does not populate the results when the request is canceled', async () => { - // FIXME: this test cases doesn't do what the suite claims it does - const { result, unmount } = renderHook(() => useFetchAlertDetail('123') ); - await waitFor(() => null); - act(() => { unmount(); }); diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.test.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.test.tsx index e82bcf1e4c369..172d9d4b5c8ee 100644 --- a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.test.tsx @@ -89,23 +89,26 @@ describe('useHostIsolationAction', () => { const { result } = render(); - expect(result.current).toEqual([ - buildExpectedMenuItemResult({ - ...(command === 'unisolate' ? { name: UNISOLATE_HOST } : {}), - }), - ]); + await appContextMock.waitFor(() => + expect(result.current).toEqual([ + buildExpectedMenuItemResult({ + ...(command === 'unisolate' ? { name: UNISOLATE_HOST } : {}), + }), + ]) + ); } ); it('should call `closePopover` callback when menu item `onClick` is called', async () => { const { result } = render(); - await appContextMock.waitFor(() => result.current); + await appContextMock.waitFor(() => expect(result.current[0].onClick).toBeDefined()); + result.current[0].onClick!({} as unknown as React.MouseEvent); expect(hookProps.closePopover).toHaveBeenCalled(); }); - it('should NOT return the menu item for Events', () => { + it('should NOT return the menu item for Events', async () => { hookProps.detailsData = endpointAlertDataMock.generateAlertDetailsItemDataForAgentType('foo', { 'kibana.alert.rule.uuid': undefined, }); @@ -134,12 +137,14 @@ describe('useHostIsolationAction', () => { it('should return disabled menu item while loading agent status', async () => { const { result } = render(); - expect(result.current).toEqual([ - buildExpectedMenuItemResult({ - disabled: true, - toolTipContent: LOADING_ENDPOINT_DATA_TOOLTIP, - }), - ]); + await appContextMock.waitFor(() => + expect(result.current).toEqual([ + buildExpectedMenuItemResult({ + disabled: true, + toolTipContent: LOADING_ENDPOINT_DATA_TOOLTIP, + }), + ]) + ); }); it.each(['endpoint', 'non-endpoint'])( @@ -156,21 +161,23 @@ describe('useHostIsolationAction', () => { hookProps.detailsData = endpointAlertDataMock.generateSentinelOneAlertDetailsItemData(); } const { result } = render(); - await appContextMock.waitFor(() => result.current); - - expect(result.current).toEqual([ - buildExpectedMenuItemResult({ - disabled: true, - toolTipContent: - type === 'endpoint' ? HOST_ENDPOINT_UNENROLLED_TOOLTIP : NOT_FROM_ENDPOINT_HOST_TOOLTIP, - }), - ]); + await appContextMock.waitFor(() => + expect(result.current).toEqual([ + buildExpectedMenuItemResult({ + disabled: true, + toolTipContent: + type === 'endpoint' + ? HOST_ENDPOINT_UNENROLLED_TOOLTIP + : NOT_FROM_ENDPOINT_HOST_TOOLTIP, + }), + ]) + ); } ); it('should call isolate API when agent is currently NOT isolated', async () => { const { result } = render(); - await appContextMock.waitFor(() => result.current); + await appContextMock.waitFor(() => expect(result.current[0].onClick).toBeDefined()); result.current[0].onClick!({} as unknown as React.MouseEvent); expect(hookProps.onAddIsolationStatusClick).toHaveBeenCalledWith('isolateHost'); @@ -183,9 +190,13 @@ describe('useHostIsolationAction', () => { }) ); const { result } = render(); - await appContextMock.waitFor(() => result.current); + + await appContextMock.waitFor(() => expect(result.current[0].onClick).toBeDefined()); + result.current[0].onClick!({} as unknown as React.MouseEvent); - expect(hookProps.onAddIsolationStatusClick).toHaveBeenCalledWith('unisolateHost'); + await appContextMock.waitFor(() => + expect(hookProps.onAddIsolationStatusClick).toHaveBeenCalledWith('unisolateHost') + ); }); }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring/components/execution_events_table/use_execution_events.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring/components/execution_events_table/use_execution_events.test.tsx index f53f104c13738..14fc30c428dd8 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring/components/execution_events_table/use_execution_events.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring/components/execution_events_table/use_execution_events.test.tsx @@ -59,28 +59,28 @@ describe('useExecutionEvents', () => { expect(result.current.isError).toEqual(false); // When fetchRuleExecutionEvents returns - await waitFor(() => null); - - // It switches to a success state - expect(result.current.isLoading).toEqual(false); - expect(result.current.isSuccess).toEqual(true); - expect(result.current.isError).toEqual(false); - expect(result.current.data).toEqual({ - events: [ - { - timestamp: '2021-12-29T10:42:59.996Z', - sequence: 0, - level: LogLevelEnum.info, - type: RuleExecutionEventTypeEnum['status-change'], - execution_id: 'execution-id-1', - message: 'Rule changed status to "succeeded". Rule execution completed without errors', + await waitFor(() => { + // It switches to a success state + expect(result.current.isLoading).toEqual(false); + expect(result.current.isSuccess).toEqual(true); + expect(result.current.isError).toEqual(false); + expect(result.current.data).toEqual({ + events: [ + { + timestamp: '2021-12-29T10:42:59.996Z', + sequence: 0, + level: LogLevelEnum.info, + type: RuleExecutionEventTypeEnum['status-change'], + execution_id: 'execution-id-1', + message: 'Rule changed status to "succeeded". Rule execution completed without errors', + }, + ], + pagination: { + page: 1, + per_page: 20, + total: 1, }, - ], - pagination: { - page: 1, - per_page: 20, - total: 1, - }, + }); }); }); @@ -96,18 +96,18 @@ describe('useExecutionEvents', () => { expect(result.current.isError).toEqual(false); // When fetchRuleExecutionEvents throws - await waitFor(() => null); - - // It switches to an error state - expect(result.current.isLoading).toEqual(false); - expect(result.current.isSuccess).toEqual(false); - expect(result.current.isError).toEqual(true); - expect(result.current.error).toEqual(exception); - - // And shows a toast with the caught exception - expect(useToasts().addError).toHaveBeenCalledTimes(1); - expect(useToasts().addError).toHaveBeenCalledWith(exception, { - title: 'Failed to fetch rule execution events', + await waitFor(() => { + // It switches to an error state + expect(result.current.isLoading).toEqual(false); + expect(result.current.isSuccess).toEqual(false); + expect(result.current.isError).toEqual(true); + expect(result.current.error).toEqual(exception); + + // And shows a toast with the caught exception + expect(useToasts().addError).toHaveBeenCalledTimes(1); + expect(useToasts().addError).toHaveBeenCalledWith(exception, { + title: 'Failed to fetch rule execution events', + }); }); }); }); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx index 4453209de741f..7ad10c08deb0d 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx @@ -36,15 +36,13 @@ describe('useSignalIndex', () => { wrapper: TestProvidersWithPrivileges, }); - await waitFor(() => - expect(result.current).toEqual({ - createDeSignalIndex: null, - loading: true, - signalIndexExists: null, - signalIndexName: null, - signalIndexMappingOutdated: null, - }) - ); + expect(result.current).toEqual({ + createDeSignalIndex: null, + loading: true, + signalIndexExists: null, + signalIndexName: null, + signalIndexMappingOutdated: null, + }); }); test('fetch alerts info', async () => { @@ -55,14 +53,15 @@ describe('useSignalIndex', () => { } ); - await waitFor(() => expect(result.current.loading).toBe(false)); - - expect(result.current).toEqual({ - createDeSignalIndex: result.current.createDeSignalIndex, - loading: false, - signalIndexExists: true, - signalIndexName: 'mock-signal-index', - signalIndexMappingOutdated: false, + await waitFor(() => { + expect(result.current.loading).toBe(false); + expect(result.current).toEqual({ + createDeSignalIndex: result.current.createDeSignalIndex, + loading: false, + signalIndexExists: true, + signalIndexName: 'mock-signal-index', + signalIndexMappingOutdated: false, + }); }); }); @@ -79,13 +78,15 @@ describe('useSignalIndex', () => { await result.current.createDeSignalIndex(); }); - expect(result.current).toEqual({ - createDeSignalIndex: result.current.createDeSignalIndex, - loading: false, - signalIndexExists: true, - signalIndexName: 'mock-signal-index', - signalIndexMappingOutdated: false, - }); + await waitFor(() => + expect(result.current).toEqual({ + createDeSignalIndex: result.current.createDeSignalIndex, + loading: false, + signalIndexExists: true, + signalIndexName: 'mock-signal-index', + signalIndexMappingOutdated: false, + }) + ); }); test('make sure that createSignalIndex have been called when trying to create signal index', async () => { @@ -124,13 +125,15 @@ describe('useSignalIndex', () => { await result.current.createDeSignalIndex(); }); - expect(result.current).toEqual({ - createDeSignalIndex: result.current.createDeSignalIndex, - loading: false, - signalIndexExists: false, - signalIndexName: null, - signalIndexMappingOutdated: null, - }); + await waitFor(() => + expect(result.current).toEqual({ + createDeSignalIndex: result.current.createDeSignalIndex, + loading: false, + signalIndexExists: false, + signalIndexName: null, + signalIndexMappingOutdated: null, + }) + ); }); test('if there is an error when fetching alerts info, signalIndexExists === false && signalIndexName == null', async () => { @@ -151,13 +154,15 @@ describe('useSignalIndex', () => { await result.current.createDeSignalIndex(); }); - expect(result.current).toEqual({ - createDeSignalIndex: result.current.createDeSignalIndex, - loading: false, - signalIndexExists: false, - signalIndexName: null, - signalIndexMappingOutdated: null, - }); + await waitFor(() => + expect(result.current).toEqual({ + createDeSignalIndex: result.current.createDeSignalIndex, + loading: false, + signalIndexExists: false, + signalIndexName: null, + signalIndexMappingOutdated: null, + }) + ); }); test('should not make API calls when signal index already stored in sourcerer', async () => { @@ -174,14 +179,15 @@ describe('useSignalIndex', () => { } ); - await waitFor(() => expect(spyOnGetSignalIndex).not.toHaveBeenCalled()); - - expect(result.current).toEqual({ - createDeSignalIndex: result.current.createDeSignalIndex, - loading: false, - signalIndexExists: true, - signalIndexName: 'mock-signal-index-from-sourcerer', - signalIndexMappingOutdated: false, + await waitFor(() => { + expect(spyOnGetSignalIndex).not.toHaveBeenCalled(); + expect(result.current).toEqual({ + createDeSignalIndex: result.current.createDeSignalIndex, + loading: false, + signalIndexExists: true, + signalIndexName: 'mock-signal-index-from-sourcerer', + signalIndexMappingOutdated: false, + }); }); }); }); diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality/use_asset_criticality.test.ts b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality/use_asset_criticality.test.ts index d4671a5bc628a..df9e39022f1e3 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality/use_asset_criticality.test.ts +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality/use_asset_criticality.test.ts @@ -5,7 +5,11 @@ * 2.0. */ -import { renderMutation, renderQuery } from '../../../management/hooks/test_utils'; +import { + renderMutation, + renderQuery, + renderWrappedHook, +} from '../../../management/hooks/test_utils'; import type { Entity } from './use_asset_criticality'; import { useAssetCriticalityPrivileges, useAssetCriticalityData } from './use_asset_criticality'; @@ -69,10 +73,7 @@ describe('useAssetCriticality', () => { mockCreateAssetCriticality.mockResolvedValue({}); const entity: Entity = { name: 'test_entity_name', type: 'host' }; - const { mutation } = await renderQuery( - () => useAssetCriticalityData({ entity }), - 'isSuccess' - ); + const { mutation } = await renderWrappedHook(() => useAssetCriticalityData({ entity })); await renderMutation(async () => mutation.mutate({ @@ -91,10 +92,7 @@ describe('useAssetCriticality', () => { mockCreateAssetCriticality.mockResolvedValue({}); const entity: Entity = { name: 'test_entity_name', type: 'host' }; - const { mutation } = await renderQuery( - () => useAssetCriticalityData({ entity }), - 'isSuccess' - ); + const { mutation } = await renderWrappedHook(() => useAssetCriticalityData({ entity })); await renderMutation(async () => mutation.mutate({ diff --git a/x-pack/plugins/security_solution/public/management/hooks/test_utils.tsx b/x-pack/plugins/security_solution/public/management/hooks/test_utils.tsx index 4152c7e708ead..1f1d01ff50d7d 100644 --- a/x-pack/plugins/security_solution/public/management/hooks/test_utils.tsx +++ b/x-pack/plugins/security_solution/public/management/hooks/test_utils.tsx @@ -43,7 +43,7 @@ export const renderQuery = async ( const { result: resultHook } = renderHook(() => hook(), { wrapper, }); - await waitFor(() => resultHook.current[waitForHook]); + await waitFor(() => expect(resultHook.current[waitForHook]).toBeTruthy()); return resultHook.current; }; @@ -59,3 +59,5 @@ export const renderMutation = async ( }); return resultHook.current; }; + +export const renderWrappedHook = renderMutation; diff --git a/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx index 7c27b6b0ad0c4..f5a76bbf752e3 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx @@ -170,22 +170,22 @@ describe('useTimelineEvents', () => { await waitFor(() => null); rerender({ ...props, startDate, endDate }); // useEffect on params request - await waitFor(() => null); - - expect(mockSearch).toHaveBeenCalledTimes(2); - expect(result.current).toEqual([ - DataLoadingState.loaded, - { - events: mockEvents, - id: TimelineId.active, - inspect: result.current[1].inspect, - loadPage: result.current[1].loadPage, - pageInfo: result.current[1].pageInfo, - refetch: result.current[1].refetch, - totalCount: 32, - refreshedAt: result.current[1].refreshedAt, - }, - ]); + await waitFor(() => { + expect(mockSearch).toHaveBeenCalledTimes(2); + expect(result.current).toEqual([ + DataLoadingState.loaded, + { + events: mockEvents, + id: TimelineId.active, + inspect: result.current[1].inspect, + loadPage: result.current[1].loadPage, + pageInfo: result.current[1].pageInfo, + refetch: result.current[1].refetch, + totalCount: 32, + refreshedAt: result.current[1].refreshedAt, + }, + ]); + }); }); test('Mock cache for active timeline when switching page', async () => { @@ -268,8 +268,7 @@ describe('useTimelineEvents', () => { act(() => { result.current[1].loadPage(4); }); - await waitFor(() => null); - expect(mockSearch).toHaveBeenCalledTimes(1); + await waitFor(() => expect(mockSearch).toHaveBeenCalledTimes(1)); }); test('should query again when a new field is added', async () => { @@ -296,9 +295,7 @@ describe('useTimelineEvents', () => { fields: ['@timestamp', 'event.kind', 'event.category'], }); - await waitFor(() => null); - - expect(mockSearch).toHaveBeenCalledTimes(1); + await waitFor(() => expect(mockSearch).toHaveBeenCalledTimes(1)); }); test('should not query again when a field is removed', async () => { @@ -320,9 +317,7 @@ describe('useTimelineEvents', () => { rerender({ ...props, startDate, endDate, fields: ['@timestamp'] }); - await waitFor(() => null); - - expect(mockSearch).toHaveBeenCalledTimes(0); + await waitFor(() => expect(mockSearch).toHaveBeenCalledTimes(0)); }); test('should not query again when a removed field is added back', async () => { const { rerender } = renderHook<[DataLoadingState, TimelineArgs], UseTimelineEventsProps>( @@ -353,9 +348,7 @@ describe('useTimelineEvents', () => { // since there is no new update in useEffect, it should throw an timeout error // await expect(waitFor(() => null)).rejects.toThrowError(); - await waitFor(() => null); - - expect(mockSearch).toHaveBeenCalledTimes(0); + await waitFor(() => expect(mockSearch).toHaveBeenCalledTimes(0)); }); describe('Fetch Notes', () => { @@ -367,10 +360,10 @@ describe('useTimelineEvents', () => { } ); - await waitFor(() => null); - - expect(mockSearch).toHaveBeenCalledTimes(1); - expect(onLoadMock).toHaveBeenNthCalledWith(1, expect.objectContaining(mockEvents)); + await waitFor(() => { + expect(mockSearch).toHaveBeenCalledTimes(1); + expect(onLoadMock).toHaveBeenNthCalledWith(1, expect.objectContaining(mockEvents)); + }); }); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations.test.tsx index cf2df1fd37ded..fc6d79fe7c62e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_aggregations.test.tsx @@ -84,7 +84,7 @@ describe('useLoadRuleAggregations', () => { rerender(); - await waitFor(() => + await waitFor(() => { expect(loadRuleAggregationsWithKueryFilter).toBeCalledWith( expect.objectContaining({ searchText: '', @@ -95,10 +95,9 @@ describe('useLoadRuleAggregations', () => { ruleStatusesFilter: [], tagsFilter: [], }) - ) - ); - - expect(result.current.rulesStatusesTotal).toEqual(MOCK_AGGS.ruleExecutionStatus); + ); + expect(result.current.rulesStatusesTotal).toEqual(MOCK_AGGS.ruleExecutionStatus); + }); }); it('should call loadRuleAggregation API with params and handle result', async () => { @@ -123,7 +122,7 @@ describe('useLoadRuleAggregations', () => { rerender(); - await waitFor(() => + await waitFor(() => { expect(loadRuleAggregationsWithKueryFilter).toBeCalledWith( expect.objectContaining({ searchText: 'test', @@ -134,10 +133,9 @@ describe('useLoadRuleAggregations', () => { tagsFilter: ['tag1', 'tag2'], ruleLastRunOutcomesFilter: ['outcome1', 'outcome2'], }) - ) - ); - - expect(result.current.rulesStatusesTotal).toEqual(MOCK_AGGS.ruleExecutionStatus); + ); + expect(result.current.rulesStatusesTotal).toEqual(MOCK_AGGS.ruleExecutionStatus); + }); }); it('should call onError if API fails', async () => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_tags_query.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_tags_query.test.tsx index 0cdc676db6015..5b53110909135 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_tags_query.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_tags_query.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ import React from 'react'; -import { renderHook, waitFor } from '@testing-library/react'; +import { waitFor } from '@testing-library/react'; +import { renderHook } from '@testing-library/react-hooks'; import { useLoadTagsQuery } from './use_load_tags_query'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useKibana } from '../../common/lib/kibana'; @@ -66,18 +67,18 @@ describe('useLoadTagsQuery', () => { ); rerender(); - await waitFor(() => null); - - expect(loadRuleTags).toHaveBeenLastCalledWith( - expect.objectContaining({ - search: 'test', - perPage: 50, - page: 1, - }) - ); + await waitFor(() => { + expect(loadRuleTags).toHaveBeenLastCalledWith( + expect.objectContaining({ + search: 'test', + perPage: 50, + page: 1, + }) + ); - expect(result.current.tags).toEqual(MOCK_TAGS); - expect(result.current.hasNextPage).toEqual(false); + expect(result.current.tags).toEqual(MOCK_TAGS); + expect(result.current.hasNextPage).toEqual(false); + }); }); it('should support pagination', async () => { @@ -100,17 +101,17 @@ describe('useLoadTagsQuery', () => { ); rerender(); - await waitFor(() => null); - - expect(loadRuleTags).toHaveBeenLastCalledWith( - expect.objectContaining({ - perPage: 5, - page: 1, - }) - ); + await waitFor(() => { + expect(loadRuleTags).toHaveBeenLastCalledWith( + expect.objectContaining({ + perPage: 5, + page: 1, + }) + ); - expect(result.current.tags).toEqual(['a', 'b', 'c', 'd', 'e']); - expect(result.current.hasNextPage).toEqual(true); + expect(result.current.tags).toEqual(['a', 'b', 'c', 'd', 'e']); + expect(result.current.hasNextPage).toEqual(true); + }); loadRuleTags.mockResolvedValue({ data: ['a', 'b', 'c', 'd', 'e'], @@ -118,6 +119,7 @@ describe('useLoadTagsQuery', () => { perPage: 5, total: 10, }); + result.current.fetchNextPage(); expect(loadRuleTags).toHaveBeenLastCalledWith( @@ -128,9 +130,7 @@ describe('useLoadTagsQuery', () => { ); rerender(); - await waitFor(() => null); - - expect(result.current.hasNextPage).toEqual(false); + await waitFor(() => expect(result.current.hasNextPage).toEqual(false)); }); it('should support pagination when there are no tags', async () => { @@ -154,17 +154,17 @@ describe('useLoadTagsQuery', () => { ); rerender(); - await waitFor(() => null); - - expect(loadRuleTags).toHaveBeenLastCalledWith( - expect.objectContaining({ - perPage: 5, - page: 1, - }) - ); + await waitFor(() => { + expect(loadRuleTags).toHaveBeenLastCalledWith( + expect.objectContaining({ + perPage: 5, + page: 1, + }) + ); - expect(result.current.tags).toEqual([]); - expect(result.current.hasNextPage).toEqual(false); + expect(result.current.tags).toEqual([]); + expect(result.current.hasNextPage).toEqual(false); + }); }); it('should call onError if API fails', async () => { From f7c18e322abb04720d8162d83d751801bb4e30ef Mon Sep 17 00:00:00 2001 From: Eyo Okon Eyo Date: Thu, 10 Oct 2024 17:20:20 +0100 Subject: [PATCH 10/18] fix types --- .../public/containers/use_messages_storage.test.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/cases/public/containers/use_messages_storage.test.tsx b/x-pack/plugins/cases/public/containers/use_messages_storage.test.tsx index b57952a75c08b..37c71a1c84fe6 100644 --- a/x-pack/plugins/cases/public/containers/use_messages_storage.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_messages_storage.test.tsx @@ -19,7 +19,7 @@ describe('useMessagesStorage', () => { }); it('should return an empty array when there is no messages', async () => { - const { result } = renderHook(() => useMessagesStorage()); + const { result } = renderHook(() => useMessagesStorage()); await waitFor(() => null); const { getMessages } = result.current; await act(async () => { @@ -28,7 +28,7 @@ describe('useMessagesStorage', () => { }); it('should add a message', async () => { - const { result } = renderHook(() => useMessagesStorage()); + const { result } = renderHook(() => useMessagesStorage()); await waitFor(() => null); const { getMessages, addMessage } = result.current; await act(async () => { @@ -38,7 +38,7 @@ describe('useMessagesStorage', () => { }); it('should add multiple messages', async () => { - const { result } = renderHook(() => useMessagesStorage()); + const { result } = renderHook(() => useMessagesStorage()); await waitFor(() => null); const { getMessages, addMessage } = result.current; await act(async () => { @@ -49,7 +49,7 @@ describe('useMessagesStorage', () => { }); it('should remove a message', async () => { - const { result } = renderHook(() => useMessagesStorage()); + const { result } = renderHook(() => useMessagesStorage()); await waitFor(() => null); const { getMessages, addMessage, removeMessage } = result.current; await act(async () => { @@ -61,7 +61,7 @@ describe('useMessagesStorage', () => { }); it('should return presence of a message', async () => { - const { result } = renderHook(() => useMessagesStorage()); + const { result } = renderHook(() => useMessagesStorage()); await waitFor(() => null); const { hasMessage, addMessage, removeMessage } = result.current; await act(async () => { @@ -74,7 +74,7 @@ describe('useMessagesStorage', () => { }); it('should clear all messages', async () => { - const { result } = renderHook(() => useMessagesStorage()); + const { result } = renderHook(() => useMessagesStorage()); await waitFor(() => null); const { getMessages, addMessage, clearAllMessages } = result.current; await act(async () => { From f8cc83ffbb06463927cf399a71af86e7588afdb3 Mon Sep 17 00:00:00 2001 From: Eyo Okon Eyo Date: Thu, 10 Oct 2024 17:32:47 +0100 Subject: [PATCH 11/18] more adoption of waitFor assertion callbacks --- .../use_fetch_alerts_fields_query.test.tsx | 58 +++++---- .../hooks/use_edit_visualization.test.ts | 15 +-- .../public/utils/use/use_ui_state.test.ts | 22 ++-- .../connectors/jira/use_get_issues.test.tsx | 29 +++-- .../use_get_case_configuration.test.tsx | 16 +-- .../containers/use_delete_comment.test.tsx | 62 +++++----- .../containers/use_get_case_files.test.tsx | 14 +-- .../containers/use_get_case_metrics.test.tsx | 13 +- .../use_suggest_user_profiles.test.ts | 22 ++-- .../hooks/persist_exception_item.test.ts | 7 +- .../hooks/use_metrics_explorer_data.test.tsx | 30 +++-- .../public/hooks/use_fetch_alert_data.test.ts | 6 +- .../hooks/use_fetch_alert_detail.test.ts | 112 +++++++++--------- .../use_host_isolation_action.test.tsx | 26 ++-- .../alerts/use_signal_index.test.tsx | 2 +- .../hooks/use_critical_alerts.test.tsx | 4 +- .../timelines/containers/index.test.tsx | 2 +- 17 files changed, 230 insertions(+), 210 deletions(-) diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.test.tsx index 37386027c6fa4..915622b7363b5 100644 --- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_alerts_fields_query.test.tsx @@ -96,28 +96,30 @@ describe('useFetchAlertsFieldsQuery', () => { } ); - await waitFor(() => result.current.data); - - expect(mockHttpGet).toHaveBeenCalledTimes(1); - expect(result.current.data).toEqual({ - browserFields: { fakeCategory: {} }, - fields: [ - { - name: 'fakeCategory', - }, - ], + await waitFor(() => { + expect(mockHttpGet).toHaveBeenCalledTimes(1); + expect(result.current.data).toEqual({ + browserFields: { fakeCategory: {} }, + fields: [ + { + name: 'fakeCategory', + }, + ], + }); }); rerender(); - expect(mockHttpGet).toHaveBeenCalledTimes(1); - expect(result.current.data).toEqual({ - browserFields: { fakeCategory: {} }, - fields: [ - { - name: 'fakeCategory', - }, - ], + await waitFor(() => { + expect(mockHttpGet).toHaveBeenCalledTimes(1); + expect(result.current.data).toEqual({ + browserFields: { fakeCategory: {} }, + fields: [ + { + name: 'fakeCategory', + }, + ], + }); }); }); @@ -133,8 +135,10 @@ describe('useFetchAlertsFieldsQuery', () => { } ); - expect(mockHttpGet).toHaveBeenCalledTimes(0); - expect(result.current.data).toEqual(emptyData); + await waitFor(() => { + expect(mockHttpGet).toHaveBeenCalledTimes(0); + expect(result.current.data).toEqual(emptyData); + }); }); it('should not fetch if all featureId are not valid', async () => { @@ -149,8 +153,10 @@ describe('useFetchAlertsFieldsQuery', () => { } ); - expect(mockHttpGet).toHaveBeenCalledTimes(0); - expect(result.current.data).toEqual(emptyData); + await waitFor(() => { + expect(mockHttpGet).toHaveBeenCalledTimes(0); + expect(result.current.data).toEqual(emptyData); + }); }); it('should filter out the non valid feature id', async () => { @@ -165,9 +171,11 @@ describe('useFetchAlertsFieldsQuery', () => { } ); - expect(mockHttpGet).toHaveBeenCalledTimes(1); - expect(mockHttpGet).toHaveBeenCalledWith('/internal/rac/alerts/browser_fields', { - query: { featureIds: ['apm', 'logs'] }, + await waitFor(() => { + expect(mockHttpGet).toHaveBeenCalledTimes(1); + expect(mockHttpGet).toHaveBeenCalledWith('/internal/rac/alerts/browser_fields', { + query: { featureIds: ['apm', 'logs'] }, + }); }); }); }); diff --git a/src/plugins/unified_histogram/public/chart/hooks/use_edit_visualization.test.ts b/src/plugins/unified_histogram/public/chart/hooks/use_edit_visualization.test.ts index 5886e1469a4cf..ce6eae51664c2 100644 --- a/src/plugins/unified_histogram/public/chart/hooks/use_edit_visualization.test.ts +++ b/src/plugins/unified_histogram/public/chart/hooks/use_edit_visualization.test.ts @@ -62,8 +62,7 @@ describe('useEditVisualization', () => { lensAttributes: {} as unknown as TypedLensByValueInput['attributes'], }) ); - await waitFor(() => null); - expect(hook.result.current).toBeUndefined(); + await waitFor(() => expect(hook.result.current).toBeUndefined()); }); it('should return undefined if the data view is not time based', async () => { @@ -76,8 +75,7 @@ describe('useEditVisualization', () => { lensAttributes: {} as unknown as TypedLensByValueInput['attributes'], }) ); - await waitFor(() => null); - expect(hook.result.current).toBeUndefined(); + await waitFor(() => expect(hook.result.current).toBeUndefined()); }); it('should return undefined if is on text based mode', async () => { @@ -91,8 +89,7 @@ describe('useEditVisualization', () => { isPlainRecord: true, }) ); - await waitFor(() => null); - expect(hook.result.current).toBeUndefined(); + await waitFor(() => expect(hook.result.current).toBeUndefined()); }); it('should return undefined if the time field is not visualizable', async () => { @@ -111,8 +108,7 @@ describe('useEditVisualization', () => { lensAttributes: {} as unknown as TypedLensByValueInput['attributes'], }) ); - await waitFor(() => null); - expect(hook.result.current).toBeUndefined(); + await waitFor(() => expect(hook.result.current).toBeUndefined()); }); it('should return undefined if there are no compatible actions', async () => { @@ -125,7 +121,6 @@ describe('useEditVisualization', () => { lensAttributes: {} as unknown as TypedLensByValueInput['attributes'], }) ); - await waitFor(() => null); - expect(hook.result.current).toBeUndefined(); + await waitFor(() => expect(hook.result.current).toBeUndefined()); }); }); diff --git a/src/plugins/vis_types/table/public/utils/use/use_ui_state.test.ts b/src/plugins/vis_types/table/public/utils/use/use_ui_state.test.ts index 6e46efeaf8345..a1bf97ec40013 100644 --- a/src/plugins/vis_types/table/public/utils/use/use_ui_state.test.ts +++ b/src/plugins/vis_types/table/public/utils/use/use_ui_state.test.ts @@ -62,18 +62,18 @@ describe('useUiState', () => { updateOnChange(); }); - await waitFor(() => null); - // should update local state with new values - expect(result.current).toEqual({ - columnsWidth: [], - sort: { - columnIndex: 1, - direction: 'asc', - }, - setColumnsWidth: expect.any(Function), - setSort: expect.any(Function), - }); + await waitFor(() => + expect(result.current).toEqual({ + columnsWidth: [], + sort: { + columnIndex: 1, + direction: 'asc', + }, + setColumnsWidth: expect.any(Function), + setSort: expect.any(Function), + }) + ); act(() => { updateOnChange(); diff --git a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issues.test.tsx b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issues.test.tsx index 2edb0ac38e377..5f57e7297aea2 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issues.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issues.test.tsx @@ -41,13 +41,14 @@ describe('useGetIssues', () => { { wrapper: appMockRender.AppWrapper } ); - await waitFor(() => result.current.isSuccess); - - expect(spy).toHaveBeenCalledWith({ - http, - signal: expect.anything(), - connectorId: actionConnector.id, - title: 'Task', + await waitFor(() => { + expect(result.current.isSuccess).toBe(true); + expect(spy).toHaveBeenCalledWith({ + http, + signal: expect.anything(), + connectorId: actionConnector.id, + title: 'Task', + }); }); }); @@ -85,9 +86,10 @@ describe('useGetIssues', () => { { wrapper: appMockRender.AppWrapper } ); - await waitFor(() => result.current.isError); - - expect(addError).toHaveBeenCalled(); + await waitFor(() => { + expect(result.current.isError).toBe(true); + expect(addError).toHaveBeenCalled(); + }); }); it('calls addError when the getIssues api returns successfully but contains an error', async () => { @@ -111,8 +113,9 @@ describe('useGetIssues', () => { { wrapper: appMockRender.AppWrapper } ); - await waitFor(() => result.current.isSuccess); - - expect(addError).toHaveBeenCalled(); + await waitFor(() => { + expect(result.current.isSuccess).toBe(true); + expect(addError).toHaveBeenCalled(); + }); }); }); diff --git a/x-pack/plugins/cases/public/containers/configure/use_get_case_configuration.test.tsx b/x-pack/plugins/cases/public/containers/configure/use_get_case_configuration.test.tsx index 2ac0a4573e6da..17f5a44c0eb31 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_get_case_configuration.test.tsx +++ b/x-pack/plugins/cases/public/containers/configure/use_get_case_configuration.test.tsx @@ -40,12 +40,10 @@ describe('Use get case configuration hook', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - /** * The response after fetching */ - expect(result.current.data).toEqual(targetConfiguration); + await waitFor(() => expect(result.current.data).toEqual(targetConfiguration)); }); it('returns the initial configuration if none matches the owner', async () => { @@ -64,12 +62,10 @@ describe('Use get case configuration hook', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - /** * The response after fetching */ - expect(result.current.data).toEqual(initialConfiguration); + await waitFor(() => expect(result.current.data).toEqual(initialConfiguration)); }); it('returns the initial configuration if none exists', async () => { @@ -81,12 +77,10 @@ describe('Use get case configuration hook', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - /** * The response after fetching */ - expect(result.current.data).toEqual(initialConfiguration); + await waitFor(() => expect(result.current.data).toEqual(initialConfiguration)); }); it('returns the initial configuration if the owner is undefined', async () => { @@ -99,11 +93,9 @@ describe('Use get case configuration hook', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - /** * The response after fetching */ - expect(result.current.data).toEqual(initialConfiguration); + await waitFor(() => expect(result.current.data).toEqual(initialConfiguration)); }); }); diff --git a/x-pack/plugins/cases/public/containers/use_delete_comment.test.tsx b/x-pack/plugins/cases/public/containers/use_delete_comment.test.tsx index 6c0d534847b12..a092cefb04e18 100644 --- a/x-pack/plugins/cases/public/containers/use_delete_comment.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_delete_comment.test.tsx @@ -58,12 +58,12 @@ describe('useDeleteComment', () => { }); }); - await waitFor(() => null); - - expect(spyOnDeleteComment).toBeCalledWith({ - caseId: basicCaseId, - commentId, - }); + await waitFor(() => + expect(spyOnDeleteComment).toBeCalledWith({ + caseId: basicCaseId, + commentId, + }) + ); }); it('refreshes the case page view after delete', async () => { @@ -71,15 +71,15 @@ describe('useDeleteComment', () => { wrapper: appMockRender.AppWrapper, }); - result.current.mutate({ - caseId: basicCaseId, - commentId, - successToasterTitle, + act(() => { + result.current.mutate({ + caseId: basicCaseId, + commentId, + successToasterTitle, + }); }); - await waitFor(() => null); - - expect(useRefreshCaseViewPage()).toBeCalled(); + await waitFor(() => expect(useRefreshCaseViewPage()).toBeCalled()); }); it('shows a success toaster correctly', async () => { @@ -95,12 +95,12 @@ describe('useDeleteComment', () => { }); }); - await waitFor(() => null); - - expect(addSuccess).toHaveBeenCalledWith({ - title: 'Deleted', - className: 'eui-textBreakWord', - }); + await waitFor(() => + expect(addSuccess).toHaveBeenCalledWith({ + title: 'Deleted', + className: 'eui-textBreakWord', + }) + ); }); it('sets isError when fails to delete a case', async () => { @@ -111,20 +111,22 @@ describe('useDeleteComment', () => { wrapper: appMockRender.AppWrapper, }); - result.current.mutate({ - caseId: basicCaseId, - commentId, - successToasterTitle, + act(() => { + result.current.mutate({ + caseId: basicCaseId, + commentId, + successToasterTitle, + }); }); - await waitFor(() => null); + await waitFor(() => { + expect(spyOnDeleteComment).toBeCalledWith({ + caseId: basicCaseId, + commentId, + }); - expect(spyOnDeleteComment).toBeCalledWith({ - caseId: basicCaseId, - commentId, + expect(addError).toHaveBeenCalled(); + expect(result.current.isError).toBe(true); }); - - expect(addError).toHaveBeenCalled(); - expect(result.current.isError).toBe(true); }); }); diff --git a/x-pack/plugins/cases/public/containers/use_get_case_files.test.tsx b/x-pack/plugins/cases/public/containers/use_get_case_files.test.tsx index 2d3aa26ba6565..e14bc2a6bd902 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_files.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_files.test.tsx @@ -52,10 +52,10 @@ describe('useGetCaseFiles', () => { renderHook(() => useGetCaseFiles(hookParams), { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - - expect(appMockRender.getFilesClient().list).toBeCalledWith(expectedCallParams); - expect(addError).toHaveBeenCalled(); + await waitFor(() => { + expect(appMockRender.getFilesClient().list).toBeCalledWith(expectedCallParams); + expect(addError).toHaveBeenCalled(); + }); }); it('calls filesClient.list with correct arguments', async () => { @@ -63,8 +63,8 @@ describe('useGetCaseFiles', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => null); - - expect(appMockRender.getFilesClient().list).toBeCalledWith(expectedCallParams); + await waitFor(() => + expect(appMockRender.getFilesClient().list).toBeCalledWith(expectedCallParams) + ); }); }); diff --git a/x-pack/plugins/cases/public/containers/use_get_case_metrics.test.tsx b/x-pack/plugins/cases/public/containers/use_get_case_metrics.test.tsx index 9ace26d964017..141fac06193da 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_metrics.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_metrics.test.tsx @@ -39,8 +39,9 @@ describe('useGetCaseMetrics', () => { wrapper, }); - await waitFor(() => null); - expect(spyOnGetCaseMetrics).toBeCalledWith(basicCase.id, features, abortCtrl.signal); + await waitFor(() => + expect(spyOnGetCaseMetrics).toBeCalledWith(basicCase.id, features, abortCtrl.signal) + ); }); it('shows an error toast when getSingleCaseMetrics throws', async () => { @@ -56,9 +57,9 @@ describe('useGetCaseMetrics', () => { wrapper, }); - await waitFor(() => null); - - expect(spyOnGetCaseMetrics).toBeCalledWith(basicCase.id, features, abortCtrl.signal); - expect(addError).toHaveBeenCalled(); + await waitFor(() => { + expect(spyOnGetCaseMetrics).toBeCalledWith(basicCase.id, features, abortCtrl.signal); + expect(addError).toHaveBeenCalled(); + }); }); }); diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.test.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.test.ts index 4357f6231a7a4..6303d0cc0b2b3 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.test.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.test.ts @@ -39,13 +39,14 @@ describe('useSuggestUserProfiles', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => result.current.isSuccess); - - expect(spyOnSuggestUserProfiles).toBeCalledWith({ - ...props, - size: 10, - http: expect.anything(), - signal: expect.anything(), + await waitFor(() => { + expect(result.current.isSuccess).toBeDefined(); + expect(spyOnSuggestUserProfiles).toBeCalledWith({ + ...props, + size: 10, + http: expect.anything(), + signal: expect.anything(), + }); }); }); @@ -63,8 +64,9 @@ describe('useSuggestUserProfiles', () => { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => result.current.isError); - - expect(addError).toHaveBeenCalled(); + await waitFor(() => { + expect(result.current.isError).toBeDefined(); + expect(addError).toHaveBeenCalled(); + }); }); }); diff --git a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts b/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts index 7cbc3477c4a77..de5463d7dbcdb 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts +++ b/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts @@ -56,9 +56,10 @@ describe('usePersistExceptionItem', () => { rerender(); - await waitFor(() => - expect(result.current).toEqual([{ isLoading: true, isSaved: false }, result.current[1]]) - ); + await waitFor(() => { + expect(result.current[0].isLoading).toBe(true); + expect(result.current).toEqual([{ isLoading: true, isSaved: false }, result.current[1]]); + }); }); test('"isSaved" is "true" when exception item saved successfully', async () => { diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.test.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.test.tsx index 404bdbde15acd..4316683b2ed27 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.test.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.test.tsx @@ -139,10 +139,12 @@ describe('useMetricsExplorerData Hook', () => { await act(async () => { await result.current.fetchNextPage(); }); - await waitFor(() => expect(result.current.isLoading).toBe(false)); - const { series: nextSeries } = result.current.data!.pages[1]; - expect(nextSeries).toBeDefined(); - expect(nextSeries.length).toBe(3); + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + const { series: nextSeries } = result.current.data!.pages[1]; + expect(nextSeries).toBeDefined(); + expect(nextSeries.length).toBe(3); + }); }); it('should reset error upon recovery', async () => { @@ -159,9 +161,11 @@ describe('useMetricsExplorerData Hook', () => { await act(async () => { await result.current.refetch(); }); - await waitFor(() => expect(result.current.isLoading).toBe(false)); - expect(result.current.data!.pages[0]).toEqual(resp); - expect(result.current.error).toBe(null); + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + expect(result.current.data!.pages[0]).toEqual(resp); + expect(result.current.error).toBe(null); + }); }); it('should not paginate on option change', async () => { @@ -186,8 +190,10 @@ describe('useMetricsExplorerData Hook', () => { timestamps, }); expect(result.current.isLoading).toBe(true); - await waitFor(() => expect(result.current.isLoading).toBe(false)); - expect(result.current.data!.pages[0]).toEqual(resp); + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + expect(result.current.data!.pages[0]).toEqual(resp); + }); }); it('should not paginate on time change', async () => { @@ -208,7 +214,9 @@ describe('useMetricsExplorerData Hook', () => { timestamps: { fromTimestamp: 1678378092225, toTimestamp: 1678381693477, interval: '>=10s' }, }); expect(result.current.isLoading).toBe(true); - await waitFor(() => expect(result.current.isLoading).toBe(false)); - expect(result.current.data!.pages[0]).toEqual(resp); + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + expect(result.current.data!.pages[0]).toEqual(resp); + }); }); }); 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 6237e751ad1f0..02cd0f6febc39 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 @@ -45,7 +45,7 @@ describe('useFetchAlertData', () => { useFetchAlertData(testIds) ); - expect(result.current).toEqual([false, {}]); + expect(result.all[0]).toEqual([false, {}]); }); it('returns no data when an error occurs', async () => { @@ -82,6 +82,8 @@ describe('useFetchAlertData', () => { 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 2e3ad3c371f37..22945a5787b34 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 @@ -69,7 +69,7 @@ describe('useFetchAlertDetail', () => { useFetchAlertDetail(id) ); - expect(result.current).toEqual([true, null]); + expect(result.all[0]).toEqual([false, null]); }); it('returns no data when an error occurs', async () => { @@ -81,9 +81,7 @@ describe('useFetchAlertDetail', () => { useFetchAlertDetail('123') ); - await waitFor(() => null); - - expect(result.current).toEqual([false, null]); + await waitFor(() => expect(result.current).toEqual([false, null])); }); it('retrieves the alert data', async () => { @@ -91,23 +89,55 @@ describe('useFetchAlertDetail', () => { useFetchAlertDetail(id) ); - await waitFor(() => null); - - expect(result.current).toMatchInlineSnapshot(` - Array [ - false, - Object { - "formatted": Object { - "0": "a", - "1": " ", - "2": "r", - "3": "e", - "4": "a", - "5": "s", - "6": "o", - "7": "n", - "active": true, - "fields": Object { + await waitFor(() => { + expect(result.current[0]).toEqual(false); + expect(result.current).toMatchInlineSnapshot(` + Array [ + false, + Object { + "formatted": Object { + "0": "a", + "1": " ", + "2": "r", + "3": "e", + "4": "a", + "5": "s", + "6": "o", + "7": "n", + "active": true, + "fields": Object { + "@timestamp": "2022-01-31T18:20:57.204Z", + "_index": "alert-index", + "event.action": "active", + "event.kind": "signal", + "kibana.alert.duration.us": 13793555000, + "kibana.alert.instance.id": "*", + "kibana.alert.reason": "Document count reported no data in the last 1 hour for all hosts", + "kibana.alert.rule.category": "Metric threshold", + "kibana.alert.rule.consumer": "infrastructure", + "kibana.alert.rule.execution.uuid": "e62c418d-734d-47e7-bbeb-e6f182f5fb45", + "kibana.alert.rule.name": "A super rule", + "kibana.alert.rule.producer": "infrastructure", + "kibana.alert.rule.revision": 0, + "kibana.alert.rule.rule_type_id": "metrics.alert.threshold", + "kibana.alert.rule.tags": Array [], + "kibana.alert.rule.uuid": "69411af0-82a2-11ec-8139-c1568734434e", + "kibana.alert.start": "2022-01-31T14:31:03.649Z", + "kibana.alert.status": "active", + "kibana.alert.uuid": "73c0d0cd-2df4-4550-862c-1d447e9c1db2", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": Array [ + "default", + ], + "kibana.version": "8.1.0", + "tags": Array [], + }, + "lastUpdated": 1643653257204, + "link": undefined, + "reason": "Document count reported no data in the last 1 hour for all hosts", + "start": 1643639463649, + }, + "raw": Object { "@timestamp": "2022-01-31T18:20:57.204Z", "_index": "alert-index", "event.action": "active", @@ -134,41 +164,10 @@ describe('useFetchAlertDetail', () => { "kibana.version": "8.1.0", "tags": Array [], }, - "lastUpdated": 1643653257204, - "link": undefined, - "reason": "Document count reported no data in the last 1 hour for all hosts", - "start": 1643639463649, }, - "raw": Object { - "@timestamp": "2022-01-31T18:20:57.204Z", - "_index": "alert-index", - "event.action": "active", - "event.kind": "signal", - "kibana.alert.duration.us": 13793555000, - "kibana.alert.instance.id": "*", - "kibana.alert.reason": "Document count reported no data in the last 1 hour for all hosts", - "kibana.alert.rule.category": "Metric threshold", - "kibana.alert.rule.consumer": "infrastructure", - "kibana.alert.rule.execution.uuid": "e62c418d-734d-47e7-bbeb-e6f182f5fb45", - "kibana.alert.rule.name": "A super rule", - "kibana.alert.rule.producer": "infrastructure", - "kibana.alert.rule.revision": 0, - "kibana.alert.rule.rule_type_id": "metrics.alert.threshold", - "kibana.alert.rule.tags": Array [], - "kibana.alert.rule.uuid": "69411af0-82a2-11ec-8139-c1568734434e", - "kibana.alert.start": "2022-01-31T14:31:03.649Z", - "kibana.alert.status": "active", - "kibana.alert.uuid": "73c0d0cd-2df4-4550-862c-1d447e9c1db2", - "kibana.alert.workflow_status": "open", - "kibana.space_ids": Array [ - "default", - ], - "kibana.version": "8.1.0", - "tags": Array [], - }, - }, - ] - `); + ] + `); + }); }); it('does not populate the results when the request is canceled', async () => { @@ -180,6 +179,7 @@ describe('useFetchAlertDetail', () => { 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/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.test.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.test.tsx index 172d9d4b5c8ee..1a3581c298a93 100644 --- a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/from_alerts/use_host_isolation_action.test.tsx @@ -4,7 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type React from 'react'; +import { act } from '@testing-library/react'; import type { UseHostIsolationActionProps } from './use_host_isolation_action'; import { useHostIsolationAction } from './use_host_isolation_action'; import type { AppContextTestRender, UserPrivilegesMockSetter } from '../../../../mock/endpoint'; @@ -15,7 +16,6 @@ import type { AlertTableContextMenuItem } from '../../../../../detections/compon import type { ResponseActionsApiCommandNames } from '../../../../../../common/endpoint/service/response_actions/constants'; import { agentStatusMocks } from '../../../../../../common/endpoint/service/response_actions/mocks/agent_status.mocks'; import { ISOLATE_HOST, UNISOLATE_HOST } from './translations'; -import type React from 'react'; import { HOST_ENDPOINT_UNENROLLED_TOOLTIP, LOADING_ENDPOINT_DATA_TOOLTIP, @@ -184,16 +184,24 @@ describe('useHostIsolationAction', () => { }); it('should call un-isolate API when agent is currently isolated', async () => { - apiMock.responseProvider.getAgentStatus.mockReturnValue( - agentStatusMocks.generateAgentStatusApiResponse({ - data: { 'abfe4a35-d5b4-42a0-a539-bd054c791769': { isolated: true } }, - }) - ); + apiMock.responseProvider.getAgentStatus.mockImplementation(({ query }) => { + const agentId = (query!.agentIds as string[])[0]; + + return agentStatusMocks.generateAgentStatusApiResponse({ + data: { [agentId]: { isolated: true } }, + }); + }); + const { result } = render(); - await appContextMock.waitFor(() => expect(result.current[0].onClick).toBeDefined()); + await appContextMock.waitFor(() => { + expect(apiMock.responseProvider.getAgentStatus).toHaveBeenCalled(); + expect(result.current[0].onClick).toBeDefined(); + }); - result.current[0].onClick!({} as unknown as React.MouseEvent); + act(() => { + result.current[0].onClick!({} as unknown as React.MouseEvent); + }); await appContextMock.waitFor(() => expect(hookProps.onAddIsolationStatusClick).toHaveBeenCalledWith('unisolateHost') diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx index 7ad10c08deb0d..65a704962a4a5 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx @@ -36,7 +36,7 @@ describe('useSignalIndex', () => { wrapper: TestProvidersWithPrivileges, }); - expect(result.current).toEqual({ + expect(result.all[0]).toEqual({ createDeSignalIndex: null, loading: true, signalIndexExists: null, diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_critical_alerts.test.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_critical_alerts.test.tsx index 3b962343bbe3a..7189b8def435f 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_critical_alerts.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/soc_trends/hooks/use_critical_alerts.test.tsx @@ -71,9 +71,7 @@ describe('useCriticalAlerts', () => { wrapper: wrapperContainer, }); - await waitFor(() => expect(result.current.isLoading).toBe(true)); - - expect(result.current).toEqual({ + expect(result.all[0]).toEqual({ stat: '-', isLoading: true, percentage: { diff --git a/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx index f5a76bbf752e3..3116b6e610c45 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx @@ -143,7 +143,7 @@ describe('useTimelineEvents', () => { } ); - expect(result.current).toEqual([ + expect(result.all[0]).toEqual([ DataLoadingState.loaded, { events: [], From 3ee8c51b8f44c5f0ca46659a8c01a749df2210e7 Mon Sep 17 00:00:00 2001 From: Eyo Okon Eyo Date: Fri, 11 Oct 2024 11:14:09 +0100 Subject: [PATCH 12/18] use act from renderHook for special instances --- .../container/hooks/use_state_props.test.ts | 4 ++-- .../use_markdown_session_storage.test.tsx | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts b/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts index b26223de96e4e..e5b5044f34196 100644 --- a/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts +++ b/src/plugins/unified_histogram/public/container/hooks/use_state_props.test.ts @@ -9,8 +9,8 @@ import { DataView, DataViewField, DataViewType } from '@kbn/data-views-plugin/common'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; -import { renderHook } from '@testing-library/react-hooks'; -import { waitFor, act } from '@testing-library/react'; +import { renderHook, act } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import type { DatatableColumn } from '@kbn/expressions-plugin/common'; import { convertDatatableColumnToDataViewFieldSpec } from '@kbn/data-view-utils'; import { UnifiedHistogramFetchStatus, UnifiedHistogramSuggestionContext } from '../../types'; diff --git a/x-pack/plugins/cases/public/components/markdown_editor/use_markdown_session_storage.test.tsx b/x-pack/plugins/cases/public/components/markdown_editor/use_markdown_session_storage.test.tsx index 6fb4d9743ce51..26b578268666b 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/use_markdown_session_storage.test.tsx +++ b/x-pack/plugins/cases/public/components/markdown_editor/use_markdown_session_storage.test.tsx @@ -5,8 +5,8 @@ * 2.0. */ -import { renderHook } from '@testing-library/react-hooks'; -import { act, waitFor } from '@testing-library/react'; +import { act, renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import type { FieldHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import type { SessionStorageType } from './use_markdown_session_storage'; import { useMarkdownSessionStorage } from './use_markdown_session_storage'; @@ -66,7 +66,7 @@ describe('useMarkdownSessionStorage', () => { }); it('should update the session value with field value when it is first render', async () => { - renderHook<{ hasConflicts: boolean }, SessionStorageType>( + renderHook( (props) => { return useMarkdownSessionStorage(props); }, @@ -86,7 +86,7 @@ describe('useMarkdownSessionStorage', () => { it('should set session storage when field has value and session key is not created yet', async () => { const specialCharsValue = '!{tooltip[Hello again](This is tooltip!)}'; - const { result } = renderHook<{ hasConflicts: boolean }, SessionStorageType>( + const { result } = renderHook( (props) => { return useMarkdownSessionStorage(props); }, @@ -108,7 +108,7 @@ describe('useMarkdownSessionStorage', () => { }); it('should update session value ', async () => { - const { result, rerender } = renderHook<{ hasConflicts: boolean }, SessionStorageType>( + const { result, rerender } = renderHook( (props) => { return useMarkdownSessionStorage(props); }, @@ -134,7 +134,7 @@ describe('useMarkdownSessionStorage', () => { }); it('should return has conflict true', async () => { - const { result, rerender } = renderHook<{ hasConflicts: boolean }, SessionStorageType>( + const { result, rerender } = renderHook( (props) => { return useMarkdownSessionStorage(props); }, @@ -158,7 +158,7 @@ describe('useMarkdownSessionStorage', () => { }); it('should set field value if session already exists and it is a first render', async () => { - const { result } = renderHook<{ hasConflicts: boolean }, SessionStorageType>( + const { result } = renderHook( (props) => { return useMarkdownSessionStorage(props); }, @@ -182,7 +182,7 @@ describe('useMarkdownSessionStorage', () => { }); it('should update existing session key if field value changed', async () => { - const { rerender, result } = renderHook<{ hasConflicts: boolean }, SessionStorageType>( + const { rerender, result } = renderHook( (props) => { return useMarkdownSessionStorage(props); }, From 46b532c0c4d15ade6d51acd92b9f72c45f5ceb8b Mon Sep 17 00:00:00 2001 From: Eyo Okon Eyo Date: Fri, 11 Oct 2024 11:17:39 +0100 Subject: [PATCH 13/18] fix types --- .../assistant/use_conversation/index.test.tsx | 8 +- .../hooks/use_ilm_explain/index.test.tsx | 2 +- ...t_supported_action_connectors.tsx.test.tsx | 14 +++- .../containers/use_get_categories.test.tsx | 8 +- .../public/containers/use_get_tags.test.tsx | 8 +- .../hooks/use_action_status.test.tsx | 4 +- .../public/mock/create_test_renderer.tsx | 1 - .../common/containers/source/index.test.tsx | 36 ++++---- .../containers/use_full_screen/index.test.tsx | 2 +- .../public/common/mock/test_providers.tsx | 4 +- ...tch_or_create_rule_exception_list.test.tsx | 2 +- .../alerts/use_query.test.tsx | 2 +- .../alerts/use_signal_index.test.tsx | 10 +-- .../sourcerer/containers/hooks.test.tsx | 4 +- .../containers/use_signal_helpers.test.tsx | 16 +++- .../open_timeline/use_timeline_types.test.tsx | 84 +++++++++---------- .../timelines/containers/index.test.tsx | 17 ++-- .../email/use_email_config.test.ts | 10 ++- 18 files changed, 132 insertions(+), 100 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.test.tsx index 6cabb7aa2f46c..9b2004e1cfe6f 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_conversation/index.test.tsx @@ -56,7 +56,7 @@ describe('useConversation', () => { it('should create a new conversation when called with valid conversationId and message', async () => { const { result } = renderHook(() => useConversation(), { - wrapper: ({ children }) => ( + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( {children} ), }); @@ -81,7 +81,7 @@ describe('useConversation', () => { it('should delete an existing conversation when called with valid conversationId', async () => { const { result } = renderHook(() => useConversation(), { - wrapper: ({ children }) => ( + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( {children} ), }); @@ -100,7 +100,7 @@ describe('useConversation', () => { it('should update the apiConfig for an existing conversation when called with a valid conversationId and apiConfig', async () => { const { result } = renderHook(() => useConversation(), { - wrapper: ({ children }) => ( + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( {children} ), }); @@ -121,7 +121,7 @@ describe('useConversation', () => { it('should remove the last message from a conversation when called with valid conversationId', async () => { const { result } = renderHook(() => useConversation(), { - wrapper: ({ children }) => ( + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( {children} ), }); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/hooks/use_ilm_explain/index.test.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/hooks/use_ilm_explain/index.test.tsx index 7e0721ccc1cf1..fd1dcc390bcad 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/hooks/use_ilm_explain/index.test.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality_panel/data_quality_details/indices_details/pattern/hooks/use_ilm_explain/index.test.tsx @@ -115,7 +115,7 @@ describe('useIlmExplain', () => { beforeEach(async () => { const { result } = renderHook(() => useIlmExplain(pattern), { - wrapper: ({ children }) => ( + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( { it('fetches connectors', async () => { const spy = jest.spyOn(api, 'getSupportedActionConnectors'); renderHook(() => useGetSupportedActionConnectors(), { - wrapper: ({ children }) => {children}, + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + {children} + ), }); await waitFor(() => expect(spy).toHaveBeenCalledWith({ signal: expect.any(AbortSignal) })); @@ -44,7 +46,9 @@ describe('useConnectors', () => { }); renderHook(() => useGetSupportedActionConnectors(), { - wrapper: ({ children }) => {children}, + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + {children} + ), }); await waitFor(() => expect(addError).toHaveBeenCalled()); @@ -55,7 +59,9 @@ describe('useConnectors', () => { useApplicationCapabilitiesMock().actions = { crud: false, read: false }; const { result } = renderHook(() => useGetSupportedActionConnectors(), { - wrapper: ({ children }) => {children}, + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + {children} + ), }); await waitFor(() => { @@ -69,7 +75,7 @@ describe('useConnectors', () => { useApplicationCapabilitiesMock().actions = { crud: true, read: true }; const { result } = renderHook(() => useGetSupportedActionConnectors(), { - wrapper: ({ children }) => ( + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( {children} ), }); diff --git a/x-pack/plugins/cases/public/containers/use_get_categories.test.tsx b/x-pack/plugins/cases/public/containers/use_get_categories.test.tsx index 71ba68eb41834..cbb8112bf5e17 100644 --- a/x-pack/plugins/cases/public/containers/use_get_categories.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_categories.test.tsx @@ -26,7 +26,9 @@ describe('useGetCategories', () => { it('calls getCategories api', async () => { const spyOnGetCategories = jest.spyOn(api, 'getCategories'); renderHook(() => useGetCategories(), { - wrapper: ({ children }) => {children}, + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + {children} + ), }); await waitFor(() => @@ -47,7 +49,9 @@ describe('useGetCategories', () => { (useToasts as jest.Mock).mockReturnValue({ addError }); renderHook(() => useGetCategories(), { - wrapper: ({ children }) => {children}, + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + {children} + ), }); await waitFor(() => expect(addError).toBeCalled()); diff --git a/x-pack/plugins/cases/public/containers/use_get_tags.test.tsx b/x-pack/plugins/cases/public/containers/use_get_tags.test.tsx index 7d388fc0bde74..1dd91d6cd42e6 100644 --- a/x-pack/plugins/cases/public/containers/use_get_tags.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_tags.test.tsx @@ -26,7 +26,9 @@ describe('useGetTags', () => { it('calls getTags api', async () => { const spyOnGetTags = jest.spyOn(api, 'getTags'); renderHook(() => useGetTags(), { - wrapper: ({ children }) => {children}, + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + {children} + ), }); await waitFor(() => null); expect(spyOnGetTags).toBeCalledWith({ @@ -43,7 +45,9 @@ describe('useGetTags', () => { throw new Error('Something went wrong'); }); renderHook(() => useGetTags(), { - wrapper: ({ children }) => {children}, + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + {children} + ), }); await waitFor(() => expect(addError).toBeCalled()); }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_action_status.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_action_status.test.tsx index 86b097bac01d6..5b19c098f650e 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_action_status.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/hooks/use_action_status.test.tsx @@ -8,6 +8,8 @@ import { renderHook } from '@testing-library/react-hooks'; import { act, waitFor } from '@testing-library/react'; +import type { ActionStatus } from '../../../../../../../common/types'; + import { sendGetActionStatus, sendPostCancelAction, useStartServices } from '../../../../hooks'; import { useActionStatus } from './use_action_status'; @@ -42,7 +44,7 @@ describe('useActionStatus', () => { nbAgentsFailed: 0, nbAgentsActioned: 2, creationTime: '2022-09-19T12:07:27.102Z', - }, + } as ActionStatus, ]; beforeEach(() => { mockSendGetActionStatus.mockReset(); diff --git a/x-pack/plugins/fleet/public/mock/create_test_renderer.tsx b/x-pack/plugins/fleet/public/mock/create_test_renderer.tsx index c9d7e9fd56243..8173c6d640697 100644 --- a/x-pack/plugins/fleet/public/mock/create_test_renderer.tsx +++ b/x-pack/plugins/fleet/public/mock/create_test_renderer.tsx @@ -138,7 +138,6 @@ export const createFleetTestRendererMock = (): TestRenderer => { }); return renderResponse!; }, - waitFor, }; return testRendererMocks; diff --git a/x-pack/plugins/security_solution/public/common/containers/source/index.test.tsx b/x-pack/plugins/security_solution/public/common/containers/source/index.test.tsx index bda66608d6c5e..5a083e8bf48e3 100644 --- a/x-pack/plugins/security_solution/public/common/containers/source/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/source/index.test.tsx @@ -84,12 +84,12 @@ describe('source/index.tsx', () => { }); }); it('sets field data for data view', async () => { - const { result } = renderHook<{ indexFieldsSearch: IndexFieldSearch }, string>( - () => useDataView(), - { - wrapper: TestProviders, - } - ); + const { result } = renderHook< + React.PropsWithChildren<{}>, + { indexFieldsSearch: IndexFieldSearch } + >(() => useDataView(), { + wrapper: TestProviders, + }); await waitFor(() => null); @@ -108,12 +108,12 @@ describe('source/index.tsx', () => { it('should reuse the result for dataView info when cleanCache not passed', async () => { let indexFieldsSearch: IndexFieldSearch; - const { result } = renderHook<{ indexFieldsSearch: IndexFieldSearch }, string>( - () => useDataView(), - { - wrapper: TestProviders, - } - ); + const { result } = renderHook< + React.PropsWithChildren<{}>, + { indexFieldsSearch: IndexFieldSearch } + >(() => useDataView(), { + wrapper: TestProviders, + }); await waitFor(() => null); @@ -139,12 +139,12 @@ describe('source/index.tsx', () => { it('should not reuse the result for dataView info when cleanCache passed', async () => { let indexFieldsSearch: IndexFieldSearch; - const { result } = renderHook<{ indexFieldsSearch: IndexFieldSearch }, string>( - () => useDataView(), - { - wrapper: TestProviders, - } - ); + const { result } = renderHook< + React.PropsWithChildren<{}>, + { indexFieldsSearch: IndexFieldSearch } + >(() => useDataView(), { + wrapper: TestProviders, + }); await waitFor(() => null); await act(async () => { indexFieldsSearch = result.current.indexFieldsSearch; diff --git a/x-pack/plugins/security_solution/public/common/containers/use_full_screen/index.test.tsx b/x-pack/plugins/security_solution/public/common/containers/use_full_screen/index.test.tsx index bc5d5661380c1..1cf1170bd2ca6 100644 --- a/x-pack/plugins/security_solution/public/common/containers/use_full_screen/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/use_full_screen/index.test.tsx @@ -18,7 +18,7 @@ describe('useFullScreen', () => { let result: RenderResult; test('Default values with no data grid in the dom', async () => { - const WrapperContainer: RenderOptions['wrapper'] = ({ children }) => ( + const WrapperContainer = ({ children }: React.PropsWithChildren<{}>) => (
{children}
diff --git a/x-pack/plugins/security_solution/public/common/mock/test_providers.tsx b/x-pack/plugins/security_solution/public/common/mock/test_providers.tsx index 1a0689b53b229..c4525faf3b316 100644 --- a/x-pack/plugins/security_solution/public/common/mock/test_providers.tsx +++ b/x-pack/plugins/security_solution/public/common/mock/test_providers.tsx @@ -53,13 +53,13 @@ window.scrollTo = jest.fn(); const MockKibanaContextProvider = createKibanaContextProviderMock(); /** A utility for wrapping children in the providers required to run most tests */ -export const TestProvidersComponent: React.FC = ({ +export const TestProvidersComponent = ({ children, store = createMockStore(), startServices, onDragEnd = jest.fn(), cellActions = [], -}) => { +}: React.PropsWithChildren) => { const queryClient = new QueryClient({ defaultOptions: { queries: { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_fetch_or_create_rule_exception_list.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_fetch_or_create_rule_exception_list.test.tsx index 2c25b24a8e65e..b503c5ff75f5a 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_fetch_or_create_rule_exception_list.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_fetch_or_create_rule_exception_list.test.tsx @@ -95,7 +95,7 @@ describe('useFetchOrCreateRuleExceptionList', () => { .mockResolvedValue(detectionExceptionList); render = (listType = detectionListType) => - renderHook( + renderHook( () => useFetchOrCreateRuleExceptionList({ http: mockKibanaHttpService, diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_query.test.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_query.test.tsx index 7f6e4d1b6229a..7b6cec311cf40 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_query.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_query.test.tsx @@ -64,7 +64,7 @@ describe('useQueryAlerts', () => { ); await waitFor(() => expect(result.current.refetch).toBeDefined()); - result.current.refetch(); + result.current.refetch!(); await waitFor(() => expect(spyOnfetchQueryAlerts).toHaveBeenCalledTimes(2)); }); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx index 65a704962a4a5..5a361899a20e9 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx @@ -6,7 +6,7 @@ */ import type { PropsWithChildren } from 'react'; import { renderHook } from '@testing-library/react-hooks'; -import { act, waitFor } from '@testing-library/react'; +import { waitFor, act } from '@testing-library/react'; import { TestProvidersWithPrivileges } from '../../../../common/mock'; import type { ReturnSignalIndex } from './use_signal_index'; import { useSignalIndex } from './use_signal_index'; @@ -75,7 +75,7 @@ describe('useSignalIndex', () => { await waitFor(() => expect(result.current.createDeSignalIndex).toBeDefined()); await act(async () => { - await result.current.createDeSignalIndex(); + await result.current.createDeSignalIndex!(); }); await waitFor(() => @@ -101,7 +101,7 @@ describe('useSignalIndex', () => { await waitFor(() => expect(result.current.createDeSignalIndex).toBeDefined()); await act(async () => { - await result.current.createDeSignalIndex(); + await result.current.createDeSignalIndex!(); }); await waitFor(() => expect(spyOnCreateSignalIndex).toHaveBeenCalledTimes(1)); @@ -122,7 +122,7 @@ describe('useSignalIndex', () => { await waitFor(() => expect(result.current.createDeSignalIndex).toBeDefined()); await act(async () => { - await result.current.createDeSignalIndex(); + await result.current.createDeSignalIndex!(); }); await waitFor(() => @@ -151,7 +151,7 @@ describe('useSignalIndex', () => { await waitFor(() => expect(result.current.createDeSignalIndex).toBeDefined()); await act(async () => { - await result.current.createDeSignalIndex(); + await result.current.createDeSignalIndex!(); }); await waitFor(() => diff --git a/x-pack/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx b/x-pack/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx index fbacdd4970f68..44c3107010654 100644 --- a/x-pack/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx +++ b/x-pack/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx @@ -164,7 +164,9 @@ describe('Sourcerer Hooks', () => { }); it('initializes loading default and timeline index patterns', async () => { const { rerender } = renderHook(() => useInitSourcerer(), { - wrapper: ({ children }) => {children}, + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + {children} + ), }); await waitFor(() => null); rerender(); diff --git a/x-pack/plugins/security_solution/public/sourcerer/containers/use_signal_helpers.test.tsx b/x-pack/plugins/security_solution/public/sourcerer/containers/use_signal_helpers.test.tsx index 59fe6f38bdf7f..41927827ebc86 100644 --- a/x-pack/plugins/security_solution/public/sourcerer/containers/use_signal_helpers.test.tsx +++ b/x-pack/plugins/security_solution/public/sourcerer/containers/use_signal_helpers.test.tsx @@ -70,7 +70,9 @@ describe('useSignalHelpers', () => { }; const store = createMockStore(state); const { result } = renderHook(() => useSignalHelpers(), { - wrapper: ({ children }) => {children}, + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + {children} + ), }); await waitFor(() => null); expect(result.current.signalIndexNeedsInit).toEqual(true); @@ -97,7 +99,9 @@ describe('useSignalHelpers', () => { }; const store = createMockStore(state); const { result } = renderHook(() => useSignalHelpers(), { - wrapper: ({ children }) => {children}, + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + {children} + ), }); await waitFor(() => null); expect(result.current.signalIndexNeedsInit).toEqual(false); @@ -126,7 +130,9 @@ describe('useSignalHelpers', () => { }; const store = createMockStore(state); const { result } = renderHook(() => useSignalHelpers(), { - wrapper: ({ children }) => {children}, + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + {children} + ), }); await waitFor(() => null); expect(result.current.signalIndexNeedsInit).toEqual(false); @@ -158,7 +164,9 @@ describe('useSignalHelpers', () => { }; const store = createMockStore(state); const { result } = renderHook(() => useSignalHelpers(), { - wrapper: ({ children }) => {children}, + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + {children} + ), }); await waitFor(() => null); expect(result.current.signalIndexNeedsInit).toEqual(false); diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx index 8ba1664b496eb..51b97fd8a31de 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.test.tsx @@ -55,12 +55,12 @@ describe('useTimelineTypes', () => { }); it('init', async () => { - const { result } = renderHook( - () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), - { - wrapper: TestProviders, - } - ); + const { result } = renderHook< + React.PropsWithChildren, + UseTimelineTypesResult + >(() => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { + wrapper: TestProviders, + }); expect(result.current).toEqual({ timelineType: 'default', @@ -71,12 +71,12 @@ describe('useTimelineTypes', () => { describe('timelineTabs', () => { it('render timelineTabs', async () => { - const { result } = renderHook( - () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), - { - wrapper: TestProviders, - } - ); + const { result } = renderHook< + React.PropsWithChildren, + UseTimelineTypesResult + >(() => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { + wrapper: TestProviders, + }); await waitFor(() => null); render(result.current.timelineTabs); @@ -85,12 +85,12 @@ describe('useTimelineTypes', () => { }); it('set timelineTypes correctly', async () => { - const { result } = renderHook( - () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), - { - wrapper: TestProviders, - } - ); + const { result } = renderHook< + React.PropsWithChildren, + UseTimelineTypesResult + >(() => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { + wrapper: TestProviders, + }); await waitFor(() => expect(result.current.timelineTabs).toBeDefined()); @@ -110,12 +110,12 @@ describe('useTimelineTypes', () => { }); it('stays in the same tab if clicking again on current tab', async () => { - const { result } = renderHook( - () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), - { - wrapper: TestProviders, - } - ); + const { result } = renderHook< + React.PropsWithChildren, + UseTimelineTypesResult + >(() => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { + wrapper: TestProviders, + }); await waitFor(() => null); render(result.current.timelineTabs); @@ -140,12 +140,12 @@ describe('useTimelineTypes', () => { describe('timelineFilters', () => { it('render timelineFilters', async () => { - const { result } = renderHook( - () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), - { - wrapper: TestProviders, - } - ); + const { result } = renderHook< + React.PropsWithChildren, + UseTimelineTypesResult + >(() => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { + wrapper: TestProviders, + }); await waitFor(() => null); const { container } = render(<>{result.current.timelineFilters}); @@ -159,12 +159,12 @@ describe('useTimelineTypes', () => { }); it('set timelineTypes correctly', async () => { - const { result } = renderHook( - () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), - { - wrapper: TestProviders, - } - ); + const { result } = renderHook< + React.PropsWithChildren, + UseTimelineTypesResult + >(() => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { + wrapper: TestProviders, + }); await waitFor(() => expect(result.current.timelineFilters).toBeDefined()); @@ -185,12 +185,12 @@ describe('useTimelineTypes', () => { }); it('stays in the same tab if clicking again on current tab', async () => { - const { result } = renderHook( - () => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), - { - wrapper: TestProviders, - } - ); + const { result } = renderHook< + React.PropsWithChildren, + UseTimelineTypesResult + >(() => useTimelineTypes({ defaultTimelineCount: 0, templateTimelineCount: 3 }), { + wrapper: TestProviders, + }); await waitFor(() => null); diff --git a/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx index 3116b6e610c45..85642646f8dc4 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx @@ -148,10 +148,13 @@ describe('useTimelineEvents', () => { { events: [], id: TimelineId.active, - inspect: result.current[1].inspect, - loadPage: result.current[1].loadPage, - pageInfo: result.current[1].pageInfo, - refetch: result.current[1].refetch, + inspect: expect.objectContaining({ dsl: [], response: [] }), + loadPage: expect.any(Function), + pageInfo: expect.objectContaining({ + activePage: 0, + querySize: 0, + }), + refetch: expect.any(Function), totalCount: -1, refreshedAt: 0, }, @@ -231,8 +234,8 @@ describe('useTimelineEvents', () => { test('Correlation pagination is calling search strategy when switching page', async () => { const { result, rerender } = renderHook< - [DataLoadingState, TimelineArgs], - UseTimelineEventsProps + UseTimelineEventsProps, + [DataLoadingState, TimelineArgs] >((args) => useTimelineEvents(args), { initialProps: { ...props, @@ -320,7 +323,7 @@ describe('useTimelineEvents', () => { await waitFor(() => expect(mockSearch).toHaveBeenCalledTimes(0)); }); test('should not query again when a removed field is added back', async () => { - const { rerender } = renderHook<[DataLoadingState, TimelineArgs], UseTimelineEventsProps>( + const { rerender } = renderHook( (args) => useTimelineEvents(args), { initialProps: { ...props }, diff --git a/x-pack/plugins/stack_connectors/public/connector_types/email/use_email_config.test.ts b/x-pack/plugins/stack_connectors/public/connector_types/email/use_email_config.test.ts index 7b03d016ec8f8..454457472749a 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/email/use_email_config.test.ts +++ b/x-pack/plugins/stack_connectors/public/connector_types/email/use_email_config.test.ts @@ -17,6 +17,12 @@ const renderUseEmailConfigHook = (currentService?: string) => renderHook(() => useEmailConfig({ http, toasts })); describe('useEmailConfig', () => { + let res: ReturnType['getEmailServiceConfig']> extends Promise< + infer R + > + ? R + : never; + beforeEach(() => jest.clearAllMocks()); it('should return the correct result when requesting the config of a service', async () => { @@ -27,7 +33,7 @@ describe('useEmailConfig', () => { }); const { result } = renderUseEmailConfigHook(); - let res: ReturnType; + await act(async () => { res = await result.current.getEmailServiceConfig('gmail'); }); @@ -48,7 +54,6 @@ describe('useEmailConfig', () => { const { result } = renderUseEmailConfigHook(); - let res: ReturnType; await act(async () => { res = await result.current.getEmailServiceConfig('gmail'); }); @@ -65,7 +70,6 @@ describe('useEmailConfig', () => { http.get.mockResolvedValueOnce({}); const { result } = renderUseEmailConfigHook(); - let res: ReturnType; await act(async () => { res = await result.current.getEmailServiceConfig('foo'); }); From 19bf496fa0a3e3d100e91f8efd0563dbbc11933c Mon Sep 17 00:00:00 2001 From: Eyo Okon Eyo Date: Mon, 14 Oct 2024 15:34:31 +0100 Subject: [PATCH 14/18] add lint rule to prevent any further usage of waitForNextUpdate --- .eslintrc.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.eslintrc.js b/.eslintrc.js index 006f39ce1026c..eeb211e4e64fe 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -891,6 +891,17 @@ module.exports = { message: 'lodash.template is unsafe, and not compatible with our content security policy.', }, + { + object: 'renderHook', + property: 'waitFor', + message: + "use waitFor exported from @testing-library/react instead. waitFor is not available on the returned object from renderHook in it's next version", + }, + { + property: 'waitForNextUpdate', + message: + "use waitFor exported from @testing-library/react instead. waitForNextUpdate is not available on the returned object from renderHook in it's next version.", + }, ], }, }, From 3a66ac1042b939ebb9a7d9bf3e90f91ac702d268 Mon Sep 17 00:00:00 2001 From: Eyo Okon Eyo Date: Mon, 14 Oct 2024 18:42:26 +0100 Subject: [PATCH 15/18] fix missed waitForNextUpdate caught by lint rule --- .../public/hooks/use_scan_usage.test.tsx | 25 ++++++++++--------- .../public/app/hooks/use_index_data.test.tsx | 14 +++++------ 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/x-pack/plugins/search_inference_endpoints/public/hooks/use_scan_usage.test.tsx b/x-pack/plugins/search_inference_endpoints/public/hooks/use_scan_usage.test.tsx index 5f1766b7a6fa4..e19cd7bf09629 100644 --- a/x-pack/plugins/search_inference_endpoints/public/hooks/use_scan_usage.test.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/hooks/use_scan_usage.test.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { waitFor } from '@testing-library/react'; import { renderHook } from '@testing-library/react-hooks'; import { useScanUsage } from './use_scan_usage'; @@ -43,7 +44,7 @@ describe('useScanUsage', () => { }); test('should call API endpoint with the correct parameters and return response', async () => { - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => useScanUsage({ type: 'text_embedding', @@ -52,18 +53,18 @@ describe('useScanUsage', () => { { wrapper } ); - await waitForNextUpdate(); + await waitFor(() => { + expect(mockDelete).toHaveBeenCalledWith( + '/internal/inference_endpoint/endpoints/text_embedding/in-1', + { query: { scanUsage: true } } + ); - expect(mockDelete).toHaveBeenCalledWith( - '/internal/inference_endpoint/endpoints/text_embedding/in-1', - { query: { scanUsage: true } } - ); - - expect(result.current.data).toEqual({ - acknowledge: true, - error_message: 'inference id is being used', - indexes: ['index1', 'index2'], - pipelines: ['pipeline1', 'pipeline2'], + expect(result.current.data).toEqual({ + acknowledge: true, + error_message: 'inference id is being used', + indexes: ['index1', 'index2'], + pipelines: ['pipeline1', 'pipeline2'], + }); }); }); }); diff --git a/x-pack/plugins/transform/public/app/hooks/use_index_data.test.tsx b/x-pack/plugins/transform/public/app/hooks/use_index_data.test.tsx index c9c5083002b04..3d5615654acc8 100644 --- a/x-pack/plugins/transform/public/app/hooks/use_index_data.test.tsx +++ b/x-pack/plugins/transform/public/app/hooks/use_index_data.test.tsx @@ -47,7 +47,7 @@ describe('Transform: useIndexData()', () => { ); - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => useIndexData({ dataView: { @@ -62,13 +62,13 @@ describe('Transform: useIndexData()', () => { { wrapper } ); - const IndexObj: UseIndexDataReturnType = result.current; - - await waitForNextUpdate(); + await waitFor(() => { + const IndexObj: UseIndexDataReturnType = result.current; - expect(IndexObj.errorMessage).toBe(''); - expect(IndexObj.status).toBe(INDEX_STATUS.UNUSED); - expect(IndexObj.tableItems).toEqual([]); + expect(IndexObj.errorMessage).toBe(''); + expect(IndexObj.status).toBe(INDEX_STATUS.UNUSED); + expect(IndexObj.tableItems).toEqual([]); + }); }); test('dataView set triggers loading', async () => { From 7f46cfd03daedec83095a1e5b02181df54489579 Mon Sep 17 00:00:00 2001 From: Eyo Okon Eyo Date: Tue, 15 Oct 2024 11:52:08 +0100 Subject: [PATCH 16/18] improve test for loading state --- .../hooks/persist_exception_item.test.ts | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts b/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts index de5463d7dbcdb..6100e206b006d 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts +++ b/x-pack/plugins/lists/public/exceptions/hooks/persist_exception_item.test.ts @@ -29,8 +29,8 @@ describe('usePersistExceptionItem', () => { const onError = jest.fn(); beforeEach(() => { - jest.spyOn(api, 'addExceptionListItem').mockResolvedValue(getExceptionListItemSchemaMock()); - jest.spyOn(api, 'updateExceptionListItem').mockResolvedValue(getExceptionListItemSchemaMock()); + (api.addEndpointExceptionList as jest.Mock).mockResolvedValue(getExceptionListItemSchemaMock()); + (api.updateExceptionListItem as jest.Mock).mockResolvedValue(getExceptionListItemSchemaMock()); }); afterEach(() => { @@ -46,20 +46,44 @@ describe('usePersistExceptionItem', () => { }); test('"isLoading" is "true" when exception item is being saved', async () => { - const { result, rerender } = renderHook(() => + const defaultImplementation = (api.addExceptionListItem as jest.Mock).getMockImplementation(); + + (api.addExceptionListItem as jest.Mock).mockImplementation(function () { + // delay response to ensure that isLoading is set to true for a while + return new Promise((resolve) => + setTimeout(() => resolve(getExceptionListItemSchemaMock()), 1000) + ); + }); + + // setup fake timers before rendering + jest.useFakeTimers(); + + const { result } = renderHook(() => usePersistExceptionItem({ http: mockKibanaHttpService, onError }) ); + await waitFor(() => + expect(result.current).toEqual([{ isLoading: false, isSaved: false }, result.current[1]]) + ); + await act(async () => { result.current[1](getCreateExceptionListItemSchemaMock()); }); - rerender(); - await waitFor(() => { - expect(result.current[0].isLoading).toBe(true); + expect(api.addExceptionListItem).toHaveBeenCalled(); expect(result.current).toEqual([{ isLoading: true, isSaved: false }, result.current[1]]); }); + + await jest.advanceTimersByTimeAsync(500); + + await waitFor(() => { + expect(result.current).toEqual([{ isLoading: false, isSaved: true }, result.current[1]]); + }); + + // restore real timers + jest.useRealTimers(); + (api.addExceptionListItem as jest.Mock).mockImplementation(defaultImplementation); }); test('"isSaved" is "true" when exception item saved successfully', async () => { From 7172565530b81c89b5f734df00c9023d19f557f6 Mon Sep 17 00:00:00 2001 From: Eyo Okon Eyo Date: Mon, 21 Oct 2024 12:48:04 +0200 Subject: [PATCH 17/18] resolve feedback from teams --- x-pack/plugins/ml/common/types/storage.test.tsx | 12 +----------- .../contexts/ml/ml_notifications_context.test.tsx | 3 +-- .../application/hooks/use_as_observable.test.ts | 4 +--- .../rules/use_rule_from_timeline.test.ts | 7 ++++--- 4 files changed, 7 insertions(+), 19 deletions(-) diff --git a/x-pack/plugins/ml/common/types/storage.test.tsx b/x-pack/plugins/ml/common/types/storage.test.tsx index b00e639507d23..0be6362323b2e 100644 --- a/x-pack/plugins/ml/common/types/storage.test.tsx +++ b/x-pack/plugins/ml/common/types/storage.test.tsx @@ -7,9 +7,7 @@ import type { FC } from 'react'; import React from 'react'; -import { renderHook } from '@testing-library/react-hooks'; - -import { act, waitFor } from '@testing-library/react'; +import { act, renderHook } from '@testing-library/react-hooks'; import type { Storage } from '@kbn/kibana-utils-plugin/public'; import { StorageContextProvider, useStorage } from '@kbn/ml-local-storage'; @@ -75,8 +73,6 @@ describe('useStorage', () => { setValue(false); }); - await waitFor(() => null); - expect(result.current[0]).toBe(false); expect(mockSet).toHaveBeenCalledWith('ml.gettingStarted.isDismissed', false); }); @@ -94,8 +90,6 @@ describe('useStorage', () => { setValue(undefined); }); - await waitFor(() => null); - expect(result.current[0]).toBe(undefined); expect(mockRemove).toHaveBeenCalledWith('ml.gettingStarted.isDismissed'); }); @@ -127,8 +121,6 @@ describe('useStorage', () => { ); }); - await waitFor(() => null); - expect(result.current[0]).toBe(undefined); await act(async () => { @@ -140,8 +132,6 @@ describe('useStorage', () => { ); }); - await waitFor(() => null); - expect(result.current[0]).toBe(false); }); }); diff --git a/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.test.tsx b/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.test.tsx index 8a9d6ea1ed0fd..a2623266712dc 100644 --- a/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.test.tsx +++ b/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.test.tsx @@ -5,8 +5,7 @@ * 2.0. */ -import { renderHook } from '@testing-library/react-hooks'; -import { act } from '@testing-library/react'; +import { renderHook, act } from '@testing-library/react-hooks'; import { of, throwError } from 'rxjs'; import { useMlNotifications, MlNotificationsContextProvider } from './ml_notifications_context'; import { useStorage } from '@kbn/ml-local-storage'; diff --git a/x-pack/plugins/ml/public/application/hooks/use_as_observable.test.ts b/x-pack/plugins/ml/public/application/hooks/use_as_observable.test.ts index 8908b09b37e4d..4de820364d561 100644 --- a/x-pack/plugins/ml/public/application/hooks/use_as_observable.test.ts +++ b/x-pack/plugins/ml/public/application/hooks/use_as_observable.test.ts @@ -6,7 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; -import { act, waitFor } from '@testing-library/react'; +import { act } from '@testing-library/react'; import { useAsObservable } from './use_as_observable'; describe('useAsObservable', () => { @@ -53,8 +53,6 @@ describe('useAsObservable', () => { rerender('test update'); }); - await waitFor(() => null); - expect(subscriptionMock).toHaveBeenCalledTimes(2); expect(subscriptionMock).toHaveBeenCalledWith('test update'); expect(observableValue).toEqual('test update'); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.test.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.test.ts index 566af0c99fa23..a093752464d80 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.test.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.test.ts @@ -119,9 +119,10 @@ describe('useRuleFromTimeline', () => { it('does not reset timeline sourcerer if it originally had same data view as the timeline used in the rule', async () => { const { result } = renderHook(() => useRuleFromTimeline(setRuleQuery)); expect(result.current.loading).toEqual(true); - await waitFor(() => null); - expect(setRuleQuery).toHaveBeenCalled(); - expect(mockDispatch).toHaveBeenCalledTimes(2); + await waitFor(() => { + expect(setRuleQuery).toHaveBeenCalled(); + expect(mockDispatch).toHaveBeenCalledTimes(2); + }); }); }); From f841c8b93fd593bf788173aa487ed3c009165d01 Mon Sep 17 00:00:00 2001 From: Karen Grigoryan Date: Tue, 22 Oct 2024 20:59:46 +0200 Subject: [PATCH 18/18] chore: fix failed tests for threat-hunting team --- .../dashboards/hooks/use_security_dashboards_table.test.tsx | 6 ++++-- .../trigger_actions_alert_table/use_cell_actions.test.tsx | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/security_solution/public/dashboards/hooks/use_security_dashboards_table.test.tsx b/x-pack/plugins/security_solution/public/dashboards/hooks/use_security_dashboards_table.test.tsx index 9f387550937b2..333bb43fe83e2 100644 --- a/x-pack/plugins/security_solution/public/dashboards/hooks/use_security_dashboards_table.test.tsx +++ b/x-pack/plugins/security_solution/public/dashboards/hooks/use_security_dashboards_table.test.tsx @@ -71,8 +71,10 @@ describe('Security Dashboards Table hooks', () => { describe('useSecurityDashboardsTableItems', () => { it('should request when renders', async () => { - await renderUseSecurityDashboardsTableItems(); - expect(getDashboardsByTagIds).toHaveBeenCalledTimes(1); + renderHook(() => useSecurityDashboardsTableItems(), { + wrapper: DashboardContextProvider, + }); + await waitFor(() => expect(getDashboardsByTagIds).toHaveBeenCalledTimes(1)); }); it('should not request again when rerendered', async () => { diff --git a/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_cell_actions.test.tsx b/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_cell_actions.test.tsx index 04f8246ea33ca..2de889d37b39e 100644 --- a/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_cell_actions.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_cell_actions.test.tsx @@ -101,13 +101,13 @@ describe('getUseCellActionsHook', () => { } ); - await waitFor(() => null); + await waitFor(() => expect(result.current.getCellActions('host.name', 0)).toHaveLength(1)); const cellAction = result.current.getCellActions('host.name', 0)[0]; renderCellAction(cellAction); - expect(screen.getByTestId('dataGridColumnCellAction-action1')).toBeInTheDocument(); + expect(await screen.findByTestId('dataGridColumnCellAction-action1')).toBeInTheDocument(); }); it('should not render cell actions correctly for eventRendered view', async () => {