['security'], undefined>;
+ security?: RouteSecurity;
/**
* When enabled, the router will also check for the presence of an `apiVersion`
* query parameter to determine the route version to resolve to:
@@ -337,7 +338,7 @@ export interface AddVersionOpts {
*/
validate: false | VersionedRouteValidation
| (() => VersionedRouteValidation
); // Provide a way to lazily load validation schemas
- security?: Exclude['security'], undefined>;
+ security?: RouteSecurity;
options?: {
deprecated?: RouteDeprecationInfo;
diff --git a/packages/kbn-server-route-repository-utils/src/typings.ts b/packages/kbn-server-route-repository-utils/src/typings.ts
index 35a2f41054c99..fc4fbe8ab6da6 100644
--- a/packages/kbn-server-route-repository-utils/src/typings.ts
+++ b/packages/kbn-server-route-repository-utils/src/typings.ts
@@ -15,6 +15,7 @@ import type {
Logger,
RequestHandlerContext,
RouteConfigOptions,
+ RouteSecurity,
RouteMethod,
} from '@kbn/core/server';
import type { ServerSentEvent } from '@kbn/sse-utils';
@@ -277,5 +278,5 @@ export interface DefaultRouteHandlerResources extends CoreRouteHandlerResources
}
export interface DefaultRouteCreateOptions {
- options?: RouteConfigOptions;
+ options?: RouteConfigOptions & { security?: RouteSecurity };
}
diff --git a/packages/kbn-server-route-repository/src/register_routes.ts b/packages/kbn-server-route-repository/src/register_routes.ts
index 5e0fa51a4544f..6e7b0d839b2f8 100644
--- a/packages/kbn-server-route-repository/src/register_routes.ts
+++ b/packages/kbn-server-route-repository/src/register_routes.ts
@@ -137,11 +137,14 @@ export function registerRoutes>({
validationObject = passThroughValidationObject;
}
+ const { security, ...restOptions } = options ?? {};
+
if (!version) {
router[method](
{
path: pathname,
- options,
+ security,
+ options: restOptions,
validate: validationObject,
},
wrappedHandler
@@ -150,7 +153,8 @@ export function registerRoutes>({
router.versioned[method]({
path: pathname,
access: pathname.startsWith('/internal/') ? 'internal' : 'public',
- options,
+ options: restOptions,
+ security,
}).addVersion(
{
version,
diff --git a/x-pack/plugins/ai_infra/product_doc_base/server/routes/installation.ts b/x-pack/plugins/ai_infra/product_doc_base/server/routes/installation.ts
index dbede9f7d94d3..1e6b5545ebb4e 100644
--- a/x-pack/plugins/ai_infra/product_doc_base/server/routes/installation.ts
+++ b/x-pack/plugins/ai_infra/product_doc_base/server/routes/installation.ts
@@ -29,10 +29,10 @@ export const registerInstallationRoutes = ({
validate: false,
options: {
access: 'internal',
- security: {
- authz: {
- requiredPrivileges: ['manage_llm_product_doc'],
- },
+ },
+ security: {
+ authz: {
+ requiredPrivileges: ['manage_llm_product_doc'],
},
},
},
@@ -56,13 +56,13 @@ export const registerInstallationRoutes = ({
validate: false,
options: {
access: 'internal',
- security: {
- authz: {
- requiredPrivileges: ['manage_llm_product_doc'],
- },
- },
timeout: { idleSocket: 20 * 60 * 1000 }, // install can take time.
},
+ security: {
+ authz: {
+ requiredPrivileges: ['manage_llm_product_doc'],
+ },
+ },
},
async (ctx, req, res) => {
const { documentationManager } = getServices();
@@ -90,10 +90,10 @@ export const registerInstallationRoutes = ({
validate: false,
options: {
access: 'internal',
- security: {
- authz: {
- requiredPrivileges: ['manage_llm_product_doc'],
- },
+ },
+ security: {
+ authz: {
+ requiredPrivileges: ['manage_llm_product_doc'],
},
},
},
From 3890bde1ab9510adc7b6b8333861d3de51381ef5 Mon Sep 17 00:00:00 2001
From: "Eyo O. Eyo" <7893459+eokoneyo@users.noreply.github.com>
Date: Fri, 22 Nov 2024 17:43:23 +0100
Subject: [PATCH 10/38] [React18] Migrate test suites to account for testing
library upgrades response-ops (#201141)
This PR migrates test suites that use `renderHook` from the library
`@testing-library/react-hooks` to adopt the equivalent and replacement
of `renderHook` from the export that is now available from
`@testing-library/react`. This work is required for the planned
migration to react18.
## Context
In this PR, usages of `waitForNextUpdate` that previously could have
been destructured from `renderHook` are now been replaced with `waitFor`
exported from `@testing-library/react`, furthermore `waitFor`
that would also have been destructured from the same renderHook result
is now been replaced with `waitFor` from the export of
`@testing-library/react`.
***Why is `waitFor` a sufficient enough replacement for
`waitForNextUpdate`, and better for testing values subject to async
computations?***
WaitFor will retry the provided callback if an error is returned, till
the configured timeout elapses. By default the retry interval is `50ms`
with a timeout value of `1000ms` that
effectively translates to at least 20 retries for assertions placed
within waitFor. See
https://testing-library.com/docs/dom-testing-library/api-async/#waitfor
for more information.
This however means that for person's writing tests, said person has to
be explicit about expectations that describe the internal state of the
hook being tested.
This implies checking for instance when a react query hook is being
rendered, there's an assertion that said hook isn't loading anymore.
In this PR you'd notice that this pattern has been adopted, with most
existing assertions following an invocation of `waitForNextUpdate` being
placed within a `waitFor`
invocation. In some cases the replacement is simply a `waitFor(() => new
Promise((resolve) => resolve(null)))` (many thanks to @kapral18, for
point out exactly why this works),
where this suffices the assertions that follow aren't placed within a
waitFor so this PR doesn't get larger than it needs to be.
It's also worth pointing out this PR might also contain changes to test
and application code to improve said existing test.
### What to do next?
1. Review the changes in this PR.
2. If you think the changes are correct, approve the PR.
## Any questions?
If you have any questions or need help with this PR, please leave
comments in this PR.
---
.../use_filters_sync_to_local_storage.test.ts | 78 ++++---
.../hooks/use_alerts_data_view.test.tsx | 23 +-
.../src/common/hooks/use_create_rule.test.tsx | 3 +-
.../use_fetch_alerts_fields_query.test.tsx | 62 ++---
...se_fetch_alerts_index_names_query.test.tsx | 6 +-
.../use_fetch_flapping_settings.test.tsx | 22 +-
...t_alerts_group_aggregations_query.test.tsx | 3 +-
.../common/hooks/use_health_check.test.tsx | 3 +-
.../hooks/use_load_connector_types.test.tsx | 3 +-
.../common/hooks/use_load_connectors.test.tsx | 3 +-
...oad_rule_type_aad_template_fields.test.tsx | 3 +-
.../common/hooks/use_resolve_rule.test.tsx | 3 +-
.../hooks/use_search_alerts_query.test.tsx | 216 +++++++++---------
.../src/common/hooks/use_update_rule.test.tsx | 3 +-
.../use_virtual_data_view_query.test.tsx | 11 +-
.../hooks/use_load_dependencies.test.tsx | 3 +-
.../rule_form_state_reducer.test.tsx | 2 +-
.../src/hooks/state/reducer.test.ts | 2 +-
.../src/hooks/use_get_group_selector.test.tsx | 2 +-
.../src/hooks/use_grouping.test.tsx | 153 ++++++-------
.../use_archive_maintenance_window.test.tsx | 4 +-
.../public/hooks/use_breadcrumbs.test.tsx | 2 +-
.../use_create_maintenance_window.test.tsx | 4 +-
.../use_find_maintenance_windows.test.tsx | 4 +-
...sh_and_archive_maintenance_window.test.tsx | 4 +-
.../use_finish_maintenance_window.test.tsx | 4 +-
.../hooks/use_get_maintenance_window.test.tsx | 4 +-
.../public/hooks/use_license.test.tsx | 2 +-
.../public/hooks/use_navigation.test.tsx | 2 +-
.../use_update_maintenance_window.test.tsx | 4 +-
.../common/apm/use_cases_transactions.test.ts | 14 +-
.../cases/public/common/hooks.test.tsx | 2 +-
.../public/common/lib/kibana/hooks.test.tsx | 7 +-
.../lib/kibana/use_application.test.tsx | 2 +-
.../public/common/navigation/hooks.test.tsx | 3 +-
.../public/common/use_cases_features.test.tsx | 40 ++--
.../common/use_cases_local_storage.test.tsx | 2 +-
.../public/common/use_cases_toast.test.tsx | 3 +-
.../public/common/use_is_user_typing.test.tsx | 2 +-
.../cases/public/common/use_license.test.tsx | 2 +-
.../assignees/use_assignees_action.test.tsx | 8 +-
.../copy_id/use_copy_id_action.test.tsx | 6 +-
.../actions/delete/use_delete_action.test.tsx | 10 +-
.../severity/use_severity_action.test.tsx | 8 +-
.../actions/status/use_status_action.test.tsx | 8 +-
.../actions/tags/use_tags_action.test.tsx | 8 +-
.../actions/use_items_action.test.tsx | 24 +-
.../actions/use_items_state.test.tsx | 2 +-
.../all_cases/all_cases_list.test.tsx | 9 +-
..._cases_add_to_existing_case_modal.test.tsx | 14 +-
.../use_filter_config.test.tsx | 6 +-
.../components/all_cases/use_actions.test.tsx | 3 +-
.../all_cases/use_all_cases_state.test.tsx | 3 +-
.../all_cases/use_bulk_actions.test.tsx | 41 ++--
.../all_cases/use_cases_columns.test.tsx | 2 +-
.../use_cases_columns_configuration.test.tsx | 2 +-
.../use_cases_columns_selection.test.tsx | 2 +-
.../all_cases/use_on_refresh_cases.test.tsx | 2 +-
.../app/use_available_owners.test.ts | 2 +-
.../app/use_readonly_header.test.tsx | 2 +-
.../state/use_is_add_to_case_open.test.tsx | 7 +-
.../use_get_fields_by_issue_type.test.tsx | 8 +-
.../connectors/jira/use_get_issue.test.tsx | 24 +-
.../jira/use_get_issue_types.test.tsx | 8 +-
.../connectors/jira/use_get_issues.test.tsx | 37 +--
.../resilient/use_get_incident_types.test.tsx | 8 +-
.../resilient/use_get_severity.test.tsx | 8 +-
.../servicenow/use_get_choices.test.tsx | 8 +-
.../use_cases_add_to_new_case_flyout.test.tsx | 13 +-
.../use_cancel_creation_action.test.tsx | 2 +-
.../files/use_file_preview.test.tsx | 2 +-
.../files/use_files_table_columns.test.tsx | 2 +-
.../use_markdown_session_storage.test.tsx | 35 +--
.../components/use_breadcrumbs/index.test.tsx | 2 +-
.../use_create_case_modal/index.test.tsx | 29 +--
.../use_push_to_service/index.test.tsx | 135 +++--------
.../use_delete_property_action.test.tsx | 2 +-
.../user_actions/use_last_page.test.tsx | 2 +-
.../use_user_actions_handler.test.tsx | 2 +-
.../use_user_actions_last_page.test.tsx | 8 +-
.../use_user_actions_pagination.test.tsx | 12 +-
.../configure/use_action_types.test.tsx | 8 +-
.../use_get_all_case_configurations.test.ts | 64 ++----
.../use_get_case_configuration.test.tsx | 26 +--
.../use_get_case_configurations_query.test.ts | 3 +-
...t_supported_action_connectors.tsx.test.tsx | 33 ++-
.../use_persist_configuration.test.tsx | 18 +-
.../containers/use_bulk_update_case.test.tsx | 40 ++--
.../use_create_attachments.test.tsx | 25 +-
.../containers/use_delete_cases.test.tsx | 40 ++--
.../containers/use_delete_comment.test.tsx | 72 +++---
.../use_delete_file_attachment.test.tsx | 41 ++--
.../use_find_case_user_actions.test.tsx | 82 ++++---
.../use_get_action_license.test.tsx | 13 +-
.../public/containers/use_get_case.test.tsx | 21 +-
.../use_get_case_connectors.test.tsx | 6 +-
.../use_get_case_file_stats.test.tsx | 20 +-
.../containers/use_get_case_files.test.tsx | 20 +-
.../containers/use_get_case_metrics.test.tsx | 19 +-
.../use_get_case_user_actions_stats.test.tsx | 28 ++-
.../containers/use_get_case_users.test.tsx | 20 +-
.../public/containers/use_get_cases.test.tsx | 14 +-
.../containers/use_get_cases_metrics.test.tsx | 26 +--
.../containers/use_get_cases_status.test.tsx | 24 +-
.../containers/use_get_categories.test.tsx | 22 +-
.../containers/use_get_feature_ids.test.tsx | 11 +-
.../public/containers/use_get_tags.test.tsx | 20 +-
...e_infinite_find_case_user_actions.test.tsx | 50 ++--
.../containers/use_messages_storage.test.tsx | 53 ++---
.../public/containers/use_post_case.test.tsx | 32 ++-
.../use_post_push_to_service.test.tsx | 38 ++-
.../use_replace_custom_field.test.tsx | 84 ++++---
.../containers/use_update_case.test.tsx | 48 ++--
.../containers/use_update_comment.test.tsx | 32 ++-
.../user_profiles/use_assignees.test.ts | 2 +-
.../use_bulk_get_user_profiles.test.ts | 32 ++-
.../use_get_current_user_profile.test.ts | 8 +-
.../use_suggest_user_profiles.test.ts | 28 +--
.../test_query_row/use_test_query.test.ts | 2 +-
.../email/use_email_config.test.ts | 61 +++--
.../lib/gen_ai/use_get_dashboard.test.ts | 99 ++++----
.../lib/servicenow/use_choices.test.tsx | 52 ++---
.../lib/servicenow/use_get_app_info.test.tsx | 12 +-
.../lib/servicenow/use_get_choices.test.tsx | 62 ++---
.../swimlane/use_get_application.test.tsx | 143 ++++++------
.../hooks/use_bulk_edit_select.test.tsx | 2 +-
.../hooks/use_create_connector.test.tsx | 14 +-
.../hooks/use_execute_connector.test.tsx | 14 +-
.../use_get_query_delay_setting.test.tsx | 3 +-
.../application/hooks/use_license.test.ts | 2 +-
.../hooks/use_load_alert_summary.test.ts | 29 ++-
.../hooks/use_load_rule_aggregations.test.tsx | 68 +++---
.../application/hooks/use_load_rules.test.tsx | 72 +++---
.../hooks/use_load_tags_query.test.tsx | 76 +++---
.../application/hooks/use_sub_action.test.tsx | 90 ++++----
.../hooks/use_update_rules_settings.test.tsx | 3 +-
.../use_rule_type_ids_by_feature_id.test.ts | 2 +-
.../cases/use_case_view_navigation.test.ts | 14 +-
.../alert_mute/use_get_muted_alerts.test.tsx | 13 +-
.../hooks/alert_mute/use_mute_alert.test.tsx | 3 +-
.../alert_mute/use_unmute_alert.test.tsx | 3 +-
.../hooks/use_bulk_actions.test.tsx | 2 +-
.../hooks/use_bulk_get_cases.test.tsx | 27 +--
.../use_bulk_get_maintenance_windows.test.ts | 19 +-
.../hooks/use_columns/use_columns.test.tsx | 37 ++-
.../alerts_table/hooks/use_pagination.test.ts | 3 +-
.../alerts_table/hooks/use_sorting.test.ts | 3 +-
.../use_rules_list_filter_store.test.tsx | 2 +-
.../rules_list_column_selector.test.tsx | 3 +-
149 files changed, 1523 insertions(+), 1766 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..dafc4e16c899f 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
@@ -8,7 +8,7 @@
*/
import type { ControlGroupRuntimeState } from '@kbn/controls-plugin/public';
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, act, renderHook } from '@testing-library/react';
import { useControlGroupSyncToLocalStorage } from './use_control_group_sync_to_local_storage';
import { Storage } from '@kbn/kibana-utils-plugin/public';
@@ -34,77 +34,97 @@ describe('Filters Sync to Local Storage', () => {
writable: true,
});
});
+
afterEach(() => {
mockLocalStorage = {};
});
- it('should not be undefined if localStorage has initial value', () => {
+
+ it('should not be undefined if localStorage has initial value', async () => {
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);
+ await waitFor(() =>
+ expect(result.current.controlGroupState).toMatchObject(DEFAULT_STORED_VALUE)
+ );
});
- it('should be undefined if localstorage as NO initial value', () => {
- const { result, waitForNextUpdate } = renderHook(() =>
+
+ it('should be undefined if localstorage as NO initial value', async () => {
+ const { result } = renderHook(() =>
useControlGroupSyncToLocalStorage({
Storage,
storageKey: TEST_STORAGE_KEY,
shouldSync: true,
})
);
- waitForNextUpdate();
- expect(result.current.controlGroupState).toBeUndefined();
- expect(result.current.setControlGroupState).toBeTruthy();
+ await waitFor(() =>
+ expect(result.current).toEqual(
+ expect.objectContaining({
+ controlGroupState: undefined,
+ setControlGroupState: expect.any(Function),
+ })
+ )
+ );
});
- it('should be update values to local storage when sync is ON', () => {
- const { result, waitFor } = renderHook(() =>
+ it('should be update values to local storage when sync is ON', async () => {
+ const { result } = renderHook(() =>
useControlGroupSyncToLocalStorage({
Storage,
storageKey: TEST_STORAGE_KEY,
shouldSync: true,
})
);
- waitFor(() => {
+ await waitFor(() => {
expect(result.current.controlGroupState).toBeUndefined();
expect(result.current.setControlGroupState).toBeTruthy();
});
- result.current.setControlGroupState(DEFAULT_STORED_VALUE);
- waitFor(() => {
+ act(() => {
+ result.current.setControlGroupState(DEFAULT_STORED_VALUE);
+ });
+ await waitFor(() => {
expect(result.current.controlGroupState).toMatchObject(DEFAULT_STORED_VALUE);
expect(global.localStorage.getItem(TEST_STORAGE_KEY)).toBe(
JSON.stringify(DEFAULT_STORED_VALUE)
);
});
});
- it('should not update values to local storage when sync is OFF', () => {
- const { waitFor, result, rerender } = renderHook(() =>
- useControlGroupSyncToLocalStorage({
- Storage,
- storageKey: TEST_STORAGE_KEY,
- shouldSync: true,
- })
- );
+ it('should not update values to local storage when sync is OFF', async () => {
+ const initialProps = {
+ Storage,
+ storageKey: TEST_STORAGE_KEY,
+ shouldSync: true,
+ };
+
+ const { result, rerender } = renderHook(useControlGroupSyncToLocalStorage, {
+ initialProps,
+ });
// Sync is ON
- waitFor(() => {
+ await waitFor(() => {
expect(result.current.controlGroupState).toBeUndefined();
expect(result.current.setControlGroupState).toBeTruthy();
});
- result.current.setControlGroupState(DEFAULT_STORED_VALUE);
- waitFor(() => {
+ act(() => {
+ result.current.setControlGroupState(DEFAULT_STORED_VALUE);
+ });
+
+ await waitFor(() => {
expect(result.current.controlGroupState).toMatchObject(DEFAULT_STORED_VALUE);
});
// Sync is OFF
- rerender({ storageKey: TEST_STORAGE_KEY, shouldSync: false });
- result.current.setControlGroupState(ANOTHER_SAMPLE_VALUE);
- waitFor(() => {
+ rerender({ ...initialProps, shouldSync: false });
+
+ act(() => {
+ result.current.setControlGroupState(ANOTHER_SAMPLE_VALUE);
+ });
+
+ await waitFor(() => {
expect(result.current.controlGroupState).toMatchObject(ANOTHER_SAMPLE_VALUE);
// old value
expect(global.localStorage.getItem(TEST_STORAGE_KEY)).toBe(
diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.test.tsx
index 2f4e8598a4cf6..b4945f298a696 100644
--- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.test.tsx
+++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_alerts_data_view.test.tsx
@@ -10,7 +10,7 @@
import React from 'react';
import { AlertConsumers } from '@kbn/rule-data-utils';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { renderHook } from '@testing-library/react-hooks/dom';
+import { renderHook, waitFor } from '@testing-library/react';
import { DataView } from '@kbn/data-views-plugin/common';
import { httpServiceMock } from '@kbn/core-http-browser-mocks';
import { notificationServiceMock } from '@kbn/core-notifications-browser-mocks';
@@ -69,7 +69,7 @@ describe('useAlertsDataView', () => {
dataView: undefined,
};
- const { result, waitFor } = renderHook(
+ const { result } = renderHook(
() =>
useAlertsDataView({
...mockServices,
@@ -84,7 +84,7 @@ describe('useAlertsDataView', () => {
});
it('fetches indexes and fields for non-siem feature ids, returning a DataViewBase object', async () => {
- const { result, waitForValueToChange } = renderHook(
+ const { result } = renderHook(
() =>
useAlertsDataView({
...mockServices,
@@ -95,7 +95,7 @@ describe('useAlertsDataView', () => {
}
);
- await waitForValueToChange(() => result.current.isLoading, { timeout: 5000 });
+ await waitFor(() => result.current.isLoading, { timeout: 5000 });
expect(mockFetchAlertsFields).toHaveBeenCalledTimes(1);
expect(mockFetchAlertsIndexNames).toHaveBeenCalledTimes(1);
@@ -103,7 +103,7 @@ describe('useAlertsDataView', () => {
});
it('only fetches index names for the siem feature id, returning a DataView', async () => {
- const { result, waitFor } = renderHook(
+ const { result } = renderHook(
() => useAlertsDataView({ ...mockServices, featureIds: [AlertConsumers.SIEM] }),
{
wrapper,
@@ -117,7 +117,7 @@ describe('useAlertsDataView', () => {
});
it('does not fetch anything if siem and other feature ids are mixed together', async () => {
- const { result, waitFor } = renderHook(
+ const { result } = renderHook(
() =>
useAlertsDataView({
...mockServices,
@@ -141,7 +141,7 @@ describe('useAlertsDataView', () => {
it('returns an undefined data view if any of the queries fails', async () => {
mockFetchAlertsIndexNames.mockRejectedValue('error');
- const { result, waitFor } = renderHook(
+ const { result } = renderHook(
() => useAlertsDataView({ ...mockServices, featureIds: observabilityFeatureIds }),
{
wrapper,
@@ -159,12 +159,9 @@ describe('useAlertsDataView', () => {
it('shows an error toast if any of the queries fails', async () => {
mockFetchAlertsIndexNames.mockRejectedValue('error');
- const { waitFor } = renderHook(
- () => useAlertsDataView({ ...mockServices, featureIds: observabilityFeatureIds }),
- {
- wrapper,
- }
- );
+ renderHook(() => useAlertsDataView({ ...mockServices, featureIds: observabilityFeatureIds }), {
+ wrapper,
+ });
await waitFor(() => expect(mockServices.toasts.addDanger).toHaveBeenCalled());
});
diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_create_rule.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_create_rule.test.tsx
index b51f878592da8..46768f355dbcf 100644
--- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_create_rule.test.tsx
+++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_create_rule.test.tsx
@@ -9,8 +9,7 @@
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { renderHook } from '@testing-library/react-hooks/dom';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import type { HttpStart } from '@kbn/core-http-browser';
import { useCreateRule } from './use_create_rule';
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..39818fab28cbf 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
@@ -10,7 +10,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, renderHook } 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,35 +88,37 @@ 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);
-
- 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',
+ },
+ ],
+ });
});
});
@@ -132,8 +134,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 () => {
@@ -148,8 +152,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 () => {
@@ -164,9 +170,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/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..c3480a6ce2675 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
@@ -9,7 +9,7 @@
import React, { FunctionComponent } from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } 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 +56,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_fetch_flapping_settings.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_flapping_settings.test.tsx
index 10e1869b9e64c..6aad133fee5e6 100644
--- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_flapping_settings.test.tsx
+++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_fetch_flapping_settings.test.tsx
@@ -9,7 +9,7 @@
import React, { FunctionComponent } from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook, waitFor } from '@testing-library/react';
import { testQueryClientConfig } from '../test_utils/test_query_client_config';
import { useFetchFlappingSettings } from './use_fetch_flapping_settings';
import { httpServiceMock } from '@kbn/core-http-browser-mocks';
@@ -43,12 +43,9 @@ describe('useFetchFlappingSettings', () => {
});
test('should call fetchFlappingSettings with the correct parameters', async () => {
- const { result, waitFor } = renderHook(
- () => useFetchFlappingSettings({ http, enabled: true }),
- {
- wrapper,
- }
- );
+ const { result } = renderHook(() => useFetchFlappingSettings({ http, enabled: true }), {
+ wrapper,
+ });
await waitFor(() => {
return expect(result.current.isInitialLoading).toEqual(false);
@@ -66,12 +63,9 @@ describe('useFetchFlappingSettings', () => {
});
test('should not call fetchFlappingSettings if enabled is false', async () => {
- const { result, waitFor } = renderHook(
- () => useFetchFlappingSettings({ http, enabled: false }),
- {
- wrapper,
- }
- );
+ const { result } = renderHook(() => useFetchFlappingSettings({ http, enabled: false }), {
+ wrapper,
+ });
await waitFor(() => {
return expect(result.current.isInitialLoading).toEqual(false);
@@ -82,7 +76,7 @@ describe('useFetchFlappingSettings', () => {
test('should call onSuccess when the fetching was successful', async () => {
const onSuccessMock = jest.fn();
- const { result, waitFor } = renderHook(
+ const { result } = renderHook(
() => useFetchFlappingSettings({ http, enabled: true, onSuccess: onSuccessMock }),
{
wrapper,
diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.test.tsx
index 14aca036ed87e..50dcf3d7e2900 100644
--- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.test.tsx
+++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_get_alerts_group_aggregations_query.test.tsx
@@ -9,13 +9,12 @@
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { renderHook } from '@testing-library/react-hooks/dom';
import type { HttpStart } from '@kbn/core-http-browser';
import { ToastsStart } from '@kbn/core-notifications-browser';
import { AlertConsumers } from '@kbn/rule-data-utils';
import { useGetAlertsGroupAggregationsQuery } from './use_get_alerts_group_aggregations_query';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import { BASE_RAC_ALERTS_API_PATH } from '../constants';
const queryClient = new QueryClient({
diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_health_check.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_health_check.test.tsx
index da4d5bc3a878c..ecf4ddc685e27 100644
--- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_health_check.test.tsx
+++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_health_check.test.tsx
@@ -9,8 +9,7 @@
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { renderHook } from '@testing-library/react-hooks/dom';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import type { HttpStart } from '@kbn/core-http-browser';
import { useHealthCheck } from './use_health_check';
diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_load_connector_types.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_load_connector_types.test.tsx
index 63e494ab87084..cc21ecef97458 100644
--- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_load_connector_types.test.tsx
+++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_load_connector_types.test.tsx
@@ -9,8 +9,7 @@
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { renderHook } from '@testing-library/react-hooks/dom';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import { httpServiceMock } from '@kbn/core/public/mocks';
import { useLoadConnectorTypes } from './use_load_connector_types';
diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_load_connectors.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_load_connectors.test.tsx
index 6ab5c58cb1514..7d81a67ebce94 100644
--- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_load_connectors.test.tsx
+++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_load_connectors.test.tsx
@@ -9,8 +9,7 @@
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { renderHook } from '@testing-library/react-hooks/dom';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import { httpServiceMock } from '@kbn/core/public/mocks';
import { useLoadConnectors } from './use_load_connectors';
diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_load_rule_type_aad_template_fields.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_load_rule_type_aad_template_fields.test.tsx
index 7d3c0815ffae5..0af35ccddba4e 100644
--- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_load_rule_type_aad_template_fields.test.tsx
+++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_load_rule_type_aad_template_fields.test.tsx
@@ -9,8 +9,7 @@
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { renderHook } from '@testing-library/react-hooks/dom';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import { httpServiceMock } from '@kbn/core/public/mocks';
import { useLoadRuleTypeAadTemplateField } from './use_load_rule_type_aad_template_fields';
diff --git a/packages/kbn-alerts-ui-shared/src/common/hooks/use_resolve_rule.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_resolve_rule.test.tsx
index 4f74179fa8d52..69c3234d812f0 100644
--- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_resolve_rule.test.tsx
+++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_resolve_rule.test.tsx
@@ -9,8 +9,7 @@
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { renderHook } from '@testing-library/react-hooks/dom';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import type { HttpStart } from '@kbn/core-http-browser';
import { useResolveRule } from './use_resolve_rule';
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..4d1d8c93407e7 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
@@ -12,7 +12,7 @@ import { of } from 'rxjs';
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, renderHook } 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,126 +126,128 @@ 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);
- 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_update_rule.test.tsx b/packages/kbn-alerts-ui-shared/src/common/hooks/use_update_rule.test.tsx
index ec3579f20db51..654166f4bbac9 100644
--- a/packages/kbn-alerts-ui-shared/src/common/hooks/use_update_rule.test.tsx
+++ b/packages/kbn-alerts-ui-shared/src/common/hooks/use_update_rule.test.tsx
@@ -9,8 +9,7 @@
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { renderHook } from '@testing-library/react-hooks/dom';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import type { HttpStart } from '@kbn/core-http-browser';
import { useUpdateRule } from './use_update_rule';
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..09be28ec15034 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
@@ -9,7 +9,7 @@
import React, { FunctionComponent } from 'react';
import * as ReactQuery from '@tanstack/react-query';
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } 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 +38,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 }: { indexNames?: string[] }) =>
useVirtualDataViewQuery({ dataViewsService: mockDataViewsService, indexNames }),
{
wrapper,
+ initialProps: {},
}
);
@@ -89,7 +90,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,10 +101,10 @@ describe('useVirtualDataViewQuery', () => {
}
);
- await waitForValueToChange(() => 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-alerts-ui-shared/src/rule_form/hooks/use_load_dependencies.test.tsx b/packages/kbn-alerts-ui-shared/src/rule_form/hooks/use_load_dependencies.test.tsx
index f0a14ac82e4a6..3dd6a6a3cee11 100644
--- a/packages/kbn-alerts-ui-shared/src/rule_form/hooks/use_load_dependencies.test.tsx
+++ b/packages/kbn-alerts-ui-shared/src/rule_form/hooks/use_load_dependencies.test.tsx
@@ -9,8 +9,7 @@
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { renderHook } from '@testing-library/react-hooks/dom';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import type { HttpStart } from '@kbn/core-http-browser';
import type { ToastsStart } from '@kbn/core-notifications-browser';
diff --git a/packages/kbn-alerts-ui-shared/src/rule_form/rule_form_state/rule_form_state_reducer.test.tsx b/packages/kbn-alerts-ui-shared/src/rule_form/rule_form_state/rule_form_state_reducer.test.tsx
index d8e6380462f9b..f560c3ace22ad 100644
--- a/packages/kbn-alerts-ui-shared/src/rule_form/rule_form_state/rule_form_state_reducer.test.tsx
+++ b/packages/kbn-alerts-ui-shared/src/rule_form/rule_form_state/rule_form_state_reducer.test.tsx
@@ -8,7 +8,7 @@
*/
import React, { useReducer } from 'react';
-import { act, renderHook } from '@testing-library/react-hooks/dom';
+import { renderHook, act } from '@testing-library/react';
import { ruleFormStateReducer } from './rule_form_state_reducer';
import { RuleFormState } from '../types';
import { getAction } from '../../common/test_utils/actions_test_utils';
diff --git a/packages/kbn-grouping/src/hooks/state/reducer.test.ts b/packages/kbn-grouping/src/hooks/state/reducer.test.ts
index c056565b7bf11..7d00d64eadd23 100644
--- a/packages/kbn-grouping/src/hooks/state/reducer.test.ts
+++ b/packages/kbn-grouping/src/hooks/state/reducer.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, act } from '@testing-library/react';
import { useReducer } from 'react';
import { groupActions, groupsReducerWithStorage, initialState } from '.';
import { defaultGroup, LOCAL_STORAGE_GROUPING_KEY } from '../..';
diff --git a/packages/kbn-grouping/src/hooks/use_get_group_selector.test.tsx b/packages/kbn-grouping/src/hooks/use_get_group_selector.test.tsx
index 312ccde33e32a..d29e1b63f1ea9 100644
--- a/packages/kbn-grouping/src/hooks/use_get_group_selector.test.tsx
+++ b/packages/kbn-grouping/src/hooks/use_get_group_selector.test.tsx
@@ -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, act } from '@testing-library/react';
import { useGetGroupSelector, useGetGroupSelectorStateless } from './use_get_group_selector';
import { initialState } from './state';
diff --git a/packages/kbn-grouping/src/hooks/use_grouping.test.tsx b/packages/kbn-grouping/src/hooks/use_grouping.test.tsx
index 22957548de314..834db5acaa39f 100644
--- a/packages/kbn-grouping/src/hooks/use_grouping.test.tsx
+++ b/packages/kbn-grouping/src/hooks/use_grouping.test.tsx
@@ -8,9 +8,8 @@
*/
import React from 'react';
-import { act, renderHook } from '@testing-library/react-hooks';
import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';
-import { render } from '@testing-library/react';
+import { render, waitFor, renderHook } from '@testing-library/react';
import { useGrouping } from './use_grouping';
@@ -46,92 +45,86 @@ 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 { 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(() => new Promise((resolve) => resolve(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, waitForNextUpdate } = renderHook(() => useGrouping(defaultArgs));
- await waitForNextUpdate();
- await waitForNextUpdate();
- 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(() => new Promise((resolve) => resolve(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/x-pack/plugins/alerting/public/hooks/use_archive_maintenance_window.test.tsx b/x-pack/plugins/alerting/public/hooks/use_archive_maintenance_window.test.tsx
index e6f58df8d3a7f..367da7e65811a 100644
--- a/x-pack/plugins/alerting/public/hooks/use_archive_maintenance_window.test.tsx
+++ b/x-pack/plugins/alerting/public/hooks/use_archive_maintenance_window.test.tsx
@@ -4,8 +4,8 @@
* 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/dom';
-import { waitFor } from '@testing-library/react';
+
+import { waitFor, renderHook, act } from '@testing-library/react';
import { AppMockRenderer, createAppMockRenderer } from '../lib/test_utils';
import { useArchiveMaintenanceWindow } from './use_archive_maintenance_window';
diff --git a/x-pack/plugins/alerting/public/hooks/use_breadcrumbs.test.tsx b/x-pack/plugins/alerting/public/hooks/use_breadcrumbs.test.tsx
index 9eb5970e86a9f..f06fd2be67996 100644
--- a/x-pack/plugins/alerting/public/hooks/use_breadcrumbs.test.tsx
+++ b/x-pack/plugins/alerting/public/hooks/use_breadcrumbs.test.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import { useBreadcrumbs } from './use_breadcrumbs';
import { MAINTENANCE_WINDOW_DEEP_LINK_IDS } from '../../common';
import { AppMockRenderer, createAppMockRenderer } from '../lib/test_utils';
diff --git a/x-pack/plugins/alerting/public/hooks/use_create_maintenance_window.test.tsx b/x-pack/plugins/alerting/public/hooks/use_create_maintenance_window.test.tsx
index 26d70f2d4e9a8..12564df1bf1b4 100644
--- a/x-pack/plugins/alerting/public/hooks/use_create_maintenance_window.test.tsx
+++ b/x-pack/plugins/alerting/public/hooks/use_create_maintenance_window.test.tsx
@@ -4,8 +4,8 @@
* 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/dom';
-import { waitFor } from '@testing-library/react';
+
+import { waitFor, renderHook, act } from '@testing-library/react';
import { AppMockRenderer, createAppMockRenderer } from '../lib/test_utils';
import { useCreateMaintenanceWindow } from './use_create_maintenance_window';
diff --git a/x-pack/plugins/alerting/public/hooks/use_find_maintenance_windows.test.tsx b/x-pack/plugins/alerting/public/hooks/use_find_maintenance_windows.test.tsx
index d21b145aea937..b543d7940cd9d 100644
--- a/x-pack/plugins/alerting/public/hooks/use_find_maintenance_windows.test.tsx
+++ b/x-pack/plugins/alerting/public/hooks/use_find_maintenance_windows.test.tsx
@@ -4,8 +4,8 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks/dom';
-import { waitFor } from '@testing-library/react';
+
+import { waitFor, renderHook } from '@testing-library/react';
import { AppMockRenderer, createAppMockRenderer } from '../lib/test_utils';
import { useFindMaintenanceWindows } from './use_find_maintenance_windows';
diff --git a/x-pack/plugins/alerting/public/hooks/use_finish_and_archive_maintenance_window.test.tsx b/x-pack/plugins/alerting/public/hooks/use_finish_and_archive_maintenance_window.test.tsx
index 8b55812bd0301..7e453d5d78d59 100644
--- a/x-pack/plugins/alerting/public/hooks/use_finish_and_archive_maintenance_window.test.tsx
+++ b/x-pack/plugins/alerting/public/hooks/use_finish_and_archive_maintenance_window.test.tsx
@@ -4,8 +4,8 @@
* 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/dom';
-import { waitFor } from '@testing-library/react';
+
+import { waitFor, renderHook, act } from '@testing-library/react';
import { AppMockRenderer, createAppMockRenderer } from '../lib/test_utils';
import { useFinishAndArchiveMaintenanceWindow } from './use_finish_and_archive_maintenance_window';
diff --git a/x-pack/plugins/alerting/public/hooks/use_finish_maintenance_window.test.tsx b/x-pack/plugins/alerting/public/hooks/use_finish_maintenance_window.test.tsx
index 6041796fcc00c..fc972eddeafee 100644
--- a/x-pack/plugins/alerting/public/hooks/use_finish_maintenance_window.test.tsx
+++ b/x-pack/plugins/alerting/public/hooks/use_finish_maintenance_window.test.tsx
@@ -4,8 +4,8 @@
* 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/dom';
-import { waitFor } from '@testing-library/react';
+
+import { waitFor, renderHook, act } from '@testing-library/react';
import { AppMockRenderer, createAppMockRenderer } from '../lib/test_utils';
import { useFinishMaintenanceWindow } from './use_finish_maintenance_window';
diff --git a/x-pack/plugins/alerting/public/hooks/use_get_maintenance_window.test.tsx b/x-pack/plugins/alerting/public/hooks/use_get_maintenance_window.test.tsx
index 3003f1003ce12..d58aebe0a1578 100644
--- a/x-pack/plugins/alerting/public/hooks/use_get_maintenance_window.test.tsx
+++ b/x-pack/plugins/alerting/public/hooks/use_get_maintenance_window.test.tsx
@@ -4,8 +4,8 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks/dom';
-import { waitFor } from '@testing-library/react';
+
+import { waitFor, renderHook } from '@testing-library/react';
import { AppMockRenderer, createAppMockRenderer } from '../lib/test_utils';
import { useGetMaintenanceWindow } from './use_get_maintenance_window';
diff --git a/x-pack/plugins/alerting/public/hooks/use_license.test.tsx b/x-pack/plugins/alerting/public/hooks/use_license.test.tsx
index 0611a6ba86aec..f9d4396072574 100644
--- a/x-pack/plugins/alerting/public/hooks/use_license.test.tsx
+++ b/x-pack/plugins/alerting/public/hooks/use_license.test.tsx
@@ -6,7 +6,7 @@
*/
import { licensingMock } from '@kbn/licensing-plugin/public/mocks';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import { useLicense } from './use_license';
import { AppMockRenderer, createAppMockRenderer } from '../lib/test_utils';
diff --git a/x-pack/plugins/alerting/public/hooks/use_navigation.test.tsx b/x-pack/plugins/alerting/public/hooks/use_navigation.test.tsx
index 2ea981db2a4d5..1b7c48ee684e9 100644
--- a/x-pack/plugins/alerting/public/hooks/use_navigation.test.tsx
+++ b/x-pack/plugins/alerting/public/hooks/use_navigation.test.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { act, renderHook } from '@testing-library/react-hooks';
+import { renderHook, act } from '@testing-library/react';
import {
useCreateMaintenanceWindowNavigation,
diff --git a/x-pack/plugins/alerting/public/hooks/use_update_maintenance_window.test.tsx b/x-pack/plugins/alerting/public/hooks/use_update_maintenance_window.test.tsx
index 6ba19c27c362e..a1da94422c898 100644
--- a/x-pack/plugins/alerting/public/hooks/use_update_maintenance_window.test.tsx
+++ b/x-pack/plugins/alerting/public/hooks/use_update_maintenance_window.test.tsx
@@ -4,8 +4,8 @@
* 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/dom';
-import { waitFor } from '@testing-library/react';
+
+import { waitFor, renderHook, act } from '@testing-library/react';
import { AppMockRenderer, createAppMockRenderer } from '../lib/test_utils';
import { useUpdateMaintenanceWindow } from './use_update_maintenance_window';
diff --git a/x-pack/plugins/cases/public/common/apm/use_cases_transactions.test.ts b/x-pack/plugins/cases/public/common/apm/use_cases_transactions.test.ts
index c1cf6b305d48d..9a5709c911fbc 100644
--- a/x-pack/plugins/cases/public/common/apm/use_cases_transactions.test.ts
+++ b/x-pack/plugins/cases/public/common/apm/use_cases_transactions.test.ts
@@ -5,12 +5,8 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import type { CaseAttachmentsWithoutOwner } from '../../types';
-import type {
- StartAddAttachmentToExistingCaseTransaction,
- StartCreateCaseWithAttachmentsTransaction,
-} from './use_cases_transactions';
import {
useAddAttachmentToExistingCaseTransaction,
useCreateCaseWithAttachmentsTransaction,
@@ -37,14 +33,10 @@ const bulkAttachments = [
] as CaseAttachmentsWithoutOwner;
const renderUseCreateCaseWithAttachmentsTransaction = () =>
- renderHook(
- useCreateCaseWithAttachmentsTransaction
- );
+ renderHook(useCreateCaseWithAttachmentsTransaction);
const renderUseAddAttachmentToExistingCaseTransaction = () =>
- renderHook(
- useAddAttachmentToExistingCaseTransaction
- );
+ renderHook(useAddAttachmentToExistingCaseTransaction);
describe('cases transactions', () => {
beforeEach(() => {
diff --git a/x-pack/plugins/cases/public/common/hooks.test.tsx b/x-pack/plugins/cases/public/common/hooks.test.tsx
index d2cea878504bb..85dcfe11aaf5c 100644
--- a/x-pack/plugins/cases/public/common/hooks.test.tsx
+++ b/x-pack/plugins/cases/public/common/hooks.test.tsx
@@ -6,7 +6,7 @@
*/
import React from 'react';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import { TestProviders } from './mock';
import { useIsMainApplication } from './hooks';
diff --git a/x-pack/plugins/cases/public/common/lib/kibana/hooks.test.tsx b/x-pack/plugins/cases/public/common/lib/kibana/hooks.test.tsx
index 60b798d37822a..73d1822c62499 100644
--- a/x-pack/plugins/cases/public/common/lib/kibana/hooks.test.tsx
+++ b/x-pack/plugins/cases/public/common/lib/kibana/hooks.test.tsx
@@ -6,7 +6,7 @@
*/
import React from 'react';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import { useApplicationCapabilities } from './hooks';
import { allCasesPermissions, TestProviders } from '../../mock';
@@ -14,10 +14,7 @@ import { allCasesPermissions, TestProviders } from '../../mock';
describe('hooks', () => {
describe('useApplicationCapabilities', () => {
it('should return the correct capabilities', async () => {
- const { result } = renderHook<
- React.PropsWithChildren<{}>,
- ReturnType
- >(() => useApplicationCapabilities(), {
+ const { result } = renderHook(() => useApplicationCapabilities(), {
wrapper: ({ children }) => {children},
});
diff --git a/x-pack/plugins/cases/public/common/lib/kibana/use_application.test.tsx b/x-pack/plugins/cases/public/common/lib/kibana/use_application.test.tsx
index 81152d3d3c5a1..69c5fc4f8db2e 100644
--- a/x-pack/plugins/cases/public/common/lib/kibana/use_application.test.tsx
+++ b/x-pack/plugins/cases/public/common/lib/kibana/use_application.test.tsx
@@ -7,7 +7,7 @@
import type { PublicAppInfo } from '@kbn/core-application-browser';
import { AppStatus } from '@kbn/core-application-browser';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import { BehaviorSubject, Subject } from 'rxjs';
import type { AppMockRenderer } from '../../mock';
import { createAppMockRenderer } from '../../mock';
diff --git a/x-pack/plugins/cases/public/common/navigation/hooks.test.tsx b/x-pack/plugins/cases/public/common/navigation/hooks.test.tsx
index 2170ed2d0e583..867e4d682695d 100644
--- a/x-pack/plugins/cases/public/common/navigation/hooks.test.tsx
+++ b/x-pack/plugins/cases/public/common/navigation/hooks.test.tsx
@@ -6,7 +6,8 @@
*/
import React from 'react';
-import { act, renderHook } from '@testing-library/react-hooks';
+
+import { renderHook, act } from '@testing-library/react';
import { APP_ID } from '../../../common/constants';
import { useNavigation } from '../lib/kibana';
diff --git a/x-pack/plugins/cases/public/common/use_cases_features.test.tsx b/x-pack/plugins/cases/public/common/use_cases_features.test.tsx
index eeabf3fb0cab2..c4c54af0b1c42 100644
--- a/x-pack/plugins/cases/public/common/use_cases_features.test.tsx
+++ b/x-pack/plugins/cases/public/common/use_cases_features.test.tsx
@@ -6,10 +6,9 @@
*/
import React from 'react';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import { licensingMock } from '@kbn/licensing-plugin/public/mocks';
import type { CasesContextFeatures } from '../../common/ui';
-import type { UseCasesFeatures } from './use_cases_features';
import { useCasesFeatures } from './use_cases_features';
import { TestProviders } from './mock/test_providers';
import type { LicenseType } from '@kbn/licensing-plugin/common/types';
@@ -37,14 +36,9 @@ describe('useCasesFeatures', () => {
it.each(tests)(
'returns isAlertsEnabled=%s and isSyncAlertsEnabled=%s if feature.alerts=%s',
async (isAlertsEnabled, isSyncAlertsEnabled, alerts) => {
- const { result } = renderHook, UseCasesFeatures>(
- () => useCasesFeatures(),
- {
- wrapper: ({ children }) => (
- {children}
- ),
- }
- );
+ const { result } = renderHook(() => useCasesFeatures(), {
+ wrapper: ({ children }) => {children},
+ });
expect(result.current).toEqual({
isAlertsEnabled,
@@ -57,16 +51,13 @@ describe('useCasesFeatures', () => {
);
it('returns the metrics correctly', async () => {
- const { result } = renderHook, UseCasesFeatures>(
- () => useCasesFeatures(),
- {
- wrapper: ({ children }) => (
-
- {children}
-
- ),
- }
- );
+ const { result } = renderHook(() => useCasesFeatures(), {
+ wrapper: ({ children }) => (
+
+ {children}
+
+ ),
+ });
expect(result.current).toEqual({
isAlertsEnabled: true,
@@ -91,12 +82,9 @@ describe('useCasesFeatures', () => {
license: { type },
});
- const { result } = renderHook, UseCasesFeatures>(
- () => useCasesFeatures(),
- {
- wrapper: ({ children }) => {children},
- }
- );
+ const { result } = renderHook(() => useCasesFeatures(), {
+ wrapper: ({ children }) => {children},
+ });
expect(result.current).toEqual({
isAlertsEnabled: true,
diff --git a/x-pack/plugins/cases/public/common/use_cases_local_storage.test.tsx b/x-pack/plugins/cases/public/common/use_cases_local_storage.test.tsx
index 740fa78dc3c0d..92dd5808b6b7a 100644
--- a/x-pack/plugins/cases/public/common/use_cases_local_storage.test.tsx
+++ b/x-pack/plugins/cases/public/common/use_cases_local_storage.test.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { act, renderHook } from '@testing-library/react-hooks';
+import { renderHook, act } from '@testing-library/react';
import { Subject } from 'rxjs';
import type { AppMockRenderer } from './mock/test_providers';
import { createAppMockRenderer } from './mock/test_providers';
diff --git a/x-pack/plugins/cases/public/common/use_cases_toast.test.tsx b/x-pack/plugins/cases/public/common/use_cases_toast.test.tsx
index bb0c0b3a9f53c..c1f7d67a8b8b1 100644
--- a/x-pack/plugins/cases/public/common/use_cases_toast.test.tsx
+++ b/x-pack/plugins/cases/public/common/use_cases_toast.test.tsx
@@ -5,7 +5,6 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
import { useKibana, useToasts } from './lib/kibana';
import type { AppMockRenderer } from './mock';
import { createAppMockRenderer, TestProviders } from './mock';
@@ -14,7 +13,7 @@ import { alertComment, basicComment, mockCase } from '../containers/mock';
import React from 'react';
import userEvent from '@testing-library/user-event';
import type { SupportedCaseAttachment } from '../types';
-import { getByTestId, queryByTestId, screen } from '@testing-library/react';
+import { getByTestId, queryByTestId, screen, renderHook } from '@testing-library/react';
import { OWNER_INFO } from '../../common/constants';
import { useApplication } from './lib/kibana/use_application';
diff --git a/x-pack/plugins/cases/public/common/use_is_user_typing.test.tsx b/x-pack/plugins/cases/public/common/use_is_user_typing.test.tsx
index 229ecc13bba0d..d4ec973469960 100644
--- a/x-pack/plugins/cases/public/common/use_is_user_typing.test.tsx
+++ b/x-pack/plugins/cases/public/common/use_is_user_typing.test.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { act, renderHook } from '@testing-library/react-hooks';
+import { renderHook, act } from '@testing-library/react';
import type { AppMockRenderer } from './mock';
import { createAppMockRenderer } from './mock';
import { useIsUserTyping } from './use_is_user_typing';
diff --git a/x-pack/plugins/cases/public/common/use_license.test.tsx b/x-pack/plugins/cases/public/common/use_license.test.tsx
index 0c28be2ca746d..8a5c29394cc62 100644
--- a/x-pack/plugins/cases/public/common/use_license.test.tsx
+++ b/x-pack/plugins/cases/public/common/use_license.test.tsx
@@ -7,7 +7,7 @@
import React from 'react';
import { licensingMock } from '@kbn/licensing-plugin/public/mocks';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import { TestProviders } from './mock';
import { useLicense } from './use_license';
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..78b7801b699f8 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,7 @@
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
-import { act, renderHook } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useAssigneesAction } from './use_assignees_action';
import * as api from '../../../containers/api';
@@ -56,7 +56,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 +92,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 +118,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..2be5f4b83a23d 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
@@ -7,7 +7,7 @@
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useCopyIDAction } from './use_copy_id_action';
import { basicCase } from '../../../containers/mock';
@@ -58,7 +58,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 +73,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/delete/use_delete_action.test.tsx b/x-pack/plugins/cases/public/components/actions/delete/use_delete_action.test.tsx
index 9730783f39af6..fee612cbf04f7 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,7 @@
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
-import { act, renderHook } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useDeleteAction } from './use_delete_action';
import * as api from '../../../containers/api';
@@ -84,7 +84,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 +112,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 +137,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 +163,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/actions/severity/use_severity_action.test.tsx b/x-pack/plugins/cases/public/components/actions/severity/use_severity_action.test.tsx
index 79ae67610d902..93982ff334c22 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,7 @@
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
-import { act, renderHook } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useSeverityAction } from './use_severity_action';
import * as api from '../../../containers/api';
@@ -80,7 +80,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 +120,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 +153,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 5ad7f9803dd67..9a007e5ea28a9 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,7 @@
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
-import { act, renderHook } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useStatusAction } from './use_status_action';
import * as api from '../../../containers/api';
@@ -82,7 +82,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,
@@ -120,7 +120,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,
@@ -152,7 +152,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..dbe2a1cc17aa5 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,7 @@
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
-import { act, renderHook } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useTagsAction } from './use_tags_action';
import * as api from '../../../containers/api';
@@ -56,7 +56,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 +86,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 +112,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..b1f24562f89bd 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,7 @@
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
-import { act, renderHook } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useItemsAction } from './use_items_action';
import * as api from '../../containers/api';
@@ -54,7 +54,7 @@ describe('useItemsAction', () => {
});
it('closes the flyout', async () => {
- const { result, waitFor } = renderHook(() => useItemsAction(props), {
+ const { result } = renderHook(() => useItemsAction(props), {
wrapper: appMockRender.AppWrapper,
});
@@ -81,7 +81,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 +117,7 @@ describe('useItemsAction', () => {
});
it('calls fieldSelector correctly', async () => {
- const { result, waitFor } = renderHook(() => useItemsAction(props), {
+ const { result } = renderHook(() => useItemsAction(props), {
wrapper: appMockRender.AppWrapper,
});
@@ -142,7 +142,7 @@ describe('useItemsAction', () => {
});
it('calls itemsTransformer correctly', async () => {
- const { result, waitFor } = renderHook(() => useItemsAction(props), {
+ const { result } = renderHook(() => useItemsAction(props), {
wrapper: appMockRender.AppWrapper,
});
@@ -169,7 +169,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 +203,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 +229,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 +254,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 +279,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 +304,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 +329,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/actions/use_items_state.test.tsx b/x-pack/plugins/cases/public/components/actions/use_items_state.test.tsx
index a680ec655652a..e0f07eaf1a5cd 100644
--- a/x-pack/plugins/cases/public/components/actions/use_items_state.test.tsx
+++ b/x-pack/plugins/cases/public/components/actions/use_items_state.test.tsx
@@ -7,7 +7,7 @@
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
-import { act, renderHook } from '@testing-library/react-hooks';
+import { renderHook, act } from '@testing-library/react';
import { useItemsState } from './use_items_state';
import { basicCase } from '../../containers/mock';
diff --git a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx
index bc540040cce57..5c79aadbcfeeb 100644
--- a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx
@@ -7,8 +7,7 @@
import React from 'react';
import moment from 'moment-timezone';
-import { render, waitFor, screen, within } from '@testing-library/react';
-import { renderHook } from '@testing-library/react-hooks';
+import { render, waitFor, screen, within, renderHook } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl';
@@ -27,7 +26,6 @@ import { SECURITY_SOLUTION_OWNER } from '../../../common/constants';
import { getEmptyCellValue } from '../empty_value';
import { useKibana } from '../../common/lib/kibana';
import { AllCasesList } from './all_cases_list';
-import type { GetCasesColumn, UseCasesColumnsReturnValue } from './use_cases_columns';
import { useCasesColumns } from './use_cases_columns';
import { triggersActionsUiMock } from '@kbn/triggers-actions-ui-plugin/public/mocks';
import { registerConnectorsToMockActionRegistry } from '../../common/mock/register_connectors';
@@ -267,10 +265,7 @@ describe.skip('AllCasesListGeneric', () => {
expect(column[key].querySelector('span')).toHaveTextContent(emptyTag);
};
- const { result } = renderHook<
- React.PropsWithChildren,
- UseCasesColumnsReturnValue
- >(() => useCasesColumns(defaultColumnArgs), {
+ const { result } = renderHook(() => useCasesColumns(defaultColumnArgs), {
wrapper: ({ children }) => {children},
});
diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx
index 644c67b632df1..dbe7412a5d7b5 100644
--- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx
@@ -5,8 +5,7 @@
* 2.0.
*/
-import { waitFor } from '@testing-library/react';
-import { act, renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook, act } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import type { FC, PropsWithChildren } from 'react';
import React from 'react';
@@ -96,12 +95,11 @@ describe('use cases add to existing case modal hook', () => {
});
it('should throw if called outside of a cases context', () => {
- const { result } = renderHook(() => {
- useCasesAddToExistingCaseModal(defaultParams());
- });
- expect(result.error?.message).toContain(
- 'useCasesContext must be used within a CasesProvider and have a defined value'
- );
+ expect(() =>
+ renderHook(() => {
+ useCasesAddToExistingCaseModal(defaultParams());
+ })
+ ).toThrow(/useCasesContext must be used within a CasesProvider and have a defined value/);
});
it('should dispatch the open action when invoked', () => {
diff --git a/x-pack/plugins/cases/public/components/all_cases/table_filter_config/use_filter_config.test.tsx b/x-pack/plugins/cases/public/components/all_cases/table_filter_config/use_filter_config.test.tsx
index 89419d587237c..c38486dfb7ea4 100644
--- a/x-pack/plugins/cases/public/components/all_cases/table_filter_config/use_filter_config.test.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/table_filter_config/use_filter_config.test.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
import React from 'react';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import type { FilterConfig, FilterConfigRenderParams } from './types';
@@ -64,7 +64,7 @@ describe('useFilterConfig', () => {
it('should remove a selected option if the filter is deleted', async () => {
const { rerender } = renderHook(useFilterConfig, {
- wrapper: ({ children }: React.PropsWithChildren[0]>) => (
+ wrapper: ({ children }: React.PropsWithChildren) => (
{children}
),
initialProps: {
@@ -106,7 +106,7 @@ describe('useFilterConfig', () => {
);
const { result } = renderHook(useFilterConfig, {
- wrapper: ({ children }: React.PropsWithChildren[0]>) => (
+ wrapper: ({ children }: React.PropsWithChildren) => (
{children}
),
initialProps: {
diff --git a/x-pack/plugins/cases/public/components/all_cases/use_actions.test.tsx b/x-pack/plugins/cases/public/components/all_cases/use_actions.test.tsx
index bb0ba6ed009e1..e98926bcd0b40 100644
--- a/x-pack/plugins/cases/public/components/all_cases/use_actions.test.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/use_actions.test.tsx
@@ -6,8 +6,7 @@
*/
import userEvent, { type UserEvent } from '@testing-library/user-event';
-import { waitFor } from '@testing-library/react';
-import { renderHook } from '@testing-library/react-hooks/dom';
+import { waitFor, renderHook } from '@testing-library/react';
import {
waitForEuiPopoverOpen,
waitForEuiContextMenuPanelTransition,
diff --git a/x-pack/plugins/cases/public/components/all_cases/use_all_cases_state.test.tsx b/x-pack/plugins/cases/public/components/all_cases/use_all_cases_state.test.tsx
index 1e257c8fbcefd..511edce760a48 100644
--- a/x-pack/plugins/cases/public/components/all_cases/use_all_cases_state.test.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/use_all_cases_state.test.tsx
@@ -6,8 +6,7 @@
*/
import React from 'react';
-import { renderHook, act } from '@testing-library/react-hooks';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook, act } from '@testing-library/react';
import { CaseStatuses } from '@kbn/cases-components';
import { TestProviders } from '../../common/mock';
diff --git a/x-pack/plugins/cases/public/components/all_cases/use_bulk_actions.test.tsx b/x-pack/plugins/cases/public/components/all_cases/use_bulk_actions.test.tsx
index 1838ee3b14f59..2bbd7da38545d 100644
--- a/x-pack/plugins/cases/public/components/all_cases/use_bulk_actions.test.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/use_bulk_actions.test.tsx
@@ -8,8 +8,7 @@
import React from 'react';
import { EuiContextMenu } from '@elastic/eui';
import userEvent from '@testing-library/user-event';
-import { waitFor } from '@testing-library/react';
-import { renderHook } from '@testing-library/react-hooks/dom';
+import { waitFor, renderHook } from '@testing-library/react';
import type { AppMockRenderer } from '../../common/mock';
import {
@@ -190,7 +189,7 @@ describe('useBulkActions', () => {
it('change the status of cases', async () => {
const updateCasesSpy = jest.spyOn(api, 'updateCases');
- const { result, waitFor: waitForHook } = renderHook(
+ const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
@@ -219,7 +218,7 @@ describe('useBulkActions', () => {
pointerEventsCheck: 0,
});
- await waitForHook(() => {
+ await waitFor(() => {
expect(updateCasesSpy).toHaveBeenCalled();
});
});
@@ -227,7 +226,7 @@ describe('useBulkActions', () => {
it('change the severity of cases', async () => {
const updateCasesSpy = jest.spyOn(api, 'updateCases');
- const { result, waitFor: waitForHook } = renderHook(
+ const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
@@ -257,7 +256,7 @@ describe('useBulkActions', () => {
pointerEventsCheck: 0,
});
- await waitForHook(() => {
+ await waitFor(() => {
expect(updateCasesSpy).toHaveBeenCalled();
});
});
@@ -266,7 +265,7 @@ describe('useBulkActions', () => {
it('delete a case', async () => {
const deleteSpy = jest.spyOn(api, 'deleteCases');
- const { result, waitFor: waitForHook } = renderHook(
+ const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
@@ -299,7 +298,7 @@ describe('useBulkActions', () => {
await userEvent.click(res.getByTestId('confirmModalConfirmButton'));
- await waitForHook(() => {
+ await waitFor(() => {
expect(deleteSpy).toHaveBeenCalled();
});
});
@@ -355,7 +354,7 @@ describe('useBulkActions', () => {
it('change the tags of the case', async () => {
const updateCasesSpy = jest.spyOn(api, 'updateCases');
- const { result, waitFor: waitForHook } = renderHook(
+ const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
@@ -394,7 +393,7 @@ describe('useBulkActions', () => {
await userEvent.click(res.getByText('coke'));
await userEvent.click(res.getByTestId('cases-edit-tags-flyout-submit'));
- await waitForHook(() => {
+ await waitFor(() => {
expect(updateCasesSpy).toHaveBeenCalled();
});
});
@@ -402,7 +401,7 @@ describe('useBulkActions', () => {
it('change the assignees of the case', async () => {
const updateCasesSpy = jest.spyOn(api, 'updateCases');
- const { result, waitFor: waitForHook } = renderHook(
+ const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
@@ -441,7 +440,7 @@ describe('useBulkActions', () => {
await userEvent.click(res.getByText('Damaged Raccoon'));
await userEvent.click(res.getByTestId('cases-edit-assignees-flyout-submit'));
- await waitForHook(() => {
+ await waitFor(() => {
expect(updateCasesSpy).toHaveBeenCalled();
});
});
@@ -450,7 +449,7 @@ describe('useBulkActions', () => {
describe('Permissions', () => {
it('shows the correct actions with all permissions', async () => {
appMockRender = createAppMockRenderer({ permissions: allCasesPermissions() });
- const { result, waitFor: waitForHook } = renderHook(
+ const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
@@ -467,7 +466,7 @@ describe('useBulkActions', () => {
>
);
- await waitForHook(() => {
+ await waitFor(() => {
expect(res.getByTestId('case-bulk-action-status')).toBeInTheDocument();
expect(res.getByTestId('cases-bulk-action-delete')).toBeInTheDocument();
expect(res.getByTestId('bulk-actions-separator')).toBeInTheDocument();
@@ -476,7 +475,7 @@ describe('useBulkActions', () => {
it('shows the correct actions with no delete permissions', async () => {
appMockRender = createAppMockRenderer({ permissions: noDeleteCasesPermissions() });
- const { result, waitFor: waitForHook } = renderHook(
+ const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
@@ -493,7 +492,7 @@ describe('useBulkActions', () => {
>
);
- await waitForHook(() => {
+ await waitFor(() => {
expect(res.getByTestId('case-bulk-action-status')).toBeInTheDocument();
expect(res.queryByTestId('cases-bulk-action-delete')).toBeFalsy();
expect(res.queryByTestId('bulk-actions-separator')).toBeFalsy();
@@ -502,7 +501,7 @@ describe('useBulkActions', () => {
it('shows the correct actions with only delete permissions', async () => {
appMockRender = createAppMockRenderer({ permissions: onlyDeleteCasesPermission() });
- const { result, waitFor: waitForHook } = renderHook(
+ const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
@@ -519,7 +518,7 @@ describe('useBulkActions', () => {
>
);
- await waitForHook(() => {
+ await waitFor(() => {
expect(res.queryByTestId('case-bulk-action-status')).toBeFalsy();
expect(res.getByTestId('cases-bulk-action-delete')).toBeInTheDocument();
expect(res.queryByTestId('bulk-actions-separator')).toBeFalsy();
@@ -528,7 +527,7 @@ describe('useBulkActions', () => {
it('shows the correct actions with no reopen permissions', async () => {
appMockRender = createAppMockRenderer({ permissions: noReopenCasesPermissions() });
- const { result, waitFor: waitForHook } = renderHook(
+ const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCaseClosed] }),
{
wrapper: appMockRender.AppWrapper,
@@ -545,12 +544,12 @@ describe('useBulkActions', () => {
>
);
- await waitForHook(() => {
+ await waitFor(() => {
expect(res.queryByTestId('case-bulk-action-status')).toBeInTheDocument();
res.queryByTestId('case-bulk-action-status')?.click();
});
- await waitForHook(() => {
+ await waitFor(() => {
expect(res.queryByTestId('cases-bulk-action-status-open')).toBeDisabled();
expect(res.queryByTestId('cases-bulk-action-status-in-progress')).toBeDisabled();
expect(res.queryByTestId('cases-bulk-action-status-closed')).toBeDisabled();
diff --git a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.test.tsx b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.test.tsx
index 22783cf05cfc1..550240060ddf6 100644
--- a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.test.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.test.tsx
@@ -15,7 +15,7 @@ import { useGetCasesMockState } from '../../containers/mock';
import { connectors, useCaseConfigureResponse } from '../configure_cases/__mock__';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer, readCasesPermissions, TestProviders } from '../../common/mock';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import { CaseStatuses, CustomFieldTypes } from '../../../common/types/domain';
import { userProfilesMap } from '../../containers/user_profiles/api.mock';
import { useGetCaseConfiguration } from '../../containers/configure/use_get_case_configuration';
diff --git a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_configuration.test.tsx b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_configuration.test.tsx
index 761da1d6316e8..4a4a139445c5e 100644
--- a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_configuration.test.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_configuration.test.tsx
@@ -6,7 +6,7 @@
*/
import { licensingMock } from '@kbn/licensing-plugin/public/mocks';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
diff --git a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_selection.test.tsx b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_selection.test.tsx
index 26f0f8c2fb85e..e6603a35a1a04 100644
--- a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_selection.test.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_selection.test.tsx
@@ -6,7 +6,7 @@
*/
import { licensingMock } from '@kbn/licensing-plugin/public/mocks';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import type { AppMockRenderer } from '../../common/mock';
diff --git a/x-pack/plugins/cases/public/components/all_cases/use_on_refresh_cases.test.tsx b/x-pack/plugins/cases/public/components/all_cases/use_on_refresh_cases.test.tsx
index 484fabca00c3d..338055e5da0cd 100644
--- a/x-pack/plugins/cases/public/components/all_cases/use_on_refresh_cases.test.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/use_on_refresh_cases.test.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { act, renderHook } from '@testing-library/react-hooks';
+import { renderHook, act } from '@testing-library/react';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { casesQueriesKeys } from '../../containers/constants';
diff --git a/x-pack/plugins/cases/public/components/app/use_available_owners.test.ts b/x-pack/plugins/cases/public/components/app/use_available_owners.test.ts
index 4cd015de0c92e..5a19e9a0f995b 100644
--- a/x-pack/plugins/cases/public/components/app/use_available_owners.test.ts
+++ b/x-pack/plugins/cases/public/components/app/use_available_owners.test.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import { APP_ID, OBSERVABILITY_OWNER, SECURITY_SOLUTION_OWNER } from '../../../common/constants';
import { useKibana } from '../../common/lib/kibana';
diff --git a/x-pack/plugins/cases/public/components/app/use_readonly_header.test.tsx b/x-pack/plugins/cases/public/components/app/use_readonly_header.test.tsx
index 9be5a6336b3c2..69d7a9a8b65a8 100644
--- a/x-pack/plugins/cases/public/components/app/use_readonly_header.test.tsx
+++ b/x-pack/plugins/cases/public/components/app/use_readonly_header.test.tsx
@@ -6,7 +6,7 @@
*/
import React from 'react';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import { useKibana } from '../../common/lib/kibana';
import { readCasesPermissions, TestProviders } from '../../common/mock';
diff --git a/x-pack/plugins/cases/public/components/cases_context/state/use_is_add_to_case_open.test.tsx b/x-pack/plugins/cases/public/components/cases_context/state/use_is_add_to_case_open.test.tsx
index 9974d0cb530d9..61cf355229664 100644
--- a/x-pack/plugins/cases/public/components/cases_context/state/use_is_add_to_case_open.test.tsx
+++ b/x-pack/plugins/cases/public/components/cases_context/state/use_is_add_to_case_open.test.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { act, renderHook } from '@testing-library/react-hooks';
+import { renderHook, act } from '@testing-library/react';
import { useCasesAddToExistingCaseModal } from '../../all_cases/selector_modal/use_cases_add_to_existing_case_modal';
import { createAppMockRenderer } from '../../../common/mock';
import { useIsAddToCaseOpen } from './use_is_add_to_case_open';
@@ -26,9 +26,8 @@ describe('use is add to existing case modal open hook', () => {
});
it('should throw if called outside of a cases context', () => {
- const { result } = renderHook(useIsAddToCaseOpen);
- expect(result.error?.message).toContain(
- 'useCasesStateContext must be used within a CasesProvider and have a defined value'
+ expect(() => renderHook(useIsAddToCaseOpen)).toThrow(
+ /useCasesStateContext must be used within a CasesProvider and have a defined value/
);
});
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..b529139644d53 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useKibana, useToasts } from '../../../common/lib/kibana';
import { connector } from '../mock';
@@ -30,7 +30,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 +88,7 @@ describe('useGetFieldsByIssueType', () => {
const addError = jest.fn();
(useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError });
- const { waitFor } = renderHook(
+ renderHook(
() =>
useGetFieldsByIssueType({
http,
@@ -114,7 +114,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..04f1995f6cc8f 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useKibana, useToasts } from '../../../common/lib/kibana';
import { connector as actionConnector } from '../mock';
@@ -30,7 +30,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,
@@ -40,7 +40,7 @@ describe('useGetIssue', () => {
{ wrapper: appMockRender.AppWrapper }
);
- await waitFor(() => result.current.isSuccess);
+ await waitFor(() => expect(result.current.isSuccess).toBe(true));
expect(spy).toHaveBeenCalledWith({
http,
@@ -88,7 +88,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,
@@ -98,9 +98,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 () => {
@@ -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,
@@ -124,8 +125,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/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..dde59c2dd64bb 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useKibana, useToasts } from '../../../common/lib/kibana';
import { connector } from '../mock';
@@ -30,7 +30,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 +70,7 @@ describe('useGetIssueTypes', () => {
const addError = jest.fn();
(useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError });
- const { waitFor } = renderHook(
+ renderHook(
() =>
useGetIssueTypes({
http,
@@ -95,7 +95,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..b43a231e4eb0b 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useKibana, useToasts } from '../../../common/lib/kibana';
import { connector as actionConnector } from '../mock';
@@ -30,7 +30,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,
@@ -40,13 +40,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',
+ });
});
});
@@ -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,
@@ -84,9 +85,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 () => {
@@ -100,7 +102,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,
@@ -110,8 +112,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/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..bfe20b4dc4dea 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useKibana, useToasts } from '../../../common/lib/kibana';
import { connector } from '../mock';
@@ -30,7 +30,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 +70,7 @@ describe('useGetIncidentTypes', () => {
const addError = jest.fn();
(useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError });
- const { waitFor } = renderHook(
+ renderHook(
() =>
useGetIncidentTypes({
http,
@@ -95,7 +95,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..71d09a0cc68e9 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useKibana, useToasts } from '../../../common/lib/kibana';
import { connector } from '../mock';
@@ -30,7 +30,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 +70,7 @@ describe('useGetSeverity', () => {
const addError = jest.fn();
(useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError });
- const { waitFor } = renderHook(
+ renderHook(
() =>
useGetSeverity({
http,
@@ -95,7 +95,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..3f44f4c30f7cf 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useKibana, useToasts } from '../../../common/lib/kibana';
import type { ActionConnector } from '../../../../common/types/domain';
@@ -47,7 +47,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 +92,7 @@ describe('useGetChoices', () => {
const addError = jest.fn();
(useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError });
- const { waitFor } = renderHook(
+ renderHook(
() =>
useGetChoices({
http,
@@ -118,7 +118,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/create/flyout/use_cases_add_to_new_case_flyout.test.tsx b/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.test.tsx
index 168cae0e478fc..0d1ad5b8b65b6 100644
--- a/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.test.tsx
+++ b/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.test.tsx
@@ -6,7 +6,7 @@
*/
import { alertComment } from '../../../containers/mock';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import type { FC, PropsWithChildren } from 'react';
import React from 'react';
import { CasesContext } from '../../cases_context';
@@ -47,12 +47,11 @@ describe('use cases add to new case flyout hook', () => {
});
it('should throw if called outside of a cases context', () => {
- const { result } = renderHook(() => {
- useCasesAddToNewCaseFlyout();
- });
- expect(result.error?.message).toContain(
- 'useCasesContext must be used within a CasesProvider and have a defined value'
- );
+ expect(() =>
+ renderHook(() => {
+ useCasesAddToNewCaseFlyout();
+ })
+ ).toThrow(/useCasesContext must be used within a CasesProvider and have a defined value/);
});
it('should dispatch the open action when invoked without attachments', () => {
diff --git a/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.test.tsx b/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.test.tsx
index 4174d33c44d2f..080009feb1847 100644
--- a/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.test.tsx
+++ b/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.test.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook, act } from '@testing-library/react-hooks';
+import { renderHook, act } from '@testing-library/react';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { useCancelCreationAction } from './use_cancel_creation_action';
diff --git a/x-pack/plugins/cases/public/components/files/use_file_preview.test.tsx b/x-pack/plugins/cases/public/components/files/use_file_preview.test.tsx
index 49e18fb818cd9..f5a502f490775 100644
--- a/x-pack/plugins/cases/public/components/files/use_file_preview.test.tsx
+++ b/x-pack/plugins/cases/public/components/files/use_file_preview.test.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { act, renderHook } from '@testing-library/react-hooks';
+import { renderHook, act } from '@testing-library/react';
import { useFilePreview } from './use_file_preview';
diff --git a/x-pack/plugins/cases/public/components/files/use_files_table_columns.test.tsx b/x-pack/plugins/cases/public/components/files/use_files_table_columns.test.tsx
index 0467bb7a2efee..a064667f93c0f 100644
--- a/x-pack/plugins/cases/public/components/files/use_files_table_columns.test.tsx
+++ b/x-pack/plugins/cases/public/components/files/use_files_table_columns.test.tsx
@@ -9,7 +9,7 @@ import type { FilesTableColumnsProps } from './use_files_table_columns';
import { useFilesTableColumns } from './use_files_table_columns';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import { basicCase } from '../../containers/mock';
describe('useFilesTableColumns', () => {
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..06a92712f63d2 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,11 +5,9 @@
* 2.0.
*/
-import { renderHook, act } from '@testing-library/react-hooks';
+import { waitFor, renderHook, act } 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 = {
@@ -45,7 +43,7 @@ describe('useMarkdownSessionStorage', () => {
});
it('should return hasConflicts as false', async () => {
- const { result, waitFor } = renderHook(() =>
+ const { result } = renderHook(() =>
useMarkdownSessionStorage({ field, sessionKey, initialValue })
);
@@ -55,7 +53,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 +64,7 @@ describe('useMarkdownSessionStorage', () => {
});
it('should update the session value with field value when it is first render', async () => {
- const { waitFor } = renderHook(
+ renderHook(
(props) => {
return useMarkdownSessionStorage(props);
},
@@ -86,7 +84,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(
(props) => {
return useMarkdownSessionStorage(props);
},
@@ -101,8 +99,6 @@ describe('useMarkdownSessionStorage', () => {
jest.advanceTimersByTime(1000);
});
- await waitForComponentToUpdate();
-
await waitFor(() => {
expect(result.current.hasConflicts).toBe(false);
expect(sessionStorage.getItem(sessionKey)).toBe(specialCharsValue);
@@ -110,7 +106,7 @@ describe('useMarkdownSessionStorage', () => {
});
it('should update session value ', async () => {
- const { result, rerender, waitFor } = renderHook(
+ const { result, rerender } = renderHook(
(props) => {
return useMarkdownSessionStorage(props);
},
@@ -129,8 +125,6 @@ describe('useMarkdownSessionStorage', () => {
jest.advanceTimersByTime(1000);
});
- await waitForComponentToUpdate();
-
await waitFor(() => {
expect(result.current.hasConflicts).toBe(false);
expect(sessionStorage.getItem(sessionKey)).toBe('new value');
@@ -138,7 +132,7 @@ describe('useMarkdownSessionStorage', () => {
});
it('should return has conflict true', async () => {
- const { result, rerender, waitFor } = renderHook(
+ const { result, rerender } = renderHook(
(props) => {
return useMarkdownSessionStorage(props);
},
@@ -162,7 +156,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(
(props) => {
return useMarkdownSessionStorage(props);
},
@@ -171,8 +165,6 @@ describe('useMarkdownSessionStorage', () => {
}
);
- await waitForComponentToUpdate();
-
await waitFor(() => {
expect(field.setValue).toHaveBeenCalled();
});
@@ -181,8 +173,6 @@ describe('useMarkdownSessionStorage', () => {
jest.advanceTimersByTime(1000);
});
- await waitForComponentToUpdate();
-
await waitFor(() => {
expect(result.current.hasConflicts).toBe(false);
expect(field.value).toBe(sessionStorage.getItem(sessionKey));
@@ -190,10 +180,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(
(props) => {
return useMarkdownSessionStorage(props);
},
@@ -202,8 +189,6 @@ describe('useMarkdownSessionStorage', () => {
}
);
- await waitForComponentToUpdate();
-
await waitFor(() => {
expect(field.setValue).toHaveBeenCalled();
});
@@ -218,8 +203,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/components/use_breadcrumbs/index.test.tsx b/x-pack/plugins/cases/public/components/use_breadcrumbs/index.test.tsx
index 9f48783fde24d..b494bd1d81839 100644
--- a/x-pack/plugins/cases/public/components/use_breadcrumbs/index.test.tsx
+++ b/x-pack/plugins/cases/public/components/use_breadcrumbs/index.test.tsx
@@ -7,7 +7,7 @@
import type { ReactNode } from 'react';
import React from 'react';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import { TestProviders } from '../../common/mock';
import { useCasesBreadcrumbs, useCasesTitleBreadcrumbs } from '.';
import { CasesDeepLinkId } from '../../common/navigation';
diff --git a/x-pack/plugins/cases/public/components/use_create_case_modal/index.test.tsx b/x-pack/plugins/cases/public/components/use_create_case_modal/index.test.tsx
index dcef6d26393aa..56599299fd0a7 100644
--- a/x-pack/plugins/cases/public/components/use_create_case_modal/index.test.tsx
+++ b/x-pack/plugins/cases/public/components/use_create_case_modal/index.test.tsx
@@ -6,10 +6,10 @@
*/
import React from 'react';
-import { renderHook, act } from '@testing-library/react-hooks';
+
+import { renderHook, act } from '@testing-library/react';
import { useKibana } from '../../common/lib/kibana';
-import type { UseCreateCaseModalProps, UseCreateCaseModalReturnedValues } from '.';
import { useCreateCaseModal } from '.';
import { TestProviders } from '../../common/mock';
@@ -27,10 +27,7 @@ describe('useCreateCaseModal', () => {
});
it('init', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- UseCreateCaseModalReturnedValues
- >(() => useCreateCaseModal({ onCaseCreated }), {
+ const { result } = renderHook(() => useCreateCaseModal({ onCaseCreated }), {
wrapper: ({ children }) => {children},
});
@@ -38,10 +35,7 @@ describe('useCreateCaseModal', () => {
});
it('opens the modal', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- UseCreateCaseModalReturnedValues
- >(() => useCreateCaseModal({ onCaseCreated }), {
+ const { result } = renderHook(() => useCreateCaseModal({ onCaseCreated }), {
wrapper: ({ children }) => {children},
});
@@ -53,10 +47,7 @@ describe('useCreateCaseModal', () => {
});
it('closes the modal', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- UseCreateCaseModalReturnedValues
- >(() => useCreateCaseModal({ onCaseCreated }), {
+ const { result } = renderHook(() => useCreateCaseModal({ onCaseCreated }), {
wrapper: ({ children }) => {children},
});
@@ -69,10 +60,7 @@ describe('useCreateCaseModal', () => {
});
it('returns a memoized value', async () => {
- const { result, rerender } = renderHook<
- React.PropsWithChildren,
- UseCreateCaseModalReturnedValues
- >(() => useCreateCaseModal({ onCaseCreated }), {
+ const { result, rerender } = renderHook(() => useCreateCaseModal({ onCaseCreated }), {
wrapper: ({ children }) => {children},
});
@@ -84,10 +72,7 @@ describe('useCreateCaseModal', () => {
});
it('closes the modal when creating a case', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- UseCreateCaseModalReturnedValues
- >(() => useCreateCaseModal({ onCaseCreated }), {
+ const { result } = renderHook(() => useCreateCaseModal({ onCaseCreated }), {
wrapper: ({ children }) => {children},
});
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 75c2694f89479..02e1a99fd0631 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,9 +6,8 @@
*/
import React from 'react';
-import { renderHook, act } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
-import type { ReturnUsePushToService, UsePushToService } from '.';
import { usePushToService } from '.';
import { noPushCasesPermissions, readCasesPermissions, TestProviders } from '../../common/mock';
import { usePostPushToService } from '../../containers/use_post_push_to_service';
@@ -67,10 +66,7 @@ describe('usePushToService', () => {
});
it('calls pushCaseToExternalService with correct arguments', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(() => usePushToService(defaultArgs), {
+ const { result } = renderHook(() => usePushToService(defaultArgs), {
wrapper: ({ children }) => {children},
});
@@ -93,10 +89,7 @@ describe('usePushToService', () => {
},
}));
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(() => usePushToService(defaultArgs), {
+ const { result } = renderHook(() => usePushToService(defaultArgs), {
wrapper: ({ children }) => {children},
});
@@ -115,10 +108,7 @@ describe('usePushToService', () => {
},
}));
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(() => usePushToService(defaultArgs), {
+ const { result } = renderHook(() => usePushToService(defaultArgs), {
wrapper: ({ children }) => {children},
});
@@ -129,10 +119,7 @@ describe('usePushToService', () => {
});
it('Displays message when user has select none as connector', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(
+ const { result } = renderHook(
() =>
usePushToService({
...defaultArgs,
@@ -155,10 +142,7 @@ describe('usePushToService', () => {
});
it('Displays message when connector is deleted', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(
+ const { result } = renderHook(
() =>
usePushToService({
...defaultArgs,
@@ -182,10 +166,7 @@ describe('usePushToService', () => {
});
it('should not call pushCaseToExternalService when the selected connector is none', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(
+ const { result } = renderHook(
() =>
usePushToService({
...defaultArgs,
@@ -209,10 +190,7 @@ describe('usePushToService', () => {
});
it('refresh case view page after push', async () => {
- const { result, waitFor } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(() => usePushToService(defaultArgs), {
+ const { result } = renderHook(() => usePushToService(defaultArgs), {
wrapper: ({ children }) => {children},
});
@@ -227,10 +205,7 @@ describe('usePushToService', () => {
describe('user does not have write or push permissions', () => {
it('returns correct information about push permissions', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(() => usePushToService(defaultArgs), {
+ const { result } = renderHook(() => usePushToService(defaultArgs), {
wrapper: ({ children }) => (
{children}
),
@@ -248,10 +223,7 @@ describe('usePushToService', () => {
},
}));
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(() => usePushToService(defaultArgs), {
+ const { result } = renderHook(() => usePushToService(defaultArgs), {
wrapper: ({ children }) => (
{children}
),
@@ -270,10 +242,7 @@ describe('usePushToService', () => {
},
}));
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(() => usePushToService(defaultArgs), {
+ const { result } = renderHook(() => usePushToService(defaultArgs), {
wrapper: ({ children }) => (
{children}
),
@@ -284,10 +253,7 @@ describe('usePushToService', () => {
});
it('does not display a message when user does not have any connector configured', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(
+ const { result } = renderHook(
() =>
usePushToService({
...defaultArgs,
@@ -310,10 +276,7 @@ describe('usePushToService', () => {
});
it('does not display a message when user does have a connector but is configured to none', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(
+ const { result } = renderHook(
() =>
usePushToService({
...defaultArgs,
@@ -336,10 +299,7 @@ describe('usePushToService', () => {
});
it('does not display a message when connector is deleted', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(
+ const { result } = renderHook(
() =>
usePushToService({
...defaultArgs,
@@ -363,10 +323,7 @@ describe('usePushToService', () => {
});
it('does not display a message when case is closed', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(
+ const { result } = renderHook(
() =>
usePushToService({
...defaultArgs,
@@ -386,10 +343,7 @@ describe('usePushToService', () => {
describe('returned values', () => {
it('initial', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(() => usePushToService(defaultArgs), {
+ const { result } = renderHook(() => usePushToService(defaultArgs), {
wrapper: ({ children }) => {children},
});
@@ -408,10 +362,7 @@ describe('usePushToService', () => {
it('isLoading is true when usePostPushToService is loading', async () => {
usePostPushToServiceMock.mockReturnValue({ ...mockPostPush, isLoading: true });
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(() => usePushToService(defaultArgs), {
+ const { result } = renderHook(() => usePushToService(defaultArgs), {
wrapper: ({ children }) => {children},
});
@@ -424,10 +375,7 @@ describe('usePushToService', () => {
data: actionLicense,
});
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(() => usePushToService(defaultArgs), {
+ const { result } = renderHook(() => usePushToService(defaultArgs), {
wrapper: ({ children }) => {children},
});
@@ -435,21 +383,18 @@ describe('usePushToService', () => {
});
it('hasErrorMessages=true if there are error messages', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(() => usePushToService({ ...defaultArgs, isValidConnector: false }), {
- wrapper: ({ children }) => {children},
- });
+ const { result } = renderHook(
+ () => usePushToService({ ...defaultArgs, isValidConnector: false }),
+ {
+ wrapper: ({ children }) => {children},
+ }
+ );
expect(result.current.hasErrorMessages).toBe(true);
});
it('needsToBePushed=true if the connector needs to be pushed', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(
+ const { result } = renderHook(
() =>
usePushToService({
...defaultArgs,
@@ -473,10 +418,7 @@ describe('usePushToService', () => {
});
it('needsToBePushed=false if the connector does not exist', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(
+ const { result } = renderHook(
() =>
usePushToService({
...defaultArgs,
@@ -497,10 +439,7 @@ describe('usePushToService', () => {
});
it('hasBeenPushed=false if the connector has been pushed', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(
+ const { result } = renderHook(
() =>
usePushToService({
...defaultArgs,
@@ -524,10 +463,7 @@ describe('usePushToService', () => {
});
it('hasBeenPushed=false if the connector does not exist', async () => {
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(
+ const { result } = renderHook(
() =>
usePushToService({
...defaultArgs,
@@ -553,10 +489,7 @@ describe('usePushToService', () => {
data: actionLicense,
});
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(() => usePushToService(defaultArgs), {
+ const { result } = renderHook(() => usePushToService(defaultArgs), {
wrapper: ({ children }) => (
{children}
),
@@ -574,10 +507,7 @@ describe('usePushToService', () => {
},
}));
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(() => usePushToService(defaultArgs), {
+ const { result } = renderHook(() => usePushToService(defaultArgs), {
wrapper: ({ children }) => {children},
});
@@ -590,10 +520,7 @@ describe('usePushToService', () => {
data: undefined,
}));
- const { result } = renderHook<
- React.PropsWithChildren,
- ReturnUsePushToService
- >(() => usePushToService(defaultArgs), {
+ const { result } = renderHook(() => usePushToService(defaultArgs), {
wrapper: ({ children }) => {children},
});
diff --git a/x-pack/plugins/cases/public/components/user_actions/property_actions/use_delete_property_action.test.tsx b/x-pack/plugins/cases/public/components/user_actions/property_actions/use_delete_property_action.test.tsx
index 2db865ee3b22b..dba35699e2d8d 100644
--- a/x-pack/plugins/cases/public/components/user_actions/property_actions/use_delete_property_action.test.tsx
+++ b/x-pack/plugins/cases/public/components/user_actions/property_actions/use_delete_property_action.test.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook, act } from '@testing-library/react-hooks';
+import { renderHook, act } from '@testing-library/react';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { useDeletePropertyAction } from './use_delete_property_action';
diff --git a/x-pack/plugins/cases/public/components/user_actions/use_last_page.test.tsx b/x-pack/plugins/cases/public/components/user_actions/use_last_page.test.tsx
index 525fe19771e41..a05097e7f7b2b 100644
--- a/x-pack/plugins/cases/public/components/user_actions/use_last_page.test.tsx
+++ b/x-pack/plugins/cases/public/components/user_actions/use_last_page.test.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import { useLastPage } from './use_last_page';
import type { UserActivityParams } from '../user_actions_activity_bar/types';
diff --git a/x-pack/plugins/cases/public/components/user_actions/use_user_actions_handler.test.tsx b/x-pack/plugins/cases/public/components/user_actions/use_user_actions_handler.test.tsx
index 3600a247540f5..4acd8ce0ee10e 100644
--- a/x-pack/plugins/cases/public/components/user_actions/use_user_actions_handler.test.tsx
+++ b/x-pack/plugins/cases/public/components/user_actions/use_user_actions_handler.test.tsx
@@ -7,7 +7,7 @@
import type { FC, PropsWithChildren } from 'react';
import React from 'react';
-import { renderHook, act } from '@testing-library/react-hooks';
+import { renderHook, act } from '@testing-library/react';
import { basicCase } from '../../containers/mock';
import { useUpdateComment } from '../../containers/use_update_comment';
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..ec50c60bb559c 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useLastPageUserActions } from './use_user_actions_last_page';
import type { UserActivityParams } from '../user_actions_activity_bar/types';
@@ -32,7 +32,7 @@ describe('useLastPageUserActions', () => {
});
it('renders correctly', async () => {
- const { result, waitFor } = renderHook(() =>
+ const { result } = renderHook(() =>
useLastPageUserActions({
lastPage: 5,
userActivityQueryParams,
@@ -79,7 +79,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 +108,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/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..21702583e0292 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useUserActionsPagination } from './use_user_actions_pagination';
import type { UserActivityParams } from '../user_actions_activity_bar/types';
@@ -32,7 +32,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 +62,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 +92,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 +124,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 +161,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_action_types.test.tsx b/x-pack/plugins/cases/public/containers/configure/use_action_types.test.tsx
index 5718b07438a98..99d79484b17cc 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import * as api from './api';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
@@ -43,10 +43,10 @@ describe('useActionTypes', () => {
(useToasts as jest.Mock).mockReturnValue({ addError: addErrorMock });
- const { waitForNextUpdate } = renderHook(() => useGetActionTypes(), {
+ renderHook(() => useGetActionTypes(), {
wrapper: appMockRenderer.AppWrapper,
});
- await waitForNextUpdate({ timeout: 2000 });
- expect(addErrorMock).toHaveBeenCalled();
+
+ await waitFor(() => 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..52d4df20e5401 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useGetAllCaseConfigurations } from './use_get_all_case_configurations';
import * as api from './api';
import type { AppMockRenderer } from '../../common/mock';
@@ -32,18 +32,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();
-
- /**
- * Ensures that the initial data is returned≠
- * before fetching
- */
- // @ts-expect-error: data is defined
- expect(result.all[0].data).toEqual([
+ expect(result.current.data).toEqual([
{
closureType: 'close-by-user',
connector: { fields: null, id: 'none', name: 'none', type: '.none' },
@@ -56,43 +49,36 @@ describe('Use get all case configurations hook', () => {
},
]);
- /**
- * 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' },
- ]);
+ await waitFor(() =>
+ expect(result.current.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 () => {
const spy = jest.spyOn(api, 'getCaseConfigure');
spy.mockResolvedValue([]);
- const { result, waitForNextUpdate } = renderHook(() => useGetAllCaseConfigurations(), {
+ const { result } = renderHook(() => useGetAllCaseConfigurations(), {
wrapper: appMockRender.AppWrapper,
});
- await waitForNextUpdate();
-
- /**
- * 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(() =>
+ expect(result.current.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_case_configuration.test.tsx b/x-pack/plugins/cases/public/containers/configure/use_get_case_configuration.test.tsx
index e504bd22e9cc8..35faebd12a788 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useGetCaseConfiguration } from './use_get_case_configuration';
import * as api from './api';
import type { AppMockRenderer } from '../../common/mock';
@@ -35,16 +35,14 @@ describe('Use get case configuration hook', () => {
targetConfiguration,
]);
- const { result, waitForNextUpdate } = renderHook(() => useGetCaseConfiguration(), {
+ const { result } = renderHook(() => useGetCaseConfiguration(), {
wrapper: appMockRender.AppWrapper,
});
- await waitForNextUpdate();
-
/**
* 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 () => {
@@ -59,16 +57,14 @@ 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();
-
/**
* 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 () => {
@@ -76,16 +72,14 @@ describe('Use get case configuration hook', () => {
spy.mockResolvedValue([]);
- const { result, waitForNextUpdate } = renderHook(() => useGetCaseConfiguration(), {
+ const { result } = renderHook(() => useGetCaseConfiguration(), {
wrapper: appMockRender.AppWrapper,
});
- await waitForNextUpdate();
-
/**
* 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 () => {
@@ -94,15 +88,13 @@ describe('Use get case configuration hook', () => {
spy.mockResolvedValue([]);
- const { result, waitForNextUpdate } = renderHook(() => useGetCaseConfiguration(), {
+ const { result } = renderHook(() => useGetCaseConfiguration(), {
wrapper: appMockRender.AppWrapper,
});
- await waitForNextUpdate();
-
/**
* 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/configure/use_get_case_configurations_query.test.ts b/x-pack/plugins/cases/public/containers/configure/use_get_case_configurations_query.test.ts
index adc06ad840d90..02cb834421445 100644
--- a/x-pack/plugins/cases/public/containers/configure/use_get_case_configurations_query.test.ts
+++ b/x-pack/plugins/cases/public/containers/configure/use_get_case_configurations_query.test.ts
@@ -5,10 +5,9 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
import { useGetCaseConfigurationsQuery } from './use_get_case_configurations_query';
import * as api from './api';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import { useToasts } from '../../common/lib/kibana';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
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..c9dad2340f2b8 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
@@ -6,7 +6,7 @@
*/
import React from 'react';
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import * as api from './api';
import { noConnectorsCasePermission, TestProviders } from '../../common/mock';
import { useApplicationCapabilities, useToasts } from '../../common/lib/kibana';
@@ -26,15 +26,13 @@ describe('useConnectors', () => {
it('fetches connectors', async () => {
const spy = jest.spyOn(api, 'getSupportedActionConnectors');
- const { waitForNextUpdate } = renderHook(() => useGetSupportedActionConnectors(), {
+ renderHook(() => useGetSupportedActionConnectors(), {
wrapper: ({ children }: React.PropsWithChildren<{}>) => (
{children}
),
});
- await waitForNextUpdate();
-
- 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 () => {
@@ -46,45 +44,44 @@ describe('useConnectors', () => {
throw new Error('Something went wrong');
});
- const { waitForNextUpdate } = renderHook(() => useGetSupportedActionConnectors(), {
+ renderHook(() => useGetSupportedActionConnectors(), {
wrapper: ({ children }: React.PropsWithChildren<{}>) => (
{children}
),
});
- await waitForNextUpdate();
- expect(addError).toHaveBeenCalled();
+ await waitFor(() => expect(addError).toHaveBeenCalled());
});
it('does not fetch connectors when the user does not has access to actions', async () => {
const spyOnFetchConnectors = jest.spyOn(api, 'getSupportedActionConnectors');
useApplicationCapabilitiesMock().actions = { crud: false, read: false };
- const { result, waitForNextUpdate } = renderHook(() => useGetSupportedActionConnectors(), {
+ const { result } = renderHook(() => useGetSupportedActionConnectors(), {
wrapper: ({ children }: React.PropsWithChildren<{}>) => (
{children}
),
});
- await waitForNextUpdate();
-
- 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 () => {
const spyOnFetchConnectors = jest.spyOn(api, 'getSupportedActionConnectors');
useApplicationCapabilitiesMock().actions = { crud: true, read: true };
- const { result, waitForNextUpdate } = renderHook(() => useGetSupportedActionConnectors(), {
+ const { result } = renderHook(() => useGetSupportedActionConnectors(), {
wrapper: ({ children }: React.PropsWithChildren<{}>) => (
{children}
),
});
- await waitForNextUpdate();
-
- 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/configure/use_persist_configuration.test.tsx b/x-pack/plugins/cases/public/containers/configure/use_persist_configuration.test.tsx
index 4fab35fd5ce5f..04b266478f667 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,7 @@
* 2.0.
*/
-import { renderHook, act } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { usePersistConfiguration } from './use_persist_configuration';
import * as api from './api';
@@ -55,7 +55,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 +80,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 +104,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 +133,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 +157,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 +184,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 +198,7 @@ describe('usePersistConfiguration', () => {
});
it('shows the success toaster', async () => {
- const { waitFor, result } = renderHook(() => usePersistConfiguration(), {
+ const { result } = renderHook(() => usePersistConfiguration(), {
wrapper: appMockRender.AppWrapper,
});
@@ -216,7 +216,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_bulk_update_case.test.tsx b/x-pack/plugins/cases/public/containers/use_bulk_update_case.test.tsx
index 17b4568cc9de7..50d28921e1aa1 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,7 @@
* 2.0.
*/
-import { renderHook, act } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useUpdateCases } from './use_bulk_update_case';
import { allCases } from './mock';
import { useToasts } from '../common/lib/kibana';
@@ -32,7 +32,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 +40,12 @@ describe('useUpdateCases', () => {
result.current.mutate({ cases: allCases.cases, successToasterTitle: 'Success title' });
});
- await waitForNextUpdate();
-
- expect(spy).toHaveBeenCalledWith({ cases: allCases.cases });
+ await waitFor(() => 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,15 +53,15 @@ describe('useUpdateCases', () => {
result.current.mutate({ cases: allCases.cases, successToasterTitle: 'Success title' });
});
- await waitForNextUpdate();
-
- expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.casesList());
- expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
- expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.userProfiles());
+ await waitFor(() => {
+ expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.casesList());
+ expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
+ expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.userProfiles());
+ });
});
it('shows a success toaster', async () => {
- const { waitForNextUpdate, result } = renderHook(() => useUpdateCases(), {
+ const { result } = renderHook(() => useUpdateCases(), {
wrapper: appMockRender.AppWrapper,
});
@@ -71,18 +69,18 @@ describe('useUpdateCases', () => {
result.current.mutate({ cases: allCases.cases, successToasterTitle: 'Success title' });
});
- await waitForNextUpdate();
-
- expect(addSuccess).toHaveBeenCalledWith({
- title: 'Success title',
- className: 'eui-textBreakWord',
- });
+ await waitFor(() =>
+ expect(addSuccess).toHaveBeenCalledWith({
+ title: 'Success title',
+ className: 'eui-textBreakWord',
+ })
+ );
});
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,8 +88,6 @@ describe('useUpdateCases', () => {
result.current.mutate({ cases: allCases.cases, successToasterTitle: 'Success title' });
});
- await waitForNextUpdate();
-
- expect(addError).toHaveBeenCalled();
+ await waitFor(() => 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..c7aa4b521bcda 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,7 @@
* 2.0.
*/
-import { renderHook, act } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { AttachmentType } from '../../common/types/domain';
import { SECURITY_SOLUTION_OWNER } from '../../common/constants';
@@ -58,7 +58,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 +66,16 @@ describe('useCreateAttachments', () => {
result.current.mutate(request);
});
- await waitForNextUpdate();
-
- expect(spy).toHaveBeenCalledWith({ attachments: attachmentsWithOwner, caseId: request.caseId });
+ await waitFor(() =>
+ 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,9 +83,7 @@ describe('useCreateAttachments', () => {
result.current.mutate(request);
});
- await waitForNextUpdate();
-
- expect(addSuccess).not.toHaveBeenCalled();
+ await waitFor(() => expect(addSuccess).not.toHaveBeenCalled());
});
it('shows a toast error when the api return an error', async () => {
@@ -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,8 +99,6 @@ describe('useCreateAttachments', () => {
result.current.mutate(request);
});
- await waitForNextUpdate();
-
- expect(addError).toHaveBeenCalled();
+ await waitFor(() => 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..405351c3f0681 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,7 @@
* 2.0.
*/
-import { renderHook, act } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useDeleteCases } from './use_delete_cases';
import * as api from './api';
@@ -32,7 +32,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 +40,12 @@ describe('useDeleteCases', () => {
result.current.mutate({ caseIds: ['1', '2'], successToasterTitle: 'Success title' });
});
- await waitForNextUpdate();
-
- expect(spy).toHaveBeenCalledWith({ caseIds: ['1', '2'] });
+ await waitFor(() => 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,15 +53,15 @@ describe('useDeleteCases', () => {
result.current.mutate({ caseIds: ['1', '2'], successToasterTitle: 'Success title' });
});
- await waitForNextUpdate();
-
- expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.casesList());
- expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
- expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.userProfiles());
+ await waitFor(() => {
+ expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.casesList());
+ expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
+ expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.userProfiles());
+ });
});
it('shows a success toaster', async () => {
- const { waitForNextUpdate, result } = renderHook(() => useDeleteCases(), {
+ const { result } = renderHook(() => useDeleteCases(), {
wrapper: appMockRender.AppWrapper,
});
@@ -71,18 +69,18 @@ describe('useDeleteCases', () => {
result.current.mutate({ caseIds: ['1', '2'], successToasterTitle: 'Success title' });
});
- await waitForNextUpdate();
-
- expect(addSuccess).toHaveBeenCalledWith({
- title: 'Success title',
- className: 'eui-textBreakWord',
- });
+ await waitFor(() =>
+ expect(addSuccess).toHaveBeenCalledWith({
+ title: 'Success title',
+ className: 'eui-textBreakWord',
+ })
+ );
});
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,8 +88,6 @@ describe('useDeleteCases', () => {
result.current.mutate({ caseIds: ['1', '2'], successToasterTitle: 'Success title' });
});
- await waitForNextUpdate();
-
- expect(addError).toHaveBeenCalled();
+ await waitFor(() => 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..c3d0739cec370 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,7 @@
* 2.0.
*/
-import { act, renderHook } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useDeleteComment } from './use_delete_comment';
import * as api from './api';
import { basicCaseId } from './mock';
@@ -45,7 +45,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,32 +57,32 @@ describe('useDeleteComment', () => {
});
});
- await waitForNextUpdate();
-
- expect(spyOnDeleteComment).toBeCalledWith({
- caseId: basicCaseId,
- commentId,
- });
+ await waitFor(() =>
+ expect(spyOnDeleteComment).toBeCalledWith({
+ caseId: basicCaseId,
+ commentId,
+ })
+ );
});
it('refreshes the case page view after delete', async () => {
- const { waitForNextUpdate, result } = renderHook(() => useDeleteComment(), {
+ const { result } = renderHook(() => useDeleteComment(), {
wrapper: appMockRender.AppWrapper,
});
- result.current.mutate({
- caseId: basicCaseId,
- commentId,
- successToasterTitle,
+ act(() => {
+ result.current.mutate({
+ caseId: basicCaseId,
+ commentId,
+ successToasterTitle,
+ });
});
- await waitForNextUpdate();
-
- expect(useRefreshCaseViewPage()).toBeCalled();
+ await waitFor(() => expect(useRefreshCaseViewPage()).toBeCalled());
});
it('shows a success toaster correctly', async () => {
- const { waitForNextUpdate, result } = renderHook(() => useDeleteComment(), {
+ const { result } = renderHook(() => useDeleteComment(), {
wrapper: appMockRender.AppWrapper,
});
@@ -94,36 +94,38 @@ describe('useDeleteComment', () => {
});
});
- await waitForNextUpdate();
-
- 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 () => {
const spyOnDeleteComment = jest.spyOn(api, 'deleteComment');
spyOnDeleteComment.mockRejectedValue(new Error('Error'));
- const { waitForNextUpdate, result } = renderHook(() => useDeleteComment(), {
+ const { result } = renderHook(() => useDeleteComment(), {
wrapper: appMockRender.AppWrapper,
});
- result.current.mutate({
- caseId: basicCaseId,
- commentId,
- successToasterTitle,
+ act(() => {
+ result.current.mutate({
+ caseId: basicCaseId,
+ commentId,
+ successToasterTitle,
+ });
});
- await waitForNextUpdate();
+ 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_delete_file_attachment.test.tsx b/x-pack/plugins/cases/public/containers/use_delete_file_attachment.test.tsx
index 51382a0f548da..329423e41dfaa 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,7 @@
* 2.0.
*/
-import { act, renderHook } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } 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 +34,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,16 +45,16 @@ describe('useDeleteFileAttachment', () => {
});
});
- await waitForNextUpdate();
-
- expect(spyOnDeleteFileAttachments).toHaveBeenCalledWith({
- caseId: basicCaseId,
- fileIds: [basicFileMock.id],
- });
+ await waitFor(() =>
+ expect(spyOnDeleteFileAttachments).toHaveBeenCalledWith({
+ caseId: basicCaseId,
+ fileIds: [basicFileMock.id],
+ })
+ );
});
it('refreshes the case page view', async () => {
- const { waitForNextUpdate, result } = renderHook(() => useDeleteFileAttachment(), {
+ const { result } = renderHook(() => useDeleteFileAttachment(), {
wrapper: appMockRender.AppWrapper,
});
@@ -65,13 +65,11 @@ describe('useDeleteFileAttachment', () => {
})
);
- await waitForNextUpdate();
-
- expect(useRefreshCaseViewPage()).toBeCalled();
+ await waitFor(() => expect(useRefreshCaseViewPage()).toBeCalled());
});
it('shows a success toaster correctly', async () => {
- const { waitForNextUpdate, result } = renderHook(() => useDeleteFileAttachment(), {
+ const { result } = renderHook(() => useDeleteFileAttachment(), {
wrapper: appMockRender.AppWrapper,
});
@@ -82,19 +80,19 @@ describe('useDeleteFileAttachment', () => {
})
);
- await waitForNextUpdate();
-
- 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 () => {
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 +103,7 @@ describe('useDeleteFileAttachment', () => {
})
);
- await waitForNextUpdate();
+ await waitFor(() => expect(result.current.isError).toBe(true));
expect(spyOnDeleteFileAttachments).toBeCalledWith({
caseId: basicCaseId,
@@ -113,6 +111,5 @@ describe('useDeleteFileAttachment', () => {
});
expect(addError).toHaveBeenCalled();
- expect(result.current.isError).toBe(true);
});
});
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..7dfaa1ff146ee 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } 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,33 +43,32 @@ describe('UseFindCaseUserActions', () => {
});
it('returns proper state on findCaseUserActions', async () => {
- const { result, waitForNextUpdate } = renderHook(
- () => useFindCaseUserActions(basicCase.id, params, isEnabled),
- { wrapper: appMockRender.AppWrapper }
- );
-
- await waitForNextUpdate();
-
- expect(result.current).toEqual(
- expect.objectContaining({
- ...initialData,
- data: {
- userActions: [...findCaseUserActionsResponse.userActions],
- total: 30,
- perPage: 10,
- page: 1,
- },
- isError: false,
- isLoading: false,
- isFetching: false,
- })
+ const { result } = renderHook(() => useFindCaseUserActions(basicCase.id, params, isEnabled), {
+ wrapper: appMockRender.AppWrapper,
+ });
+
+ 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,
+ })
+ )
);
});
it('calls the API with correct parameters', async () => {
const spy = jest.spyOn(api, 'findCaseUserActions').mockRejectedValue(initialData);
- const { waitForNextUpdate } = renderHook(
+ renderHook(
() =>
useFindCaseUserActions(
basicCase.id,
@@ -84,12 +83,12 @@ describe('UseFindCaseUserActions', () => {
{ wrapper: appMockRender.AppWrapper }
);
- await waitForNextUpdate();
-
- 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)
+ )
);
});
@@ -120,20 +119,17 @@ describe('UseFindCaseUserActions', () => {
const addError = jest.fn();
(useToasts as jest.Mock).mockReturnValue({ addError });
- const { waitForNextUpdate } = renderHook(
- () => useFindCaseUserActions(basicCase.id, params, isEnabled),
- {
- wrapper: appMockRender.AppWrapper,
- }
- );
-
- await waitForNextUpdate();
-
- expect(spy).toHaveBeenCalledWith(
- basicCase.id,
- { type: filterActionType, sortOrder, page: 1, perPage: 10 },
- expect.any(AbortSignal)
- );
- expect(addError).toHaveBeenCalled();
+ renderHook(() => useFindCaseUserActions(basicCase.id, params, isEnabled), {
+ wrapper: appMockRender.AppWrapper,
+ });
+
+ 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_action_license.test.tsx b/x-pack/plugins/cases/public/containers/use_get_action_license.test.tsx
index 43e445fa39aab..33cba9ef71235 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import * as api from './api';
import { useGetActionLicense } from './use_get_action_license';
import type { AppMockRenderer } from '../common/mock';
@@ -25,12 +25,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();
- expect(spyOnGetActionLicense).toBeCalledWith(abortCtrl.signal);
+ await waitFor(() => expect(spyOnGetActionLicense).toBeCalledWith(abortCtrl.signal));
});
it('unhappy path', async () => {
@@ -42,11 +41,9 @@ describe('useGetActionLicense', () => {
throw new Error('Something went wrong');
});
- const { waitForNextUpdate } = renderHook(() => useGetActionLicense(), {
+ renderHook(() => useGetActionLicense(), {
wrapper: appMockRenderer.AppWrapper,
});
- await waitForNextUpdate();
-
- expect(addError).toHaveBeenCalled();
+ await waitFor(() => 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..6f693e5d4dc18 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
@@ -5,10 +5,9 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
import { useGetCase } from './use_get_case';
import * as api from './api';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import type { FC, PropsWithChildren } from 'react';
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
@@ -32,21 +31,21 @@ 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();
- expect(spy).toHaveBeenCalledWith({
- caseId: 'case-1',
- includeComments: true,
- signal: expect.any(AbortSignal),
- });
+ renderHook(() => useGetCase('case-1'), { wrapper });
+ await waitFor(() =>
+ expect(spy).toHaveBeenCalledWith({
+ caseId: 'case-1',
+ includeComments: true,
+ signal: expect.any(AbortSignal),
+ })
+ );
});
it('shows a toast error when the api return an error', async () => {
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(() => {
expect(spy).toHaveBeenCalledWith({
caseId: 'case-1',
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..713f8865cd020 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import * as api from './api';
import type { AppMockRenderer } from '../common/mock';
import { createAppMockRenderer } from '../common/mock';
@@ -30,7 +30,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 +50,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_get_case_file_stats.test.tsx b/x-pack/plugins/cases/public/containers/use_get_case_file_stats.test.tsx
index e7c55cd1fc0c5..dbf800577e850 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { basicCase } from './mock';
@@ -37,12 +37,12 @@ describe('useGetCaseFileStats', () => {
});
it('calls filesClient.list with correct arguments', async () => {
- const { waitForNextUpdate } = renderHook(() => useGetCaseFileStats(hookParams), {
+ renderHook(() => useGetCaseFileStats(hookParams), {
wrapper: appMockRender.AppWrapper,
});
- await waitForNextUpdate();
-
- expect(appMockRender.getFilesClient().list).toHaveBeenCalledWith(expectedCallParams);
+ await waitFor(() =>
+ expect(appMockRender.getFilesClient().list).toHaveBeenCalledWith(expectedCallParams)
+ );
});
it('shows an error toast when filesClient.list throws', async () => {
@@ -53,12 +53,12 @@ describe('useGetCaseFileStats', () => {
throw new Error('Something went wrong');
});
- const { waitForNextUpdate } = renderHook(() => useGetCaseFileStats(hookParams), {
+ renderHook(() => useGetCaseFileStats(hookParams), {
wrapper: appMockRender.AppWrapper,
});
- await waitForNextUpdate();
-
- 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_case_files.test.tsx b/x-pack/plugins/cases/public/containers/use_get_case_files.test.tsx
index 2be8dd6052408..c95eaf15aefe0 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { basicCase } from './mock';
@@ -48,22 +48,22 @@ describe('useGetCaseFiles', () => {
throw new Error('Something went wrong');
});
- const { waitForNextUpdate } = renderHook(() => useGetCaseFiles(hookParams), {
+ renderHook(() => useGetCaseFiles(hookParams), {
wrapper: appMockRender.AppWrapper,
});
- await waitForNextUpdate();
-
- 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 () => {
- const { waitForNextUpdate } = renderHook(() => useGetCaseFiles(hookParams), {
+ renderHook(() => useGetCaseFiles(hookParams), {
wrapper: appMockRender.AppWrapper,
});
- await waitForNextUpdate();
-
- 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 3cda384f1c63c..0feb032649a65 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
@@ -7,7 +7,7 @@
import type { FC, PropsWithChildren } from 'react';
import React from 'react';
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import type { SingleCaseMetricsFeature } from '../../common/ui';
import { useGetCaseMetrics } from './use_get_case_metrics';
import { basicCase } from './mock';
@@ -34,12 +34,13 @@ 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();
- 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 () => {
@@ -51,13 +52,13 @@ describe('useGetCaseMetrics', () => {
throw new Error('Something went wrong');
});
- const { waitForNextUpdate } = renderHook(() => useGetCaseMetrics(basicCase.id, features), {
+ renderHook(() => useGetCaseMetrics(basicCase.id, features), {
wrapper,
});
- await waitForNextUpdate();
-
- 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/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..bd8ecf7393b2a 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
@@ -4,7 +4,8 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+
+import { waitFor, renderHook } from '@testing-library/react';
import { useToasts } from '../common/lib/kibana';
import type { AppMockRenderer } from '../common/mock';
@@ -31,12 +32,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(() => expect(result.current.isLoading).toBe(false));
expect(result.current).toEqual(
expect.objectContaining({
@@ -61,25 +61,23 @@ 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();
-
- 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 () => {
const spy = jest.spyOn(api, 'getCaseUserActionsStats');
- const { waitForNextUpdate } = renderHook(() => useGetCaseUserActionsStats(basicCase.id), {
+ renderHook(() => useGetCaseUserActionsStats(basicCase.id), {
wrapper: appMockRender.AppWrapper,
});
- await waitForNextUpdate();
-
- 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 e35e41c3d49f6..7f425081989b8 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useGetCaseUsers } from './use_get_case_users';
import * as api from './api';
import { useToasts } from '../common/lib/kibana';
@@ -26,13 +26,13 @@ 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();
-
- expect(spy).toHaveBeenCalledWith({ caseId: 'case-1', signal: expect.any(AbortSignal) });
+ await waitFor(() =>
+ expect(spy).toHaveBeenCalledWith({ caseId: 'case-1', signal: expect.any(AbortSignal) })
+ );
});
it('shows a toast error when the api return an error', async () => {
@@ -40,13 +40,13 @@ 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();
-
- 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_cases.test.tsx b/x-pack/plugins/cases/public/containers/use_get_cases.test.tsx
index 92d7abde2f9d2..0719c14e9fc4f 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } 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 +31,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 +55,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 +90,7 @@ describe('useGetCases', () => {
};
const spyOnGetCases = jest.spyOn(api, 'getCases');
- const { waitFor } = renderHook(() => useGetCases(), {
+ renderHook(() => useGetCases(), {
wrapper: appMockRender.AppWrapper,
});
@@ -109,7 +109,7 @@ describe('useGetCases', () => {
appMockRender = createAppMockRenderer({ owner: [] });
const spyOnGetCases = jest.spyOn(api, 'getCases');
- const { waitFor } = renderHook(() => useGetCases(), {
+ renderHook(() => useGetCases(), {
wrapper: appMockRender.AppWrapper,
});
@@ -128,7 +128,7 @@ describe('useGetCases', () => {
appMockRender = createAppMockRenderer({ owner: ['observability'] });
const spyOnGetCases = jest.spyOn(api, 'getCases');
- const { waitFor } = renderHook(() => useGetCases(), {
+ renderHook(() => useGetCases(), {
wrapper: appMockRender.AppWrapper,
});
@@ -147,7 +147,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/cases/public/containers/use_get_cases_metrics.test.tsx b/x-pack/plugins/cases/public/containers/use_get_cases_metrics.test.tsx
index 619e1ea4e1ebf..895d41bbfa4c1 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import * as api from '../api';
import type { AppMockRenderer } from '../common/mock';
import { createAppMockRenderer } from '../common/mock';
@@ -33,17 +33,17 @@ 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();
-
- 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 () => {
@@ -51,12 +51,12 @@ describe('useGetCasesMetrics', () => {
.spyOn(api, 'getCasesMetrics')
.mockRejectedValue(new Error('useGetCasesMetrics: Test error'));
- const { waitForNextUpdate } = renderHook(() => useGetCasesMetrics(), {
+ renderHook(() => useGetCasesMetrics(), {
wrapper: appMockRender.AppWrapper,
});
- await waitForNextUpdate();
-
- 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 fed7159ac15e3..e24ac9d1fec4a 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useGetCasesStatus } from './use_get_cases_status';
import * as api from '../api';
import type { AppMockRenderer } from '../common/mock';
@@ -32,17 +32,17 @@ 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();
-
- 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 () => {
@@ -50,12 +50,10 @@ describe('useGetCasesMetrics', () => {
.spyOn(api, 'getCasesStatus')
.mockRejectedValue(new Error('useGetCasesMetrics: Test error'));
- const { waitForNextUpdate } = renderHook(() => useGetCasesStatus(), {
+ renderHook(() => useGetCasesStatus(), {
wrapper: appMockRender.AppWrapper,
});
- await waitForNextUpdate();
-
- 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 d80f03822ec7a..11b242a3072d0 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
@@ -6,7 +6,7 @@
*/
import React from 'react';
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import * as api from './api';
import { TestProviders } from '../common/mock';
import { SECURITY_SOLUTION_OWNER } from '../../common/constants';
@@ -24,18 +24,18 @@ describe('useGetCategories', () => {
it('calls getCategories api', async () => {
const spyOnGetCategories = jest.spyOn(api, 'getCategories');
- const { waitForNextUpdate } = renderHook(() => useGetCategories(), {
+ renderHook(() => useGetCategories(), {
wrapper: ({ children }: React.PropsWithChildren<{}>) => (
{children}
),
});
- await waitForNextUpdate();
-
- 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 () => {
@@ -47,14 +47,12 @@ describe('useGetCategories', () => {
const addError = jest.fn();
(useToasts as jest.Mock).mockReturnValue({ addError });
- const { waitForNextUpdate } = renderHook(() => useGetCategories(), {
+ renderHook(() => useGetCategories(), {
wrapper: ({ children }: React.PropsWithChildren<{}>) => (
{children}
),
});
- await waitForNextUpdate();
-
- expect(addError).toBeCalled();
+ await waitFor(() => 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..dee68dff03371 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
@@ -5,8 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import { useToasts } from '../common/lib/kibana';
import type { AppMockRenderer } from '../common/mock';
import { createAppMockRenderer } from '../common/mock';
@@ -32,12 +31,10 @@ 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(() => {
expect(spy).toHaveBeenCalledWith({
query: {
@@ -67,12 +64,10 @@ 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(() => {
expect(spy).toHaveBeenCalledWith({
query: {
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..315757f065d88 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
@@ -6,7 +6,7 @@
*/
import React from 'react';
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import * as api from './api';
import { TestProviders } from '../common/mock';
import { SECURITY_SOLUTION_OWNER } from '../../common/constants';
@@ -24,16 +24,17 @@ describe('useGetTags', () => {
it('calls getTags api', async () => {
const spyOnGetTags = jest.spyOn(api, 'getTags');
- const { waitForNextUpdate } = renderHook(() => useGetTags(), {
+ renderHook(() => useGetTags(), {
wrapper: ({ children }: React.PropsWithChildren<{}>) => (
{children}
),
});
- await waitForNextUpdate();
- expect(spyOnGetTags).toBeCalledWith({
- owner: [SECURITY_SOLUTION_OWNER],
- signal: abortCtrl.signal,
- });
+ await waitFor(() =>
+ expect(spyOnGetTags).toBeCalledWith({
+ owner: [SECURITY_SOLUTION_OWNER],
+ signal: abortCtrl.signal,
+ })
+ );
});
it('displays and error toast when an error occurs', async () => {
@@ -43,12 +44,11 @@ describe('useGetTags', () => {
spyOnGetTags.mockImplementation(() => {
throw new Error('Something went wrong');
});
- const { waitForNextUpdate } = renderHook(() => useGetTags(), {
+ renderHook(() => useGetTags(), {
wrapper: ({ children }: React.PropsWithChildren<{}>) => (
{children}
),
});
- await waitForNextUpdate();
- 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 b3df805033ba8..19a7f2b9edc3f 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,7 @@
* 2.0.
*/
-import { act, renderHook } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useInfiniteFindCaseUserActions } from './use_infinite_find_case_user_actions';
import type { CaseUserActionTypeWithAll } from '../../common/ui/types';
@@ -42,12 +42,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(() => expect(result.current.isLoading).toBe(false));
expect(result.current).toEqual(
expect.objectContaining({
@@ -73,7 +73,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,12 +87,12 @@ describe('UseInfiniteFindCaseUserActions', () => {
{ wrapper: appMockRender.AppWrapper }
);
- await waitForNextUpdate();
-
- 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)
+ )
);
});
@@ -122,33 +122,31 @@ 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(() => {
+ 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();
});
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 }
);
- await waitFor(() => result.current.isSuccess);
+ await waitFor(() => expect(result.current.isSuccess).toBe(true));
expect(result.current.data?.pages).toStrictEqual([findCaseUserActionsResponse]);
@@ -165,7 +163,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/cases/public/containers/use_messages_storage.test.tsx b/x-pack/plugins/cases/public/containers/use_messages_storage.test.tsx
index ef4a164e759ba..30254f02412f8 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,8 +5,7 @@
* 2.0.
*/
-import { renderHook, act } from '@testing-library/react-hooks';
-import type { UseMessagesStorage } from './use_messages_storage';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useMessagesStorage } from './use_messages_storage';
describe('useMessagesStorage', () => {
@@ -18,35 +17,29 @@ describe('useMessagesStorage', () => {
});
it('should return an empty array when there is no messages', async () => {
+ const { result } = renderHook(() => useMessagesStorage());
+ await waitFor(() => new Promise((resolve) => resolve(null)));
+ const { getMessages } = result.current;
await act(async () => {
- const { result, waitForNextUpdate } = renderHook(() =>
- useMessagesStorage()
- );
- await waitForNextUpdate();
- const { getMessages } = result.current;
expect(getMessages('case')).toEqual([]);
});
});
it('should add a message', async () => {
+ const { result } = renderHook(() => useMessagesStorage());
+ await waitFor(() => new Promise((resolve) => resolve(null)));
+ const { getMessages, addMessage } = result.current;
await act(async () => {
- const { result, waitForNextUpdate } = renderHook(() =>
- useMessagesStorage()
- );
- await waitForNextUpdate();
- 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(() => new Promise((resolve) => resolve(null)));
+ const { getMessages, addMessage } = result.current;
await act(async () => {
- const { result, waitForNextUpdate } = renderHook(() =>
- useMessagesStorage()
- );
- await waitForNextUpdate();
- const { getMessages, addMessage } = result.current;
addMessage('case', 'id-1');
addMessage('case', 'id-2');
expect(getMessages('case')).toEqual(['id-1', 'id-2']);
@@ -54,12 +47,10 @@ describe('useMessagesStorage', () => {
});
it('should remove a message', async () => {
+ const { result } = renderHook(() => useMessagesStorage());
+ await waitFor(() => new Promise((resolve) => resolve(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 +59,10 @@ describe('useMessagesStorage', () => {
});
it('should return presence of a message', async () => {
+ const { result } = renderHook(() => useMessagesStorage());
+ await waitFor(() => new Promise((resolve) => resolve(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,16 +72,14 @@ describe('useMessagesStorage', () => {
});
it('should clear all messages', async () => {
+ const { result } = renderHook(() => useMessagesStorage());
+ await waitFor(() => new Promise((resolve) => resolve(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');
- expect(getMessages('case')).toEqual([]);
});
+ expect(getMessages('case')).toEqual([]);
});
});
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..d2c4cb65435c1 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,7 @@
* 2.0.
*/
-import { renderHook, act } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import * as api from './api';
import { ConnectorTypes } from '../../common/types/domain';
import { SECURITY_SOLUTION_OWNER } from '../../common/constants';
@@ -49,7 +49,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 +57,12 @@ describe('usePostCase', () => {
result.current.mutate({ request: samplePost });
});
- await waitForNextUpdate();
-
- expect(spy).toHaveBeenCalledWith({ newCase: samplePost });
+ await waitFor(() => 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,15 +70,15 @@ describe('usePostCase', () => {
result.current.mutate({ request: samplePost });
});
- await waitForNextUpdate();
-
- expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.casesList());
- expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
- expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.userProfiles());
+ await waitFor(() => {
+ expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.casesList());
+ expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
+ expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.userProfiles());
+ });
});
it('does not show a success toaster', async () => {
- const { waitForNextUpdate, result } = renderHook(() => usePostCase(), {
+ const { result } = renderHook(() => usePostCase(), {
wrapper: appMockRender.AppWrapper,
});
@@ -88,15 +86,13 @@ describe('usePostCase', () => {
result.current.mutate({ request: samplePost });
});
- await waitForNextUpdate();
-
- expect(addSuccess).not.toHaveBeenCalled();
+ await waitFor(() => expect(addSuccess).not.toHaveBeenCalled());
});
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,8 +100,6 @@ describe('usePostCase', () => {
result.current.mutate({ request: samplePost });
});
- await waitForNextUpdate();
-
- expect(addError).toHaveBeenCalled();
+ await waitFor(() => 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..0c7a76bc6ff3a 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,7 @@
* 2.0.
*/
-import { renderHook, act } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useToasts } from '../common/lib/kibana';
import { usePostPushToService } from './use_post_push_to_service';
import { pushedCase } from './mock';
@@ -42,7 +42,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,15 +50,15 @@ describe('usePostPushToService', () => {
result.current.mutate({ caseId, connector });
});
- await waitForNextUpdate();
-
- expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.caseView());
- expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
+ await waitFor(() => {
+ expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.caseView());
+ expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
+ });
});
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 +66,11 @@ describe('usePostPushToService', () => {
result.current.mutate({ caseId, connector });
});
- await waitForNextUpdate();
-
- expect(spy).toHaveBeenCalledWith({ caseId, connectorId: connector.id });
+ await waitFor(() => 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,18 +78,18 @@ describe('usePostPushToService', () => {
result.current.mutate({ caseId, connector });
});
- await waitForNextUpdate();
-
- expect(addSuccess).toHaveBeenCalledWith({
- title: 'Successfully sent to My connector',
- className: 'eui-textBreakWord',
- });
+ await waitFor(() =>
+ expect(addSuccess).toHaveBeenCalledWith({
+ title: 'Successfully sent to My connector',
+ className: 'eui-textBreakWord',
+ })
+ );
});
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,8 +97,6 @@ describe('usePostPushToService', () => {
result.current.mutate({ caseId, connector });
});
- await waitForNextUpdate();
-
- expect(addError).toHaveBeenCalled();
+ await waitFor(() => 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..4b17c874339d0 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,7 @@
* 2.0.
*/
-import { renderHook, act } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { basicCase } from './mock';
import * as api from './api';
import type { AppMockRenderer } from '../common/mock';
@@ -39,7 +39,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,15 +47,15 @@ describe('useReplaceCustomField', () => {
result.current.mutate(sampleData);
});
- await waitForNextUpdate();
-
- expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.caseView());
- expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
+ await waitFor(() => {
+ expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.caseView());
+ expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
+ });
});
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,16 +63,16 @@ describe('useReplaceCustomField', () => {
result.current.mutate(sampleData);
});
- await waitForNextUpdate();
-
- expect(patchCustomFieldSpy).toHaveBeenCalledWith({
- caseId: sampleData.caseId,
- customFieldId: sampleData.customFieldId,
- request: {
- value: sampleData.customFieldValue,
- caseVersion: sampleData.caseVersion,
- },
- });
+ await waitFor(() =>
+ expect(patchCustomFieldSpy).toHaveBeenCalledWith({
+ caseId: sampleData.caseId,
+ customFieldId: sampleData.customFieldId,
+ request: {
+ value: sampleData.customFieldValue,
+ caseVersion: sampleData.caseVersion,
+ },
+ })
+ );
});
it('calls the api when invoked with the correct parameters of toggle field', async () => {
@@ -83,7 +83,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,16 +91,16 @@ describe('useReplaceCustomField', () => {
result.current.mutate(newData);
});
- await waitForNextUpdate();
-
- expect(patchCustomFieldSpy).toHaveBeenCalledWith({
- caseId: newData.caseId,
- customFieldId: newData.customFieldId,
- request: {
- value: newData.customFieldValue,
- caseVersion: newData.caseVersion,
- },
- });
+ await waitFor(() =>
+ expect(patchCustomFieldSpy).toHaveBeenCalledWith({
+ caseId: newData.caseId,
+ customFieldId: newData.customFieldId,
+ request: {
+ value: newData.customFieldValue,
+ caseVersion: newData.caseVersion,
+ },
+ })
+ );
});
it('calls the api when invoked with the correct parameters with null value', async () => {
@@ -111,7 +111,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,16 +119,16 @@ describe('useReplaceCustomField', () => {
result.current.mutate(newData);
});
- await waitForNextUpdate();
-
- expect(patchCustomFieldSpy).toHaveBeenCalledWith({
- caseId: newData.caseId,
- customFieldId: newData.customFieldId,
- request: {
- value: newData.customFieldValue,
- caseVersion: newData.caseVersion,
- },
- });
+ await waitFor(() =>
+ expect(patchCustomFieldSpy).toHaveBeenCalledWith({
+ caseId: newData.caseId,
+ customFieldId: newData.customFieldId,
+ request: {
+ value: newData.customFieldValue,
+ caseVersion: newData.caseVersion,
+ },
+ })
+ );
});
it('shows a toast error when the api return an error', async () => {
@@ -136,7 +136,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,8 +144,6 @@ describe('useReplaceCustomField', () => {
result.current.mutate(sampleData);
});
- await waitForNextUpdate();
-
- expect(addError).toHaveBeenCalled();
+ await waitFor(() => 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..4b14544460792 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,7 @@
* 2.0.
*/
-import { renderHook, act } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useUpdateCase } from './use_update_case';
import { basicCase } from './mock';
import * as api from './api';
@@ -41,7 +41,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,15 +49,15 @@ describe('useUpdateCase', () => {
result.current.mutate(sampleUpdate);
});
- await waitForNextUpdate();
-
- expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.caseView());
- expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
+ await waitFor(() => {
+ expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.caseView());
+ expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
+ });
});
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,17 +65,17 @@ describe('useUpdateCase', () => {
result.current.mutate(sampleUpdate);
});
- await waitForNextUpdate();
-
- expect(patchCaseSpy).toHaveBeenCalledWith({
- caseId: basicCase.id,
- updatedCase: { description: 'updated description' },
- version: basicCase.version,
- });
+ await waitFor(() =>
+ expect(patchCaseSpy).toHaveBeenCalledWith({
+ caseId: basicCase.id,
+ updatedCase: { description: 'updated description' },
+ version: basicCase.version,
+ })
+ );
});
it('shows a success toaster', async () => {
- const { waitForNextUpdate, result } = renderHook(() => useUpdateCase(), {
+ const { result } = renderHook(() => useUpdateCase(), {
wrapper: appMockRender.AppWrapper,
});
@@ -83,18 +83,18 @@ describe('useUpdateCase', () => {
result.current.mutate(sampleUpdate);
});
- await waitForNextUpdate();
-
- expect(addSuccess).toHaveBeenCalledWith({
- title: 'Updated "Another horrible breach!!"',
- className: 'eui-textBreakWord',
- });
+ await waitFor(() =>
+ expect(addSuccess).toHaveBeenCalledWith({
+ title: 'Updated "Another horrible breach!!"',
+ className: 'eui-textBreakWord',
+ })
+ );
});
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,8 +102,6 @@ describe('useUpdateCase', () => {
result.current.mutate(sampleUpdate);
});
- await waitForNextUpdate();
-
- expect(addError).toHaveBeenCalled();
+ await waitFor(() => 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..7a2522d6ac8c2 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,7 @@
* 2.0.
*/
-import { renderHook, act } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { basicCase } from './mock';
import * as api from './api';
import type { AppMockRenderer } from '../common/mock';
@@ -39,7 +39,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,15 +47,15 @@ describe('useUpdateComment', () => {
result.current.mutate(sampleUpdate);
});
- await waitForNextUpdate();
-
- expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.caseView());
- expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
+ await waitFor(() => {
+ expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.caseView());
+ expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
+ });
});
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,18 +63,18 @@ describe('useUpdateComment', () => {
result.current.mutate(sampleUpdate);
});
- await waitForNextUpdate();
-
- expect(patchCommentSpy).toHaveBeenCalledWith({
- ...sampleUpdate,
- owner: 'securitySolution',
- });
+ await waitFor(() =>
+ expect(patchCommentSpy).toHaveBeenCalledWith({
+ ...sampleUpdate,
+ owner: 'securitySolution',
+ })
+ );
});
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,8 +82,6 @@ describe('useUpdateComment', () => {
result.current.mutate(sampleUpdate);
});
- await waitForNextUpdate();
-
- expect(addError).toHaveBeenCalled();
+ await waitFor(() => expect(addError).toHaveBeenCalled());
});
});
diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.test.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.test.ts
index 3622b66aef006..f808d8d7dd934 100644
--- a/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.test.ts
+++ b/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.test.ts
@@ -6,7 +6,7 @@
*/
import type { UserProfileWithAvatar } from '@kbn/user-profile-components';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import { userProfiles, userProfilesMap } from './api.mock';
import { useAssignees } from './use_assignees';
diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.test.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.test.ts
index 4edc105b8d349..4558c7cdd2d36 100644
--- a/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.test.ts
+++ b/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.test.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook, waitFor } from '@testing-library/react';
import { useToasts, useKibana } from '../../common/lib/kibana';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
@@ -41,26 +41,25 @@ describe.skip('useBulkGetUserProfiles', () => {
it('calls bulkGetUserProfiles with correct arguments', async () => {
const spyOnBulkGetUserProfiles = jest.spyOn(api, 'bulkGetUserProfiles');
- const { result, waitFor } = renderHook(() => useBulkGetUserProfiles(props), {
+ renderHook(() => useBulkGetUserProfiles(props), {
wrapper: appMockRender.AppWrapper,
});
- await waitFor(() => result.current.isSuccess);
-
- expect(spyOnBulkGetUserProfiles).toBeCalledWith({
- ...props,
- security: expect.anything(),
- });
+ await waitFor(() =>
+ expect(spyOnBulkGetUserProfiles).toBeCalledWith({
+ ...props,
+ security: expect.anything(),
+ })
+ );
});
it('returns a mapping with user profiles', async () => {
- const { result, waitFor } = renderHook(() => useBulkGetUserProfiles(props), {
+ const { result } = renderHook(() => useBulkGetUserProfiles(props), {
wrapper: appMockRender.AppWrapper,
});
- await waitFor(() => result.current.isSuccess);
-
- expect(result.current.data).toMatchInlineSnapshot(`
+ await waitFor(() =>
+ expect(result.current.data).toMatchInlineSnapshot(`
Map {
"u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0" => Object {
"data": Object {},
@@ -93,7 +92,8 @@ describe.skip('useBulkGetUserProfiles', () => {
},
},
}
- `);
+ `)
+ );
});
it('shows a toast error message when an error occurs in the response', async () => {
@@ -106,13 +106,11 @@ describe.skip('useBulkGetUserProfiles', () => {
const addError = jest.fn();
(useToasts as jest.Mock).mockReturnValue({ addSuccess, addError });
- const { result, waitFor } = renderHook(() => useBulkGetUserProfiles(props), {
+ renderHook(() => useBulkGetUserProfiles(props), {
wrapper: appMockRender.AppWrapper,
});
- await waitFor(() => result.current.isError);
-
- expect(addError).toHaveBeenCalled();
+ await waitFor(() => expect(addError).toHaveBeenCalled());
});
it('does not call the bulkGetUserProfiles if the array of uids is empty', async () => {
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..918771d5b2187 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } 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 +36,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 +59,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 +78,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/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..67907d6494645 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
@@ -6,7 +6,7 @@
*/
import { GENERAL_CASES_OWNER } from '../../../common/constants';
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useToasts } from '../../common/lib/kibana';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
@@ -34,17 +34,18 @@ 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,
});
- 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(),
+ });
});
});
@@ -58,12 +59,13 @@ 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,
});
- await waitFor(() => result.current.isError);
-
- expect(addError).toHaveBeenCalled();
+ await waitFor(() => {
+ expect(result.current.isError).toBeDefined();
+ expect(addError).toHaveBeenCalled();
+ });
});
});
diff --git a/x-pack/plugins/stack_alerts/public/rule_types/es_query/test_query_row/use_test_query.test.ts b/x-pack/plugins/stack_alerts/public/rule_types/es_query/test_query_row/use_test_query.test.ts
index f476d7d896b69..b22c1a81537c1 100644
--- a/x-pack/plugins/stack_alerts/public/rule_types/es_query/test_query_row/use_test_query.test.ts
+++ b/x-pack/plugins/stack_alerts/public/rule_types/es_query/test_query_row/use_test_query.test.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import { act } from 'react-test-renderer';
import { useTestQuery } from './use_test_query';
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..0830b68fc1d56 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,7 @@
*/
import { httpServiceMock, notificationServiceMock } from '@kbn/core/public/mocks';
-import { renderHook, act } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useEmailConfig } from './use_email_config';
const http = httpServiceMock.createStartContract();
@@ -16,6 +16,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 () => {
@@ -26,14 +32,16 @@ describe('useEmailConfig', () => {
});
const { result } = renderUseEmailConfigHook();
+
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 +52,16 @@ describe('useEmailConfig', () => {
});
const { result } = renderUseEmailConfigHook();
+
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,
});
});
@@ -60,13 +70,14 @@ describe('useEmailConfig', () => {
const { result } = renderUseEmailConfigHook();
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 +86,13 @@ 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(() => 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..39706e6d22c05 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useGetDashboard } from './use_get_dashboard';
import { getDashboard } from './api';
import { useKibana } from '@kbn/triggers-actions-ui-plugin/public';
@@ -58,44 +58,44 @@ 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();
- expect(mockDashboard).toHaveBeenCalledWith(
- expect.objectContaining({
- connectorId,
+ const { result } = renderHook(() => useGetDashboard({ ...defaultArgs, selectedProvider }));
+ await waitFor(() => {
+ expect(mockDashboard).toHaveBeenCalledWith(
+ expect.objectContaining({
+ connectorId,
+ dashboardId: `generative-ai-token-usage-${urlKey}-space`,
+ })
+ );
+ expect(mockGetRedirectUrl).toHaveBeenCalledWith({
+ query: {
+ language: 'kuery',
+ query: `kibana.saved_objects: { id : ${connectorId} }`,
+ },
dashboardId: `generative-ai-token-usage-${urlKey}-space`,
- })
- );
- expect(mockGetRedirectUrl).toHaveBeenCalledWith({
- query: {
- language: 'kuery',
- query: `kibana.saved_objects: { id : ${connectorId} }`,
- },
- dashboardId: `generative-ai-token-usage-${urlKey}-space`,
+ });
+ expect(result.current.isLoading).toBe(false);
+ expect(result.current.dashboardUrl).toBe(
+ `http://localhost:5601/app/dashboards#/view/generative-ai-token-usage-${urlKey}-space`
+ );
});
- expect(result.current.isLoading).toBe(false);
- expect(result.current.dashboardUrl).toBe(
- `http://localhost:5601/app/dashboards#/view/generative-ai-token-usage-${urlKey}-space`
- );
}
);
it('handles the case where the dashboard is not available.', async () => {
mockDashboard.mockResolvedValue({ data: { available: false } });
- const { result, waitForNextUpdate } = renderHook(() => useGetDashboard(defaultArgs));
- await waitForNextUpdate();
- expect(mockDashboard).toHaveBeenCalledWith(
- expect.objectContaining({
- connectorId,
- dashboardId: 'generative-ai-token-usage-openai-space',
- })
- );
- expect(mockGetRedirectUrl).not.toHaveBeenCalled();
+ const { result } = renderHook(() => useGetDashboard(defaultArgs));
+ await waitFor(() => {
+ expect(mockDashboard).toHaveBeenCalledWith(
+ expect.objectContaining({
+ connectorId,
+ dashboardId: 'generative-ai-token-usage-openai-space',
+ })
+ );
+ expect(mockGetRedirectUrl).not.toHaveBeenCalled();
- expect(result.current.isLoading).toBe(false);
- expect(result.current.dashboardUrl).toBe(null);
+ expect(result.current.isLoading).toBe(false);
+ expect(result.current.dashboardUrl).toBe(null);
+ });
});
it('handles the case where the spaces API is not available.', async () => {
@@ -111,34 +111,35 @@ describe('useGetDashboard', () => {
});
it('handles the case where connectorId is empty string', async () => {
- const { result, waitForNextUpdate } = renderHook(() =>
- useGetDashboard({ ...defaultArgs, connectorId: '' })
- );
- await waitForNextUpdate();
- expect(mockDashboard).not.toHaveBeenCalled();
- expect(mockGetRedirectUrl).not.toHaveBeenCalled();
- expect(result.current.isLoading).toBe(false);
- expect(result.current.dashboardUrl).toBe(null);
+ const { result } = renderHook(() => useGetDashboard({ ...defaultArgs, connectorId: '' }));
+ await waitFor(() => {
+ expect(mockDashboard).not.toHaveBeenCalled();
+ expect(mockGetRedirectUrl).not.toHaveBeenCalled();
+ expect(result.current.isLoading).toBe(false);
+ expect(result.current.dashboardUrl).toBe(null);
+ });
});
it('handles the case where the dashboard locator is not available.', async () => {
mockKibana.mockReturnValue({
services: { ...mockServices, dashboard: {} },
});
- const { result, waitForNextUpdate } = renderHook(() => useGetDashboard(defaultArgs));
- await waitForNextUpdate();
- expect(result.current.isLoading).toBe(false);
- expect(result.current.dashboardUrl).toBe(null);
+ const { result } = renderHook(() => useGetDashboard(defaultArgs));
+ await waitFor(() => {
+ 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();
- expect(result.current.isLoading).toBe(false);
- expect(mockToasts.addDanger).toHaveBeenCalledWith({
- title: 'Error finding OpenAI Token Usage Dashboard.',
- text: 'Error fetching dashboard',
+ const { result } = renderHook(() => useGetDashboard(defaultArgs));
+ await waitFor(() => {
+ expect(result.current.isLoading).toBe(false);
+ expect(mockToasts.addDanger).toHaveBeenCalledWith({
+ title: 'Error finding OpenAI Token Usage Dashboard.',
+ text: 'Error fetching 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..3033cebd3ccf6 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
@@ -5,11 +5,11 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useKibana } from '@kbn/triggers-actions-ui-plugin/public';
import { ActionConnector } from '@kbn/triggers-actions-ui-plugin/public/types';
-import { useChoices, UseChoices, UseChoicesProps } from './use_choices';
+import { useChoices } from './use_choices';
import { getChoices } from './api';
jest.mock('./api');
@@ -73,7 +73,7 @@ describe('UseChoices', () => {
const fields = ['category'];
it('init', async () => {
- const { result, waitForNextUpdate } = renderHook(() =>
+ const { result } = renderHook(() =>
useChoices({
http: services.http,
actionConnector,
@@ -82,13 +82,11 @@ describe('UseChoices', () => {
})
);
- await waitForNextUpdate();
-
- expect(result.current).toEqual(useChoicesResponse);
+ await waitFor(() => 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,16 +95,16 @@ describe('UseChoices', () => {
})
);
- await waitForNextUpdate();
-
- expect(result.current).toEqual({
- isLoading: false,
- choices: { priority: [], category: getChoicesResponse },
- });
+ await waitFor(() =>
+ expect(result.current).toEqual({
+ isLoading: false,
+ choices: { priority: [], category: getChoicesResponse },
+ })
+ );
});
it('returns an empty array when connector is not presented', async () => {
- const { result } = renderHook(() =>
+ const { result } = renderHook(() =>
useChoices({
http: services.http,
actionConnector: undefined,
@@ -127,7 +125,7 @@ describe('UseChoices', () => {
serviceMessage: 'An error occurred',
});
- const { waitForNextUpdate } = renderHook(() =>
+ renderHook(() =>
useChoices({
http: services.http,
actionConnector,
@@ -136,12 +134,12 @@ describe('UseChoices', () => {
})
);
- await waitForNextUpdate();
-
- expect(services.notifications.toasts.addDanger).toHaveBeenCalledWith({
- text: 'An error occurred',
- title: 'Unable to get choices',
- });
+ await waitFor(() =>
+ expect(services.notifications.toasts.addDanger).toHaveBeenCalledWith({
+ text: 'An error occurred',
+ title: 'Unable to get choices',
+ })
+ );
});
it('it displays an error when http throws an error', async () => {
@@ -149,7 +147,7 @@ describe('UseChoices', () => {
throw new Error('An error occurred');
});
- renderHook(() =>
+ renderHook(() =>
useChoices({
http: services.http,
actionConnector,
@@ -158,9 +156,11 @@ describe('UseChoices', () => {
})
);
- expect(services.notifications.toasts.addDanger).toHaveBeenCalledWith({
- text: 'An error occurred',
- title: 'Unable to get choices',
- });
+ await waitFor(() =>
+ expect(services.notifications.toasts.addDanger).toHaveBeenCalledWith({
+ text: 'An error occurred',
+ title: 'Unable to get choices',
+ })
+ );
});
});
diff --git a/x-pack/plugins/stack_connectors/public/connector_types/lib/servicenow/use_get_app_info.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/lib/servicenow/use_get_app_info.test.tsx
index c8c061c9d07f1..c4cf65a591338 100644
--- a/x-pack/plugins/stack_connectors/public/connector_types/lib/servicenow/use_get_app_info.test.tsx
+++ b/x-pack/plugins/stack_connectors/public/connector_types/lib/servicenow/use_get_app_info.test.tsx
@@ -5,9 +5,9 @@
* 2.0.
*/
-import { renderHook, act } from '@testing-library/react-hooks';
+import { renderHook, act } from '@testing-library/react';
-import { useGetAppInfo, UseGetAppInfo, UseGetAppInfoProps } from './use_get_app_info';
+import { useGetAppInfo } from './use_get_app_info';
import { getAppInfo } from './api';
import { ServiceNowActionConnector } from './types';
import { httpServiceMock } from '@kbn/core/public/mocks';
@@ -50,7 +50,7 @@ describe('useGetAppInfo', () => {
});
it('init', async () => {
- const { result } = renderHook(() =>
+ const { result } = renderHook(() =>
useGetAppInfo({
actionTypeId,
http,
@@ -64,7 +64,7 @@ describe('useGetAppInfo', () => {
});
it('returns the application information', async () => {
- const { result } = renderHook(() =>
+ const { result } = renderHook(() =>
useGetAppInfo({
actionTypeId,
http,
@@ -86,7 +86,7 @@ describe('useGetAppInfo', () => {
throw new Error('An error occurred');
});
- const { result } = renderHook(() =>
+ const { result } = renderHook(() =>
useGetAppInfo({
actionTypeId,
http,
@@ -108,7 +108,7 @@ describe('useGetAppInfo', () => {
throw error;
});
- const { result } = renderHook(() =>
+ const { result } = renderHook(() =>
useGetAppInfo({
actionTypeId,
http,
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..fd9808139b8ba 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
@@ -5,11 +5,11 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { useKibana } from '@kbn/triggers-actions-ui-plugin/public';
import { ActionConnector } from '@kbn/triggers-actions-ui-plugin/public/types';
-import { useGetChoices, UseGetChoices, UseGetChoicesProps } from './use_get_choices';
+import { useGetChoices } from './use_get_choices';
import { getChoices } from './api';
jest.mock('./api');
@@ -69,7 +69,7 @@ describe('useGetChoices', () => {
const fields = ['priority'];
it('init', async () => {
- const { result, waitForNextUpdate } = renderHook(() =>
+ const { result } = renderHook(() =>
useGetChoices({
http: services.http,
actionConnector,
@@ -79,16 +79,16 @@ describe('useGetChoices', () => {
})
);
- await waitForNextUpdate();
-
- expect(result.current).toEqual({
- isLoading: false,
- choices: getChoicesResponse,
- });
+ await waitFor(() =>
+ expect(result.current).toEqual({
+ isLoading: false,
+ choices: getChoicesResponse,
+ })
+ );
});
it('returns an empty array when connector is not presented', async () => {
- const { result } = renderHook(() =>
+ const { result } = renderHook(() =>
useGetChoices({
http: services.http,
actionConnector: undefined,
@@ -105,7 +105,7 @@ describe('useGetChoices', () => {
});
it('it calls onSuccess', async () => {
- const { waitForNextUpdate } = renderHook(() =>
+ renderHook(() =>
useGetChoices({
http: services.http,
actionConnector,
@@ -115,9 +115,7 @@ describe('useGetChoices', () => {
})
);
- await waitForNextUpdate();
-
- expect(onSuccess).toHaveBeenCalledWith(getChoicesResponse);
+ await waitFor(() => expect(onSuccess).toHaveBeenCalledWith(getChoicesResponse));
});
it('it displays an error when service fails', async () => {
@@ -126,7 +124,7 @@ describe('useGetChoices', () => {
serviceMessage: 'An error occurred',
});
- const { waitForNextUpdate } = renderHook(() =>
+ renderHook(() =>
useGetChoices({
http: services.http,
actionConnector,
@@ -136,12 +134,12 @@ describe('useGetChoices', () => {
})
);
- await waitForNextUpdate();
-
- expect(services.notifications.toasts.addDanger).toHaveBeenCalledWith({
- text: 'An error occurred',
- title: 'Unable to get choices',
- });
+ await waitFor(() =>
+ expect(services.notifications.toasts.addDanger).toHaveBeenCalledWith({
+ text: 'An error occurred',
+ title: 'Unable to get choices',
+ })
+ );
});
it('it displays an error when http throws an error', async () => {
@@ -149,7 +147,7 @@ describe('useGetChoices', () => {
throw new Error('An error occurred');
});
- renderHook(() =>
+ renderHook(() =>
useGetChoices({
http: services.http,
actionConnector,
@@ -159,10 +157,12 @@ describe('useGetChoices', () => {
})
);
- expect(services.notifications.toasts.addDanger).toHaveBeenCalledWith({
- text: 'An error occurred',
- title: 'Unable to get choices',
- });
+ await waitFor(() =>
+ expect(services.notifications.toasts.addDanger).toHaveBeenCalledWith({
+ text: 'An error occurred',
+ title: 'Unable to get choices',
+ })
+ );
});
it('returns an empty array if the response is not an array', async () => {
@@ -171,7 +171,7 @@ describe('useGetChoices', () => {
data: {},
});
- const { result } = renderHook(() =>
+ const { result } = renderHook(() =>
useGetChoices({
http: services.http,
actionConnector: undefined,
@@ -181,9 +181,11 @@ describe('useGetChoices', () => {
})
);
- expect(result.current).toEqual({
- isLoading: false,
- choices: [],
+ await waitFor(() => {
+ expect(result.current).toEqual({
+ isLoading: false,
+ choices: [],
+ });
});
});
});
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..db33c7aa68014 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,11 +5,11 @@
* 2.0.
*/
-import { renderHook, act } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useKibana } from '@kbn/triggers-actions-ui-plugin/public/common/lib/kibana';
import { getApplication } from './api';
-import { useGetApplication, UseGetApplication } from './use_get_application';
+import { useGetApplication } from './use_get_application';
jest.mock('./api');
jest.mock('@kbn/triggers-actions-ui-plugin/public/common/lib/kibana');
@@ -43,87 +43,86 @@ 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(() => new Promise((resolve) => resolve(null)));
+ act(() => {
result.current.getApplication({
appId: action.config.appId,
apiToken: action.secrets.apiToken,
apiUrl: action.config.apiUrl,
});
+ });
- await waitForNextUpdate();
+ await waitFor(() =>
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(() => new Promise((resolve) => resolve(null)));
+ act(() => {
result.current.getApplication({
appId: action.config.appId,
apiToken: action.secrets.apiToken,
apiUrl: action.config.apiUrl,
});
- await waitForNextUpdate();
-
+ });
+ await waitFor(() =>
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(() => new Promise((resolve) => resolve(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(() => new Promise((resolve) => resolve(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(() => new Promise((resolve) => resolve(null)));
+ act(() => {
result.current.getApplication({
appId: action.config.appId,
apiToken: action.secrets.apiToken,
apiUrl: action.config.apiUrl,
});
- await waitForNextUpdate();
-
+ });
+ await waitFor(() =>
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/triggers_actions_ui/public/application/hooks/use_bulk_edit_select.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_bulk_edit_select.test.tsx
index 1a5e3f278eb5e..8452345543145 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_bulk_edit_select.test.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_bulk_edit_select.test.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook, act } from '@testing-library/react-hooks';
+import { renderHook, act } from '@testing-library/react';
import { useBulkEditSelect } from './use_bulk_edit_select';
import { RuleTableItem } from '../../types';
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..f33092c3dea9e 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,7 @@
* 2.0.
*/
-import { act, renderHook } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useKibana } from '../../common/lib/kibana';
import { useCreateConnector } from './use_create_connector';
@@ -29,7 +29,7 @@ describe('useCreateConnector', () => {
});
it('executes correctly', async () => {
- const { result, waitForNextUpdate } = renderHook(() => useCreateConnector());
+ const { result } = renderHook(() => useCreateConnector());
act(() => {
result.current.createConnector({
@@ -40,10 +40,10 @@ describe('useCreateConnector', () => {
});
});
- await waitForNextUpdate();
-
- expect(useKibanaMock().services.http.post).toHaveBeenCalledWith('/api/actions/connector', {
- body: '{"name":"test","config":{},"secrets":{},"connector_type_id":".test"}',
- });
+ await waitFor(() =>
+ 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..a381296e6bc91 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,7 @@
* 2.0.
*/
-import { act, renderHook } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useKibana } from '../../common/lib/kibana';
import { useExecuteConnector } from './use_execute_connector';
@@ -29,17 +29,17 @@ 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();
-
- expect(useKibanaMock().services.http.post).toHaveBeenCalledWith(
- '/api/actions/connector/test-id/_execute',
- { body: '{"params":{}}' }
+ await waitFor(() =>
+ expect(useKibanaMock().services.http.post).toHaveBeenCalledWith(
+ '/api/actions/connector/test-id/_execute',
+ { body: '{"params":{}}' }
+ )
);
});
});
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_get_query_delay_setting.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_get_query_delay_setting.test.tsx
index 4b65e355b9c86..231b9b9be49d4 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_get_query_delay_setting.test.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_get_query_delay_setting.test.tsx
@@ -5,8 +5,7 @@
* 2.0.
*/
import React from 'react';
-import { renderHook } from '@testing-library/react-hooks/dom';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { useGetQueryDelaySettings } from './use_get_query_delay_settings';
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_license.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_license.test.ts
index 1b2fc7784f4e3..ec203e4bdacf8 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_license.test.ts
+++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_license.test.ts
@@ -6,7 +6,7 @@
*/
import { BehaviorSubject } from 'rxjs';
import { licensingMock } from '@kbn/licensing-plugin/public/mocks';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import { useLicense } from './use_license';
import { useKibana } from '../../common/lib/kibana';
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..92c1e3bc5ca69 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
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor, renderHook } from '@testing-library/react';
import { ValidFeatureId } from '@kbn/rule-data-utils';
import { useKibana } from '../../common/lib/kibana';
import {
@@ -34,7 +34,7 @@ describe('useLoadAlertSummary', () => {
...mockedAlertSummaryResponse,
});
- const { result, waitForNextUpdate } = renderHook(() =>
+ const { result } = renderHook(() =>
useLoadAlertSummary({
featureIds,
timeRange: mockedAlertSummaryTimeRange,
@@ -49,7 +49,7 @@ describe('useLoadAlertSummary', () => {
},
});
- await waitForNextUpdate();
+ await waitFor(() => new Promise((resolve) => resolve(null)));
const { alertSummary, error } = result.current;
expect(alertSummary).toEqual({
@@ -70,7 +70,7 @@ describe('useLoadAlertSummary', () => {
...mockedAlertSummaryResponse,
});
- const { waitForNextUpdate } = renderHook(() =>
+ renderHook(() =>
useLoadAlertSummary({
featureIds,
timeRange: mockedAlertSummaryTimeRange,
@@ -78,8 +78,6 @@ describe('useLoadAlertSummary', () => {
})
);
- await waitForNextUpdate();
-
const body = JSON.stringify({
fixed_interval: fixedInterval,
gte: utcFrom,
@@ -87,11 +85,14 @@ describe('useLoadAlertSummary', () => {
featureIds,
filter: [filter],
});
- expect(mockedPostAPI).toHaveBeenCalledWith(
- '/internal/rac/alerts/_alert_summary',
- expect.objectContaining({
- body,
- })
+
+ await waitFor(() =>
+ expect(mockedPostAPI).toHaveBeenCalledWith(
+ '/internal/rac/alerts/_alert_summary',
+ expect.objectContaining({
+ body,
+ })
+ )
);
});
@@ -99,15 +100,13 @@ 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();
-
- expect(result.current.error).toMatch(error.message);
+ await waitFor(() => 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..e1cb5f6f4f5ee 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 { waitFor, renderHook } 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,20 +82,21 @@ describe('useLoadRuleAggregations', () => {
);
rerender();
- await waitForNextUpdate();
- expect(loadRuleAggregationsWithKueryFilter).toBeCalledWith(
- expect.objectContaining({
- searchText: '',
- typesFilter: [],
- actionTypesFilter: [],
- ruleExecutionStatusesFilter: [],
- ruleLastRunOutcomesFilter: [],
- ruleStatusesFilter: [],
- tagsFilter: [],
- })
- );
- expect(result.current.rulesStatusesTotal).toEqual(MOCK_AGGS.ruleExecutionStatus);
+ await waitFor(() => {
+ expect(loadRuleAggregationsWithKueryFilter).toBeCalledWith(
+ expect.objectContaining({
+ searchText: '',
+ typesFilter: [],
+ actionTypesFilter: [],
+ ruleExecutionStatusesFilter: [],
+ ruleLastRunOutcomesFilter: [],
+ ruleStatusesFilter: [],
+ tagsFilter: [],
+ })
+ );
+ expect(result.current.rulesStatusesTotal).toEqual(MOCK_AGGS.ruleExecutionStatus);
+ });
});
it('should call loadRuleAggregation API with params and handle result', async () => {
@@ -115,28 +115,26 @@ describe('useLoadRuleAggregations', () => {
refresh: undefined,
};
- const { rerender, result, waitForNextUpdate } = renderHook(
- () => useLoadRuleAggregations(params),
- {
- wrapper,
- }
- );
+ const { rerender, result } = renderHook(() => useLoadRuleAggregations(params), {
+ wrapper,
+ });
rerender();
- await waitForNextUpdate();
- 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);
+ 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);
+ });
});
it('should call onError if API fails', async () => {
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..3c87b04cb62e1 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 { waitFor, renderHook } 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,11 +290,10 @@ describe('useLoadRules', () => {
expect(result.current.rulesState.isLoading).toBeTruthy();
rerender();
- await waitForNextUpdate();
+ 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(
@@ -339,29 +337,29 @@ describe('useLoadRules', () => {
sort: { field: 'name', direction: 'asc' },
};
- const { waitForNextUpdate, rerender } = renderHook(() => useLoadRules(params), {
+ const { rerender } = renderHook(() => useLoadRules(params), {
wrapper,
});
rerender();
- await waitForNextUpdate();
-
- 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' },
+ })
+ )
);
});
@@ -391,7 +389,7 @@ describe('useLoadRules', () => {
sort: { field: 'name', direction: 'asc' },
};
- const { rerender, waitForNextUpdate } = renderHook(
+ const { rerender } = renderHook(
() => {
return useLoadRules(params);
},
@@ -399,12 +397,12 @@ describe('useLoadRules', () => {
);
rerender();
- await waitForNextUpdate();
-
- expect(onPage).toHaveBeenCalledWith({
- index: 0,
- size: 25,
- });
+ await waitFor(() =>
+ expect(onPage).toHaveBeenCalledWith({
+ index: 0,
+ size: 25,
+ })
+ );
});
it('should call onError if API fails', async () => {
@@ -459,16 +457,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();
-
- 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 () => {
@@ -494,16 +490,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();
-
- expect(result.current.hasData).toBeFalsy();
+ await waitFor(() => 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..3aa1bcbf07b2c 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 { waitFor, renderHook } 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,18 +66,18 @@ describe('useLoadTagsQuery', () => {
);
rerender();
- await waitForNextUpdate();
-
- 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 () => {
@@ -88,7 +87,7 @@ describe('useLoadTagsQuery', () => {
perPage: 5,
total: 10,
});
- const { rerender, result, waitForNextUpdate } = renderHook(
+ const { rerender, result } = renderHook(
() =>
useLoadTagsQuery({
enabled: true,
@@ -101,17 +100,17 @@ describe('useLoadTagsQuery', () => {
);
rerender();
- await waitForNextUpdate();
-
- 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'],
@@ -119,6 +118,7 @@ describe('useLoadTagsQuery', () => {
perPage: 5,
total: 10,
});
+
result.current.fetchNextPage();
expect(loadRuleTags).toHaveBeenLastCalledWith(
@@ -129,9 +129,7 @@ describe('useLoadTagsQuery', () => {
);
rerender();
- await waitForNextUpdate();
-
- expect(result.current.hasNextPage).toEqual(false);
+ await waitFor(() => expect(result.current.hasNextPage).toEqual(false));
});
it('should support pagination when there are no tags', async () => {
@@ -142,7 +140,7 @@ describe('useLoadTagsQuery', () => {
total: 0,
});
- const { rerender, result, waitForNextUpdate } = renderHook(
+ const { rerender, result } = renderHook(
() =>
useLoadTagsQuery({
enabled: true,
@@ -155,17 +153,17 @@ describe('useLoadTagsQuery', () => {
);
rerender();
- await waitForNextUpdate();
-
- 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 () => {
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..161f1564b1dd7 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,7 @@
* 2.0.
*/
-import { act, renderHook } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useKibana } from '../../common/lib/kibana';
import { useSubAction, UseSubActionParams } from './use_sub_action';
@@ -30,102 +30,96 @@ describe('useSubAction', () => {
});
it('init', async () => {
- const { result, waitForNextUpdate } = renderHook(() => useSubAction(params));
- await waitForNextUpdate();
-
- expect(result.current).toEqual({
- isLoading: false,
- response: {},
- error: null,
- });
+ const { result } = renderHook(() => useSubAction(params));
+ await waitFor(() =>
+ expect(result.current).toEqual({
+ isLoading: false,
+ response: {},
+ error: null,
+ })
+ );
});
it('executes the sub action correctly', async () => {
- const { waitForNextUpdate } = renderHook(() => useSubAction(params));
- await waitForNextUpdate();
-
- expect(mockHttpPost).toHaveBeenCalledWith('/api/actions/connector/test-id/_execute', {
- body: '{"params":{"subAction":"test","subActionParams":{"foo":"bar"}}}',
- signal: new AbortController().signal,
- });
+ renderHook(() => useSubAction(params));
+ await waitFor(() =>
+ expect(mockHttpPost).toHaveBeenCalledWith('/api/actions/connector/test-id/_execute', {
+ body: '{"params":{"subAction":"test","subActionParams":{"foo":"bar"}}}',
+ signal: new AbortController().signal,
+ })
+ );
});
it('executes sub action if subAction parameter changes', async () => {
- const { rerender, waitForNextUpdate } = renderHook(useSubAction, { initialProps: params });
- await waitForNextUpdate();
-
- expect(mockHttpPost).toHaveBeenCalledTimes(1);
+ const { rerender } = renderHook(useSubAction, { initialProps: params });
+ await waitFor(() => expect(mockHttpPost).toHaveBeenCalledTimes(1));
await act(async () => {
rerender({ ...params, subAction: 'test-2' });
- await waitForNextUpdate();
});
- expect(mockHttpPost).toHaveBeenCalledTimes(2);
+ await waitFor(() => expect(mockHttpPost).toHaveBeenCalledTimes(2));
});
it('executes sub action if connectorId parameter changes', async () => {
- const { rerender, waitForNextUpdate } = renderHook(useSubAction, { initialProps: params });
- await waitForNextUpdate();
-
- expect(mockHttpPost).toHaveBeenCalledTimes(1);
+ const { rerender } = renderHook(useSubAction, { initialProps: params });
+ await waitFor(() => expect(mockHttpPost).toHaveBeenCalledTimes(1));
await act(async () => {
rerender({ ...params, connectorId: 'test-id-2' });
- await waitForNextUpdate();
});
- expect(mockHttpPost).toHaveBeenCalledTimes(2);
+ await waitFor(() => 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(() => expect(mockHttpPost).toHaveBeenCalledTimes(1));
- expect(mockHttpPost).toHaveBeenCalledTimes(1);
const previous = result.current;
await act(async () => {
rerender({ ...params, subActionParams: { foo: 'bar' } });
- await waitForNextUpdate();
});
- expect(result.current.response).toBe(previous.response);
- expect(mockHttpPost).toHaveBeenCalledTimes(1);
+ await waitFor(() => {
+ expect(result.current.response).toBe(previous.response);
+ expect(mockHttpPost).toHaveBeenCalledTimes(1);
+ });
});
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(() => expect(mockHttpPost).toHaveBeenCalledTimes(1));
- expect(mockHttpPost).toHaveBeenCalledTimes(1);
const previous = result.current;
await act(async () => {
rerender({ ...params, subActionParams: { foo: 'baz' } });
- await waitForNextUpdate();
});
- expect(result.current.response).not.toBe(previous.response);
- expect(mockHttpPost).toHaveBeenCalledTimes(2);
+ await waitFor(() => {
+ expect(result.current.response).not.toBe(previous.response);
+ expect(mockHttpPost).toHaveBeenCalledTimes(2);
+ });
});
it('returns an error correctly', async () => {
const error = new Error('error executing');
mockHttpPost.mockRejectedValueOnce(error);
- const { result, waitForNextUpdate } = renderHook(() => useSubAction(params));
- await waitForNextUpdate();
-
- expect(result.current).toEqual({
- isLoading: false,
- response: undefined,
- error,
- });
+ const { result } = renderHook(() => useSubAction(params));
+ await waitFor(() =>
+ expect(result.current).toEqual({
+ isLoading: false,
+ response: undefined,
+ error,
+ })
+ );
});
it('should abort on unmount', async () => {
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_update_rules_settings.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_update_rules_settings.test.tsx
index c5f61885adddc..e1a04ea929b59 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_update_rules_settings.test.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_update_rules_settings.test.tsx
@@ -6,8 +6,7 @@
*/
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { act, renderHook } from '@testing-library/react-hooks/dom';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook, act } from '@testing-library/react';
import { useUpdateRuleSettings } from './use_update_rules_settings';
const mockAddDanger = jest.fn();
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/hooks/use_rule_type_ids_by_feature_id.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/hooks/use_rule_type_ids_by_feature_id.test.ts
index 3fd8ec70d9ff8..03f1f66ede9fc 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/hooks/use_rule_type_ids_by_feature_id.test.ts
+++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_page/hooks/use_rule_type_ids_by_feature_id.test.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks/dom';
+import { renderHook } from '@testing-library/react';
import { useRuleTypeIdsByFeatureId } from './use_rule_type_ids_by_feature_id';
import { ruleTypesIndex } from '../../../mock/rule_types_index';
import { MULTI_CONSUMER_RULE_TYPE_IDS } from '../../../constants';
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..6b1a14c0f7d2d 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,7 @@
*/
import { BehaviorSubject } from 'rxjs';
-import { act, renderHook } from '@testing-library/react-hooks';
+import { act, waitFor, renderHook } from '@testing-library/react';
import { useKibana } from '../../../../common/lib/kibana';
import { AppMockRenderer, createAppMockRenderer } from '../../test_utils';
import { useCaseViewNavigation } from './use_case_view_navigation';
@@ -25,8 +25,8 @@ describe('useCaseViewNavigation', () => {
useKibanaMock().services.application.navigateToApp = navigateToApp;
});
- it('calls navigateToApp with correct arguments', () => {
- const { result, waitFor } = renderHook(() => useCaseViewNavigation(), {
+ it('calls navigateToApp with correct arguments', async () => {
+ const { result } = renderHook(() => useCaseViewNavigation(), {
wrapper: appMockRender.AppWrapper,
});
@@ -34,7 +34,7 @@ describe('useCaseViewNavigation', () => {
result.current.navigateToCaseView({ caseId: 'test-id' });
});
- waitFor(() => {
+ await waitFor(() => {
expect(navigateToApp).toHaveBeenCalledWith('testAppId', {
deepLinkId: 'cases',
path: '/test-id',
@@ -42,8 +42,8 @@ describe('useCaseViewNavigation', () => {
});
});
- it('calls navigateToApp with correct arguments and bypass current app id', () => {
- const { result, waitFor } = renderHook(() => useCaseViewNavigation('superAppId'), {
+ it('calls navigateToApp with correct arguments and bypass current app id', async () => {
+ const { result } = renderHook(() => useCaseViewNavigation('superAppId'), {
wrapper: appMockRender.AppWrapper,
});
@@ -51,7 +51,7 @@ describe('useCaseViewNavigation', () => {
result.current.navigateToCaseView({ caseId: 'test-id' });
});
- waitFor(() => {
+ await waitFor(() => {
expect(navigateToApp).toHaveBeenCalledWith('superAppId', {
deepLinkId: 'cases',
path: '/test-id',
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..2718ccd8ca88e 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
@@ -5,9 +5,8 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
import * as api from '../apis/get_rules_muted_alerts';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import { useKibana } from '../../../../../common/lib/kibana';
import { AppMockRenderer, createAppMockRenderer } from '../../../test_utils';
import { useGetMutedAlerts } from './use_get_muted_alerts';
@@ -31,12 +30,10 @@ 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(() => {
expect(muteAlertInstanceSpy).toHaveBeenCalledWith(
expect.anything(),
@@ -53,18 +50,16 @@ describe('useGetMutedAlerts', () => {
wrapper: appMockRender.AppWrapper,
});
- expect(spy).not.toHaveBeenCalled();
+ await waitFor(() => expect(spy).not.toHaveBeenCalled());
});
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(() => {
expect(spy).toHaveBeenCalled();
expect(addErrorMock).toHaveBeenCalled();
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_mute_alert.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_mute_alert.test.tsx
index f7e8b94aa2e66..74d93a0504ca7 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_mute_alert.test.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_mute_alert.test.tsx
@@ -5,9 +5,8 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks/dom';
import * as api from '../../../../lib/rule_api/mute_alert';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import { useKibana } from '../../../../../common/lib/kibana';
import { AppMockRenderer, createAppMockRenderer } from '../../../test_utils';
import { useMuteAlert } from './use_mute_alert';
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_unmute_alert.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_unmute_alert.test.tsx
index d24a481ba30b8..178dc5bb6ed9b 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_unmute_alert.test.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/alert_mute/use_unmute_alert.test.tsx
@@ -5,9 +5,8 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks/dom';
import * as api from '../../../../lib/rule_api/unmute_alert';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import { useKibana } from '../../../../../common/lib/kibana';
import { AppMockRenderer, createAppMockRenderer } from '../../../test_utils';
import { useUnmuteAlert } from './use_unmute_alert';
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.test.tsx
index d84909e746f27..0f136e15156d7 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.test.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_bulk_actions.test.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react';
import { useBulkActions, useBulkAddToCaseActions, useBulkUntrackActions } from './use_bulk_actions';
import { AppMockRenderer, createAppMockRenderer } from '../../test_utils';
import { createCasesServiceMock } from '../index.mock';
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..e79955715d4ee 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
@@ -5,9 +5,8 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
import * as api from './apis/bulk_get_cases';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import { useKibana } from '../../../../common/lib/kibana';
import { useBulkGetCases } from './use_bulk_get_cases';
import { AppMockRenderer, createAppMockRenderer } from '../../test_utils';
@@ -35,18 +34,18 @@ 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();
-
- expect(spy).toHaveBeenCalledWith(
- expect.anything(),
- {
- ids: ['case-1'],
- },
- expect.any(AbortSignal)
+ await waitFor(() =>
+ expect(spy).toHaveBeenCalledWith(
+ expect.anything(),
+ {
+ ids: ['case-1'],
+ },
+ expect.any(AbortSignal)
+ )
);
});
@@ -58,18 +57,16 @@ describe('useBulkGetCases', () => {
wrapper: appMockRender.AppWrapper,
});
- expect(spy).not.toHaveBeenCalled();
+ await waitFor(() => expect(spy).not.toHaveBeenCalled());
});
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(() => {
expect(spy).toHaveBeenCalledWith(
expect.anything(),
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..7a2ffd32ad2c3 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
@@ -5,8 +5,7 @@
* 2.0.
*/
-import { renderHook } from '@testing-library/react-hooks';
-import { waitFor } from '@testing-library/react';
+import { waitFor, renderHook } from '@testing-library/react';
import { MaintenanceWindowStatus } from '@kbn/alerting-plugin/common';
import * as api from './apis/bulk_get_maintenance_windows';
import { coreMock } from '@kbn/core/public/mocks';
@@ -96,7 +95,7 @@ describe('useBulkGetMaintenanceWindows', () => {
const spy = jest.spyOn(api, 'bulkGetMaintenanceWindows');
spy.mockResolvedValue(response);
- const { waitForNextUpdate, result } = renderHook(
+ const { result } = renderHook(
() =>
useBulkGetMaintenanceWindows({
ids: ['test-id'],
@@ -107,9 +106,7 @@ describe('useBulkGetMaintenanceWindows', () => {
}
);
- await waitForNextUpdate();
-
- 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(),
@@ -132,7 +129,7 @@ describe('useBulkGetMaintenanceWindows', () => {
}
);
- expect(spy).not.toHaveBeenCalled();
+ await waitFor(() => expect(spy).not.toHaveBeenCalled());
});
it('does not call the api if license is not platinum', async () => {
@@ -152,7 +149,7 @@ describe('useBulkGetMaintenanceWindows', () => {
}
);
- expect(spy).not.toHaveBeenCalled();
+ await waitFor(() => expect(spy).not.toHaveBeenCalled());
});
it('does not call the api if capabilities are not adequate', async () => {
@@ -177,7 +174,7 @@ describe('useBulkGetMaintenanceWindows', () => {
}
);
- expect(spy).not.toHaveBeenCalled();
+ await waitFor(() => expect(spy).not.toHaveBeenCalled());
});
it('shows a toast error when the api return an error', async () => {
@@ -185,7 +182,7 @@ describe('useBulkGetMaintenanceWindows', () => {
.spyOn(api, 'bulkGetMaintenanceWindows')
.mockRejectedValue(new Error('An error'));
- const { waitForNextUpdate } = renderHook(
+ renderHook(
() =>
useBulkGetMaintenanceWindows({
ids: ['test-id'],
@@ -196,8 +193,6 @@ describe('useBulkGetMaintenanceWindows', () => {
}
);
- await waitForNextUpdate();
-
await waitFor(() => {
expect(spy).toHaveBeenCalledWith({
http: expect.anything(),
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..d6ecf3d9ab20d 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,12 +9,12 @@ 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 { act, waitFor, renderHook } 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';
import { fetchAlertsFields } from '@kbn/alerts-ui-shared/src/common/apis/fetch_alerts_fields';
-import { useColumns, UseColumnsArgs, UseColumnsResp } from './use_columns';
+import { useColumns } from './use_columns';
import { AlertsTableStorage } from '../../alerts_table_state';
import { createStartServicesMock } from '../../../../../common/lib/kibana/kibana_react.mock';
import { AlertsQueryContext } from '@kbn/alerts-ui-shared/src/common/contexts/alerts_query_context';
@@ -151,10 +151,7 @@ describe('useColumns', () => {
test('onColumnResize', async () => {
const localDefaultColumns = [...defaultColumns];
const localStorageAlertsTable = getStorageAlertsTableByDefaultColumns(localDefaultColumns);
- const { result, rerender } = renderHook<
- React.PropsWithChildren,
- UseColumnsResp
- >(
+ const { result, rerender } = renderHook(
() =>
useColumns({
defaultColumns,
@@ -186,7 +183,7 @@ describe('useColumns', () => {
test('check if initial width for the last column does not exist', async () => {
const localStorageAlertsTable = getStorageAlertsTableByDefaultColumns(defaultColumns);
- const { result } = renderHook, UseColumnsResp>(
+ const { result } = renderHook(
() =>
useColumns({
defaultColumns,
@@ -211,7 +208,7 @@ describe('useColumns', () => {
const alertsFields = {
testField: { name: 'testField', type: 'string', searchable: true, aggregatable: true },
};
- const { result } = renderHook, UseColumnsResp>(
+ const { result } = renderHook(
() =>
useColumns({
alertsFields,
@@ -231,7 +228,7 @@ describe('useColumns', () => {
describe('visibleColumns', () => {
test('hide all columns with onChangeVisibleColumns', async () => {
const localStorageAlertsTable = getStorageAlertsTableByDefaultColumns(defaultColumns);
- const { result } = renderHook, UseColumnsResp>(
+ const { result } = renderHook(
() =>
useColumns({
defaultColumns,
@@ -253,7 +250,7 @@ describe('useColumns', () => {
test('show all columns with onChangeVisibleColumns', async () => {
const localStorageAlertsTable = getStorageAlertsTableByDefaultColumns(defaultColumns);
- const { result } = renderHook, UseColumnsResp>(
+ const { result } = renderHook(
() =>
useColumns({
defaultColumns,
@@ -282,7 +279,7 @@ describe('useColumns', () => {
test('should populate visibleColumns correctly', async () => {
const localStorageAlertsTable = getStorageAlertsTableByDefaultColumns(defaultColumns);
- const { result } = renderHook, UseColumnsResp>(
+ const { result } = renderHook(
() =>
useColumns({
defaultColumns,
@@ -300,10 +297,7 @@ describe('useColumns', () => {
test('should change visibleColumns if provided defaultColumns change', async () => {
let localDefaultColumns = [...defaultColumns];
let localStorageAlertsTable = getStorageAlertsTableByDefaultColumns(localDefaultColumns);
- const { result, rerender } = renderHook<
- React.PropsWithChildren,
- UseColumnsResp
- >(
+ const { result, rerender } = renderHook(
() =>
useColumns({
defaultColumns: localDefaultColumns,
@@ -340,10 +334,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(
() =>
useColumns({
defaultColumns,
@@ -362,7 +353,7 @@ describe('useColumns', () => {
describe('onToggleColumns', () => {
test('should update the list of columns when on Toggle Columns is called', () => {
const localStorageAlertsTable = getStorageAlertsTableByDefaultColumns(defaultColumns);
- const { result } = renderHook, UseColumnsResp>(
+ const { result } = renderHook(
() =>
useColumns({
defaultColumns,
@@ -383,7 +374,7 @@ describe('useColumns', () => {
test('should update the list of visible columns when onToggleColumn is called', async () => {
const localStorageAlertsTable = getStorageAlertsTableByDefaultColumns(defaultColumns);
- const { result } = renderHook, UseColumnsResp>(
+ const { result } = renderHook(
() =>
useColumns({
defaultColumns,
@@ -412,7 +403,7 @@ describe('useColumns', () => {
test('should update the column details in the storage when onToggleColumn is called', () => {
const localStorageAlertsTable = getStorageAlertsTableByDefaultColumns(defaultColumns);
- const { result } = renderHook, UseColumnsResp>(
+ const { result } = renderHook(
() =>
useColumns({
defaultColumns,
@@ -445,7 +436,7 @@ describe('useColumns', () => {
describe('onResetColumns', () => {
test('should restore visible columns defaults', () => {
const localStorageAlertsTable = getStorageAlertsTableByDefaultColumns(defaultColumns);
- const { result } = renderHook, UseColumnsResp>(
+ const { result } = renderHook(
() =>
useColumns({
defaultColumns,
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_pagination.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_pagination.test.ts
index 24bddbe90ec59..b53855f991c59 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_pagination.test.ts
+++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_pagination.test.ts
@@ -5,7 +5,8 @@
* 2.0.
*/
import { usePagination } from './use_pagination';
-import { renderHook, act } from '@testing-library/react-hooks';
+
+import { renderHook, act } from '@testing-library/react';
describe('usePagination', () => {
const onPageChange = jest.fn();
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_sorting.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_sorting.test.ts
index 092ec0ed0eb43..95efe7c9c8c5a 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_sorting.test.ts
+++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_sorting.test.ts
@@ -5,7 +5,8 @@
* 2.0.
*/
import { useSorting } from './use_sorting';
-import { renderHook, act } from '@testing-library/react-hooks';
+
+import { renderHook, act } from '@testing-library/react';
describe('useSorting', () => {
const onSortChange = jest.fn();
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/hooks/use_rules_list_filter_store.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/hooks/use_rules_list_filter_store.test.tsx
index 89b5e56aa33dd..ee2a8637b9912 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/hooks/use_rules_list_filter_store.test.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/hooks/use_rules_list_filter_store.test.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { act, renderHook } from '@testing-library/react-hooks';
+import { renderHook, act } from '@testing-library/react';
import * as useLocalStorage from 'react-use/lib/useLocalStorage';
import { useRulesListFilterStore } from './use_rules_list_filter_store';
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_column_selector.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_column_selector.test.tsx
index ad623631fe85e..c3afafd716054 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_column_selector.test.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_column_selector.test.tsx
@@ -5,8 +5,7 @@
* 2.0.
*/
-import { render } from '@testing-library/react';
-import { renderHook } from '@testing-library/react-hooks';
+import { render, renderHook } from '@testing-library/react';
import React from 'react';
import {
RulesListColumns,
From 93dac5435ff51a3b28c5b3dd30bc4c24d1cf302c Mon Sep 17 00:00:00 2001
From: Robert Oskamp
Date: Fri, 22 Nov 2024 17:54:01 +0100
Subject: [PATCH 11/38] [ML] Functional tests - cleanMlIndices without system
index access (#199653)
## Summary
This PR updates the `cleanMlIndices` service method to no longer run
with `esDeleteAllIndices` and thus no longer requires system index
superuser privileges.
### Details / other changes
- Not all ML items can be cleaned up through APIs (e.g. notifications),
so tests have been adjusted to deal with pre-existing data
- Some cleanup steps had to be re-ordered
- Basic license tests didn't need the `cleanMlIndices` in their `before`
so it was removed there
- Observability serverless tests can't use `cleanMlIndices` as the APIs
for DFA are not available for that project type, so the cleanup is
changed to `cleanAnomalyDetection` for the AD tests and the
`cleanMlIndices` is removed from the AI assistant helpers as the
existing cleanup there should be enough
---
.../ml/notifications/count_notifications.ts | 27 ++--
.../ml/notifications/get_notifications.ts | 10 +-
.../apis/ml/trained_models/get_models.ts | 2 +-
x-pack/test/functional/services/ml/api.ts | 152 +++++++++++++++++-
.../apps/ml/permissions/full_ml_access.ts | 2 -
.../apps/ml/permissions/read_ml_access.ts | 2 -
.../tests/knowledge_base/helpers.ts | 1 -
.../ml/anomaly_detection_jobs_list.ts | 2 +-
.../ml/anomaly_detection_jobs_list.ts | 2 +-
.../ml/data_frame_analytics_jobs_list.ts | 2 +-
10 files changed, 175 insertions(+), 27 deletions(-)
diff --git a/x-pack/test/api_integration/apis/ml/notifications/count_notifications.ts b/x-pack/test/api_integration/apis/ml/notifications/count_notifications.ts
index a066999a08b51..e1ddf399d5722 100644
--- a/x-pack/test/api_integration/apis/ml/notifications/count_notifications.ts
+++ b/x-pack/test/api_integration/apis/ml/notifications/count_notifications.ts
@@ -6,7 +6,6 @@
*/
import expect from '@kbn/expect';
-import moment from 'moment';
import type { FtrProviderContext } from '../../../ftr_provider_context';
import { USER } from '../../../../functional/services/ml/security_common';
import { getCommonRequestHeader } from '../../../../functional/services/ml/common_api';
@@ -14,20 +13,25 @@ import { getCommonRequestHeader } from '../../../../functional/services/ml/commo
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertestWithoutAuth');
const ml = getService('ml');
+ let testStart: number;
describe('GET notifications count', () => {
+ before(async () => {
+ testStart = Date.now();
+ });
+
describe('when no ML entities present', () => {
it('return a default response', async () => {
const { body, status } = await supertest
.get(`/internal/ml/notifications/count`)
- .query({ lastCheckedAt: moment().subtract(7, 'd').valueOf() })
+ .query({ lastCheckedAt: testStart })
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
.set(getCommonRequestHeader('1'));
ml.api.assertResponseStatusCode(200, status, body);
- expect(body.info).to.eql(0);
- expect(body.warning).to.eql(0);
- expect(body.error).to.eql(0);
+ expect(body.info).to.eql(0, `Expecting info count to be 0, got ${body.info}`);
+ expect(body.warning).to.eql(0, `Expecting warning count to be 0, got ${body.warning}`);
+ expect(body.error).to.eql(0, `Expecting error count to be 0, got ${body.error}`);
});
});
@@ -36,10 +40,11 @@ export default ({ getService }: FtrProviderContext) => {
await ml.api.initSavedObjects();
await ml.testResources.setKibanaTimeZoneToUTC();
- const adJobConfig = ml.commonConfig.getADFqSingleMetricJobConfig('fq_job');
+ const jobId = `fq_job_${Date.now()}`;
+ const adJobConfig = ml.commonConfig.getADFqSingleMetricJobConfig(jobId);
await ml.api.createAnomalyDetectionJob(adJobConfig);
- await ml.api.waitForJobNotificationsToIndex('fq_job');
+ await ml.api.waitForJobNotificationsToIndex(jobId);
});
after(async () => {
@@ -50,14 +55,14 @@ export default ({ getService }: FtrProviderContext) => {
it('return notifications count by level', async () => {
const { body, status } = await supertest
.get(`/internal/ml/notifications/count`)
- .query({ lastCheckedAt: moment().subtract(7, 'd').valueOf() })
+ .query({ lastCheckedAt: testStart })
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
.set(getCommonRequestHeader('1'));
ml.api.assertResponseStatusCode(200, status, body);
- expect(body.info).to.eql(1);
- expect(body.warning).to.eql(0);
- expect(body.error).to.eql(0);
+ expect(body.info).to.eql(1, `Expecting info count to be 1, got ${body.info}`);
+ expect(body.warning).to.eql(0, `Expecting warning count to be 0, got ${body.warning}`);
+ expect(body.error).to.eql(0, `Expecting error count to be 0, got ${body.error}`);
});
it('returns an error for unauthorized user', async () => {
diff --git a/x-pack/test/api_integration/apis/ml/notifications/get_notifications.ts b/x-pack/test/api_integration/apis/ml/notifications/get_notifications.ts
index e13f1869e6659..5e5f2c584c46f 100644
--- a/x-pack/test/api_integration/apis/ml/notifications/get_notifications.ts
+++ b/x-pack/test/api_integration/apis/ml/notifications/get_notifications.ts
@@ -18,9 +18,11 @@ export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertestWithoutAuth');
const esArchiver = getService('esArchiver');
const ml = getService('ml');
+ let testStart: number;
describe('GET notifications', () => {
before(async () => {
+ testStart = Date.now();
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/bm_classification');
await ml.api.initSavedObjects();
await ml.testResources.setKibanaTimeZoneToUTC();
@@ -45,7 +47,7 @@ export default ({ getService }: FtrProviderContext) => {
it('return all notifications ', async () => {
const { body, status } = await supertest
.get(`/internal/ml/notifications`)
- .query({ earliest: 'now-1d', latest: 'now' })
+ .query({ earliest: testStart, latest: 'now' })
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
.set(getCommonRequestHeader('1'));
ml.api.assertResponseStatusCode(200, status, body);
@@ -56,7 +58,7 @@ export default ({ getService }: FtrProviderContext) => {
it('return notifications based on the query string', async () => {
const { body, status } = await supertest
.get(`/internal/ml/notifications`)
- .query({ earliest: 'now-1d', latest: 'now', queryString: 'job_type:anomaly_detector' })
+ .query({ earliest: testStart, latest: 'now', queryString: 'job_type:anomaly_detector' })
.auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER))
.set(getCommonRequestHeader('1'));
ml.api.assertResponseStatusCode(200, status, body);
@@ -72,7 +74,7 @@ export default ({ getService }: FtrProviderContext) => {
it('supports sorting asc sorting by field', async () => {
const { body, status } = await supertest
.get(`/internal/ml/notifications`)
- .query({ earliest: 'now-1d', latest: 'now', sortField: 'job_id', sortDirection: 'asc' })
+ .query({ earliest: testStart, latest: 'now', sortField: 'job_id', sortDirection: 'asc' })
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
.set(getCommonRequestHeader('1'));
ml.api.assertResponseStatusCode(200, status, body);
@@ -83,7 +85,7 @@ export default ({ getService }: FtrProviderContext) => {
it('supports sorting desc sorting by field', async () => {
const { body, status } = await supertest
.get(`/internal/ml/notifications`)
- .query({ earliest: 'now-1h', latest: 'now', sortField: 'job_id', sortDirection: 'desc' })
+ .query({ earliest: testStart, latest: 'now', sortField: 'job_id', sortDirection: 'desc' })
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
.set(getCommonRequestHeader('1'));
ml.api.assertResponseStatusCode(200, status, body);
diff --git a/x-pack/test/api_integration/apis/ml/trained_models/get_models.ts b/x-pack/test/api_integration/apis/ml/trained_models/get_models.ts
index 78f4347cd091e..a3953a87b82b2 100644
--- a/x-pack/test/api_integration/apis/ml/trained_models/get_models.ts
+++ b/x-pack/test/api_integration/apis/ml/trained_models/get_models.ts
@@ -32,7 +32,6 @@ export default ({ getService }: FtrProviderContext) => {
});
after(async () => {
- await ml.api.cleanMlIndices();
await esDeleteAllIndices('user-index_dfa*');
// delete created ingest pipelines
@@ -42,6 +41,7 @@ export default ({ getService }: FtrProviderContext) => {
)
);
await ml.testResources.cleanMLSavedObjects();
+ await ml.api.cleanMlIndices();
});
it('returns all trained models with associated pipelines including aliases', async () => {
diff --git a/x-pack/test/functional/services/ml/api.ts b/x-pack/test/functional/services/ml/api.ts
index 0a3d988fd750c..3d2d1004528d0 100644
--- a/x-pack/test/functional/services/ml/api.ts
+++ b/x-pack/test/functional/services/ml/api.ts
@@ -85,7 +85,6 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) {
const retry = getService('retry');
const esSupertest = getService('esSupertest');
const kbnSupertest = getService('supertest');
- const esDeleteAllIndices = getService('esDeleteAllIndices');
return {
assertResponseStatusCode(expectedStatus: number, actualStatus: number, responseBody: object) {
@@ -310,8 +309,37 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) {
log.debug('> Indices deleted.');
},
+ async deleteExpiredAnomalyDetectionData() {
+ log.debug('Deleting expired data ...');
+ const { body, status } = await esSupertest.delete('/_ml/_delete_expired_data');
+ this.assertResponseStatusCode(200, status, body);
+ log.debug('> Expired data deleted.');
+ },
+
+ async cleanAnomalyDetection() {
+ await this.deleteAllAnomalyDetectionJobs();
+ await this.deleteAllCalendars();
+ await this.deleteAllFilters();
+ await this.deleteAllAnnotations();
+ await this.deleteExpiredAnomalyDetectionData();
+ await this.syncSavedObjects();
+ },
+
+ async cleanDataFrameAnalytics() {
+ await this.deleteAllDataFrameAnalyticsJobs();
+ await this.syncSavedObjects();
+ },
+
+ async cleanTrainedModels() {
+ await this.deleteAllTrainedModelsIngestPipelines();
+ await this.deleteAllTrainedModelsES();
+ await this.syncSavedObjects();
+ },
+
async cleanMlIndices() {
- await esDeleteAllIndices('.ml-*');
+ await this.cleanAnomalyDetection();
+ await this.cleanDataFrameAnalytics();
+ await this.cleanTrainedModels();
},
async getJobState(jobId: string): Promise {
@@ -537,6 +565,12 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) {
return response;
},
+ async getAllCalendars(expectedCode = 200) {
+ const response = await esSupertest.get('/_ml/calendars/_all');
+ this.assertResponseStatusCode(expectedCode, response.status, response.body);
+ return response;
+ },
+
async createCalendar(
calendarId: string,
requestBody: Partial = { description: '', job_ids: [] }
@@ -559,6 +593,14 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) {
log.debug('> Calendar deleted.');
},
+ async deleteAllCalendars() {
+ log.debug('Deleting all calendars');
+ const getAllCalendarsRsp = await this.getAllCalendars();
+ for (const calendar of getAllCalendarsRsp.body.calendars) {
+ await this.deleteCalendar(calendar.calendar_id);
+ }
+ },
+
async waitForCalendarToExist(calendarId: string, errorMsg?: string) {
await retry.waitForWithTimeout(`'${calendarId}' to exist`, 5 * 1000, async () => {
if (await this.getCalendar(calendarId, 200)) {
@@ -660,6 +702,12 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) {
return response;
},
+ async getAllAnomalyDetectionJobs() {
+ const response = await esSupertest.get('/_ml/anomaly_detectors/_all');
+ this.assertResponseStatusCode(200, response.status, response.body);
+ return response;
+ },
+
async getAnomalyDetectionJobsKibana(jobId?: string, space?: string) {
const { body, status } = await kbnSupertest
.get(
@@ -831,6 +879,14 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) {
log.debug('> AD job deleted.');
},
+ async deleteAllAnomalyDetectionJobs() {
+ log.debug('Deleting all anomaly detection jobs');
+ const getAllAdJobsResp = await this.getAllAnomalyDetectionJobs();
+ for (const job of getAllAdJobsResp.body.jobs) {
+ await this.deleteAnomalyDetectionJobES(job.job_id);
+ }
+ },
+
async getDatafeed(datafeedId: string) {
const response = await esSupertest.get(`/_ml/datafeeds/${datafeedId}`);
this.assertResponseStatusCode(200, response.status, response.body);
@@ -1034,6 +1090,12 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) {
log.debug('> DFA job created.');
},
+ async getAllDataFrameAnalyticsJobs(expectedCode = 200) {
+ const response = await esSupertest.get('/_ml/data_frame/analytics/_all');
+ this.assertResponseStatusCode(expectedCode, response.status, response.body);
+ return response;
+ },
+
async createDataFrameAnalyticsJobES(jobConfig: DataFrameAnalyticsConfig) {
const { id: analyticsId, ...analyticsConfig } = jobConfig;
log.debug(`Creating data frame analytic job with id '${analyticsId}' via ES API...`);
@@ -1064,6 +1126,14 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) {
log.debug('> DFA job deleted.');
},
+ async deleteAllDataFrameAnalyticsJobs() {
+ log.debug('Deleting all data frame analytics jobs');
+ const getAllDfaJobsResp = await this.getAllDataFrameAnalyticsJobs();
+ for (const job of getAllDfaJobsResp.body.data_frame_analytics) {
+ await this.deleteDataFrameAnalyticsJobES(job.id);
+ }
+ },
+
async getADJobRecordCount(jobId: string): Promise {
const jobStats = await this.getADJobStats(jobId);
@@ -1114,12 +1184,24 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) {
);
},
+ async filterExists(filterId: string): Promise {
+ const { status } = await esSupertest.get(`/_ml/filters/${filterId}`);
+ if (status !== 200) return false;
+ return true;
+ },
+
async getFilter(filterId: string, expectedCode = 200) {
const response = await esSupertest.get(`/_ml/filters/${filterId}`);
this.assertResponseStatusCode(expectedCode, response.status, response.body);
return response;
},
+ async getAllFilters(expectedCode = 200) {
+ const response = await esSupertest.get(`/_ml/filters`);
+ this.assertResponseStatusCode(expectedCode, response.status, response.body);
+ return response;
+ },
+
async createFilter(filterId: string, requestBody: object) {
log.debug(`Creating filter with id '${filterId}'...`);
const { body, status } = await esSupertest.put(`/_ml/filters/${filterId}`).send(requestBody);
@@ -1131,12 +1213,27 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) {
async deleteFilter(filterId: string) {
log.debug(`Deleting filter with id '${filterId}'...`);
- await esSupertest.delete(`/_ml/filters/${filterId}`);
+
+ if ((await this.filterExists(filterId)) === false) {
+ log.debug('> Filter does not exist, nothing to delete');
+ return;
+ }
+
+ const { body, status } = await esSupertest.delete(`/_ml/filters/${filterId}`);
+ this.assertResponseStatusCode(200, status, body);
await this.waitForFilterToNotExist(filterId, `expected filter '${filterId}' to be deleted`);
log.debug('> Filter deleted.');
},
+ async deleteAllFilters() {
+ log.debug('Deleting all filters');
+ const getAllFiltersRsp = await this.getAllFilters();
+ for (const filter of getAllFiltersRsp.body.filters) {
+ await this.deleteFilter(filter.filter_id);
+ }
+ },
+
async assertModelMemoryLimitForJob(jobId: string, expectedMml: string) {
const {
body: {
@@ -1198,6 +1295,25 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) {
return body.hits.hits;
},
+ async getAllAnnotations() {
+ log.debug('Fetching all annotations ...');
+
+ if (
+ (await es.indices.exists({
+ index: ML_ANNOTATIONS_INDEX_ALIAS_READ,
+ allow_no_indices: false,
+ })) === false
+ ) {
+ return [];
+ }
+
+ const body = await es.search({ index: ML_ANNOTATIONS_INDEX_ALIAS_READ });
+ expect(body).to.not.be(undefined);
+ expect(body).to.have.property('hits');
+ log.debug('> All annotations fetched.');
+ return body.hits.hits;
+ },
+
async getAnnotationById(annotationId: string): Promise {
log.debug(`Fetching annotation '${annotationId}'...`);
@@ -1264,6 +1380,24 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) {
);
},
+ async deleteAnnotation(annotationId: string) {
+ log.debug(`Deleting annotation with id "${annotationId}"`);
+ const { body, status } = await kbnSupertest
+ .delete(`/internal/ml/annotations/delete/${annotationId}`)
+ .set(getCommonRequestHeader('1'));
+ this.assertResponseStatusCode(200, status, body);
+
+ log.debug('> Annotation deleted');
+ },
+
+ async deleteAllAnnotations() {
+ log.debug('Deleting all annotations.');
+ const allAnnotations = await this.getAllAnnotations();
+ for (const annotation of allAnnotations) {
+ await this.deleteAnnotation(annotation._id!);
+ }
+ },
+
async runDFAJob(dfaId: string) {
log.debug(`Starting data frame analytics job '${dfaId}'...`);
const { body: startResponse, status } = await esSupertest
@@ -1647,6 +1781,18 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) {
log.debug('> Ingest pipeline deleted');
},
+ async deleteAllTrainedModelsIngestPipelines() {
+ log.debug(`Deleting all trained models ingest pipelines`);
+ const getModelsRsp = await this.getTrainedModelsES();
+ for (const model of getModelsRsp.trained_model_configs) {
+ if (this.isInternalModelId(model.model_id)) {
+ log.debug(`> Skipping internal ${model.model_id}`);
+ continue;
+ }
+ await this.deleteIngestPipeline(model.model_id);
+ }
+ },
+
async assureMlStatsIndexExists(timeout: number = 60 * 1000) {
const params = {
index: '.ml-stats-000001',
diff --git a/x-pack/test/functional_basic/apps/ml/permissions/full_ml_access.ts b/x-pack/test/functional_basic/apps/ml/permissions/full_ml_access.ts
index 010bae3ba4bb2..ab4dc572517ca 100644
--- a/x-pack/test/functional_basic/apps/ml/permissions/full_ml_access.ts
+++ b/x-pack/test/functional_basic/apps/ml/permissions/full_ml_access.ts
@@ -32,8 +32,6 @@ export default function ({ getService }: FtrProviderContext) {
const expectedUploadFileTitle = 'artificial_server_log';
before(async () => {
- await ml.api.cleanMlIndices();
-
await esArchiver.loadIfNeeded(
'x-pack/test/functional/es_archives/ml/module_sample_ecommerce'
);
diff --git a/x-pack/test/functional_basic/apps/ml/permissions/read_ml_access.ts b/x-pack/test/functional_basic/apps/ml/permissions/read_ml_access.ts
index 96aec074ec557..14a4be1ac8fdc 100644
--- a/x-pack/test/functional_basic/apps/ml/permissions/read_ml_access.ts
+++ b/x-pack/test/functional_basic/apps/ml/permissions/read_ml_access.ts
@@ -32,8 +32,6 @@ export default function ({ getService }: FtrProviderContext) {
const expectedUploadFileTitle = 'artificial_server_log';
before(async () => {
- await ml.api.cleanMlIndices();
-
await esArchiver.loadIfNeeded(
'x-pack/test/functional/es_archives/ml/module_sample_ecommerce'
);
diff --git a/x-pack/test/observability_ai_assistant_api_integration/tests/knowledge_base/helpers.ts b/x-pack/test/observability_ai_assistant_api_integration/tests/knowledge_base/helpers.ts
index 25bbeb183a3b6..8965504aafc3c 100644
--- a/x-pack/test/observability_ai_assistant_api_integration/tests/knowledge_base/helpers.ts
+++ b/x-pack/test/observability_ai_assistant_api_integration/tests/knowledge_base/helpers.ts
@@ -30,7 +30,6 @@ export async function createKnowledgeBaseModel(ml: ReturnType) {
await ml.api.stopTrainedModelDeploymentES(TINY_ELSER.id, true);
await ml.api.deleteTrainedModelES(TINY_ELSER.id);
- await ml.api.cleanMlIndices();
await ml.testResources.cleanMLSavedObjects();
}
diff --git a/x-pack/test_serverless/functional/test_suites/observability/ml/anomaly_detection_jobs_list.ts b/x-pack/test_serverless/functional/test_suites/observability/ml/anomaly_detection_jobs_list.ts
index bdd5d443b3592..8073a7c5fcc78 100644
--- a/x-pack/test_serverless/functional/test_suites/observability/ml/anomaly_detection_jobs_list.ts
+++ b/x-pack/test_serverless/functional/test_suites/observability/ml/anomaly_detection_jobs_list.ts
@@ -31,7 +31,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
after(async () => {
- await ml.api.cleanMlIndices();
+ await ml.api.cleanAnomalyDetection();
await ml.testResources.cleanMLSavedObjects();
await esArchiver.unload('x-pack/test/functional/es_archives/logstash_functional');
await kibanaServer.savedObjects.cleanStandardList();
diff --git a/x-pack/test_serverless/functional/test_suites/security/ml/anomaly_detection_jobs_list.ts b/x-pack/test_serverless/functional/test_suites/security/ml/anomaly_detection_jobs_list.ts
index 9e1154ea09bbc..e8f3f5e1796f3 100644
--- a/x-pack/test_serverless/functional/test_suites/security/ml/anomaly_detection_jobs_list.ts
+++ b/x-pack/test_serverless/functional/test_suites/security/ml/anomaly_detection_jobs_list.ts
@@ -29,7 +29,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
after(async () => {
- await ml.api.cleanMlIndices();
+ await ml.api.cleanAnomalyDetection();
await ml.testResources.cleanMLSavedObjects();
await esArchiver.unload('x-pack/test/functional/es_archives/logstash_functional');
await kibanaServer.savedObjects.cleanStandardList();
diff --git a/x-pack/test_serverless/functional/test_suites/security/ml/data_frame_analytics_jobs_list.ts b/x-pack/test_serverless/functional/test_suites/security/ml/data_frame_analytics_jobs_list.ts
index d3caa3425f753..110cf64e07a17 100644
--- a/x-pack/test_serverless/functional/test_suites/security/ml/data_frame_analytics_jobs_list.ts
+++ b/x-pack/test_serverless/functional/test_suites/security/ml/data_frame_analytics_jobs_list.ts
@@ -29,7 +29,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
after(async () => {
- await ml.api.cleanMlIndices();
+ await ml.api.cleanAnomalyDetection();
await ml.testResources.cleanMLSavedObjects();
});
From 1cb56d7196cf60b03cb539f32f6a466a17141e02 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Patryk=20Kopyci=C5=84ski?=
Date: Fri, 22 Nov 2024 17:58:24 +0100
Subject: [PATCH 12/38] [Security KB] Fix setup KB (#201175)
## Summary
Fix an issue with auto-recovery of Knowledge Base setup.
When the KB setup was initialized on an undersized cluster, the model
failed to deploy correctly. This resulted in the KB ending up in a
broken state, repeatedly displaying the Setup KB button.
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
---
.../knowledge_base/index.ts | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/knowledge_base/index.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/knowledge_base/index.ts
index 231aa1c319da4..c3ce7fb1a43a0 100644
--- a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/knowledge_base/index.ts
+++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/knowledge_base/index.ts
@@ -178,9 +178,22 @@ export class AIAssistantKnowledgeBaseDataClient extends AIAssistantDataClient {
public createInferenceEndpoint = async () => {
const elserId = await this.options.getElserId();
this.options.logger.debug(`Deploying ELSER model '${elserId}'...`);
+ const esClient = await this.options.elasticsearchClientPromise;
+
try {
- const esClient = await this.options.elasticsearchClientPromise;
+ await esClient.inference.delete({
+ inference_id: ASSISTANT_ELSER_INFERENCE_ID,
+ // it's being used in the mapping so we need to force delete
+ force: true,
+ });
+ this.options.logger.debug(`Deleted existing inference endpoint for ELSER model '${elserId}'`);
+ } catch (error) {
+ this.options.logger.error(
+ `Error deleting inference endpoint for ELSER model '${elserId}':\n${error}`
+ );
+ }
+ try {
await esClient.inference.put({
task_type: 'sparse_embedding',
inference_id: ASSISTANT_ELSER_INFERENCE_ID,
@@ -198,6 +211,9 @@ export class AIAssistantKnowledgeBaseDataClient extends AIAssistantDataClient {
task_settings: {},
},
});
+
+ // await for the model to be deployed
+ await this.isInferenceEndpointExists();
} catch (error) {
this.options.logger.error(
`Error creating inference endpoint for ELSER model '${elserId}':\n${error}`
From 9fa8ec71529faa31a44fe2eac0902fb0d4b98797 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mike=20C=C3=B4t=C3=A9?=
Date: Fri, 22 Nov 2024 12:33:43 -0500
Subject: [PATCH 13/38] Fix bug in capacity warning logs when
assumedAverageRecurringRequiredThroughputPerMinutePerKibana was sufficient
(#200578)
In this PR, I'm fixing a bug where the task manager unhealthy logs were
showing the wrong reason. Because the if condition was checking
`assumedAverageRecurringRequiredThroughputPerMinutePerKibana` to be less
than `capacityPerMinutePerKibana`, it would log this as the reason task
manager is healthy. However whenever the value is less, it means task
manager is running fine from a recurring task perspective. Changing the
if condition allows the next step in the code to log which then logs
`assumedRequiredThroughputPerMinutePerKibana` as the real reason why
task manager is unhealthy.
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
---
.../server/monitoring/capacity_estimation.test.ts | 4 ++--
.../task_manager/server/monitoring/capacity_estimation.ts | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/x-pack/plugins/task_manager/server/monitoring/capacity_estimation.test.ts b/x-pack/plugins/task_manager/server/monitoring/capacity_estimation.test.ts
index 23ef344c197fc..f5b3912eabd3b 100644
--- a/x-pack/plugins/task_manager/server/monitoring/capacity_estimation.test.ts
+++ b/x-pack/plugins/task_manager/server/monitoring/capacity_estimation.test.ts
@@ -644,7 +644,7 @@ describe('estimateCapacity', () => {
value: expect.any(Object),
});
expect(logger.warn).toHaveBeenCalledWith(
- 'Task Manager is unhealthy, the assumedAverageRecurringRequiredThroughputPerMinutePerKibana (175) < capacityPerMinutePerKibana (200)'
+ 'Task Manager is unhealthy, the assumedRequiredThroughputPerMinutePerKibana (215) >= capacityPerMinutePerKibana (200)'
);
});
@@ -710,7 +710,7 @@ describe('estimateCapacity', () => {
value: expect.any(Object),
});
expect(logger.warn).toHaveBeenCalledWith(
- 'Task Manager is unhealthy, the assumedRequiredThroughputPerMinutePerKibana (250) >= capacityPerMinutePerKibana (200) AND assumedAverageRecurringRequiredThroughputPerMinutePerKibana (210) >= capacityPerMinutePerKibana (200)'
+ 'Task Manager is unhealthy, the assumedAverageRecurringRequiredThroughputPerMinutePerKibana (210) > capacityPerMinutePerKibana (200)'
);
});
diff --git a/x-pack/plugins/task_manager/server/monitoring/capacity_estimation.ts b/x-pack/plugins/task_manager/server/monitoring/capacity_estimation.ts
index acbf1284b21b7..a4a9c963e8ee3 100644
--- a/x-pack/plugins/task_manager/server/monitoring/capacity_estimation.ts
+++ b/x-pack/plugins/task_manager/server/monitoring/capacity_estimation.ts
@@ -248,13 +248,13 @@ function getHealthStatus(
return { status: HealthStatus.OK, reason };
}
- if (assumedAverageRecurringRequiredThroughputPerMinutePerKibana < capacityPerMinutePerKibana) {
- const reason = `Task Manager is unhealthy, the assumedAverageRecurringRequiredThroughputPerMinutePerKibana (${assumedAverageRecurringRequiredThroughputPerMinutePerKibana}) < capacityPerMinutePerKibana (${capacityPerMinutePerKibana})`;
+ if (assumedAverageRecurringRequiredThroughputPerMinutePerKibana > capacityPerMinutePerKibana) {
+ const reason = `Task Manager is unhealthy, the assumedAverageRecurringRequiredThroughputPerMinutePerKibana (${assumedAverageRecurringRequiredThroughputPerMinutePerKibana}) > capacityPerMinutePerKibana (${capacityPerMinutePerKibana})`;
logger.warn(reason);
return { status: HealthStatus.OK, reason };
}
- const reason = `Task Manager is unhealthy, the assumedRequiredThroughputPerMinutePerKibana (${assumedRequiredThroughputPerMinutePerKibana}) >= capacityPerMinutePerKibana (${capacityPerMinutePerKibana}) AND assumedAverageRecurringRequiredThroughputPerMinutePerKibana (${assumedAverageRecurringRequiredThroughputPerMinutePerKibana}) >= capacityPerMinutePerKibana (${capacityPerMinutePerKibana})`;
+ const reason = `Task Manager is unhealthy, the assumedRequiredThroughputPerMinutePerKibana (${assumedRequiredThroughputPerMinutePerKibana}) >= capacityPerMinutePerKibana (${capacityPerMinutePerKibana})`;
logger.warn(reason);
return { status: HealthStatus.OK, reason };
}
From 62b191c0dd65e992e08181961fb8b64614432daa Mon Sep 17 00:00:00 2001
From: jennypavlova
Date: Fri, 22 Nov 2024 18:40:27 +0100
Subject: [PATCH 14/38] [Profiling UI] Fix deprecated usage of ApiActions `get`
(#200883)
Closes #200708
## Summary
This PR fixes deprecated usage of ApiActions get in
[get_has_setup_privileges.ts](https://github.com/elastic/kibana/compare/main...jennypavlova:200708-profiling-ui-fix-deprecated-usage-of-apiactions-get?expand=1#diff-3ed5ba625d0b40a258485edf84456c4258de4ea21727ec342a440238a534bc97)
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
---
.../server/lib/setup/get_has_setup_privileges.ts | 8 ++++++--
.../observability_solution/profiling/tsconfig.json | 3 ++-
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/x-pack/plugins/observability_solution/profiling/server/lib/setup/get_has_setup_privileges.ts b/x-pack/plugins/observability_solution/profiling/server/lib/setup/get_has_setup_privileges.ts
index 83bd21b1740b8..8696c97dabd31 100644
--- a/x-pack/plugins/observability_solution/profiling/server/lib/setup/get_has_setup_privileges.ts
+++ b/x-pack/plugins/observability_solution/profiling/server/lib/setup/get_has_setup_privileges.ts
@@ -7,6 +7,7 @@
import { KibanaRequest } from '@kbn/core/server';
import { INTEGRATIONS_PLUGIN_ID, PLUGIN_ID as FLEET_PLUGIN_ID } from '@kbn/fleet-plugin/common';
+import { ApiOperation } from '@kbn/security-plugin-types-server';
import { ProfilingPluginStartDeps } from '../../types';
export async function getHasSetupPrivileges({
@@ -31,8 +32,11 @@ export async function getHasSetupPrivileges({
},
},
kibana: [
- securityPluginStart.authz.actions.api.get(`${FLEET_PLUGIN_ID}-all`),
- securityPluginStart.authz.actions.api.get(`${INTEGRATIONS_PLUGIN_ID}-all`),
+ securityPluginStart.authz.actions.api.get(ApiOperation.Manage, `${FLEET_PLUGIN_ID}-all`),
+ securityPluginStart.authz.actions.api.get(
+ ApiOperation.Manage,
+ `${INTEGRATIONS_PLUGIN_ID}-all`
+ ),
],
});
return hasAllRequested;
diff --git a/x-pack/plugins/observability_solution/profiling/tsconfig.json b/x-pack/plugins/observability_solution/profiling/tsconfig.json
index 937eee96641c8..b89d34bb8442b 100644
--- a/x-pack/plugins/observability_solution/profiling/tsconfig.json
+++ b/x-pack/plugins/observability_solution/profiling/tsconfig.json
@@ -54,7 +54,8 @@
"@kbn/management-settings-components-field-row",
"@kbn/deeplinks-observability",
"@kbn/react-kibana-context-render",
- "@kbn/apm-data-access-plugin"
+ "@kbn/apm-data-access-plugin",
+ "@kbn/security-plugin-types-server"
// add references to other TypeScript projects the plugin depends on
// requiredPlugins from ./kibana.json
From 8e6698f6e70681d9bdb23ff88a2a76cdde3a38c0 Mon Sep 17 00:00:00 2001
From: Nicolas Chaulet
Date: Fri, 22 Nov 2024 12:00:22 -0600
Subject: [PATCH 15/38] [Fleet] Fix agent dashboard link accross multiple space
(#201280)
---
.../components/agent_dashboard_link.test.tsx | 7 ++-
.../components/agent_dashboard_link.tsx | 34 ++++++++++-
.../components/dashboards_buttons.tsx | 60 ++++++++++++-------
.../agents/services/dashboard_helper.test.ts | 38 ++++++++++++
.../agents/services/dashboard_helpers.ts | 32 ++++++++++
5 files changed, 147 insertions(+), 24 deletions(-)
create mode 100644 x-pack/plugins/fleet/public/applications/fleet/sections/agents/services/dashboard_helper.test.ts
create mode 100644 x-pack/plugins/fleet/public/applications/fleet/sections/agents/services/dashboard_helpers.ts
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_dashboard_link.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_dashboard_link.test.tsx
index 79908819ff863..03f7b2b33a83c 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_dashboard_link.test.tsx
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_dashboard_link.test.tsx
@@ -21,6 +21,7 @@ jest.mock('../../../../../../hooks/use_fleet_status', () => ({
FleetStatusProvider: (props: any) => {
return props.children;
},
+ useFleetStatus: jest.fn().mockReturnValue({ spaceId: 'default' }),
}));
jest.mock('../../../../../../hooks/use_request/epm');
@@ -30,7 +31,7 @@ jest.mock('../../../../../../hooks/use_locator', () => {
useDashboardLocator: jest.fn().mockImplementation(() => {
return {
id: 'DASHBOARD_APP_LOCATOR',
- getRedirectUrl: jest.fn().mockResolvedValue('app/dashboards#/view/elastic_agent-a0001'),
+ getRedirectUrl: jest.fn().mockReturnValue('app/dashboards#/view/elastic_agent-a0001'),
};
}),
};
@@ -43,6 +44,10 @@ describe('AgentDashboardLink', () => {
data: {
item: {
status: 'installed',
+ installationInfo: {
+ install_status: 'installed',
+ installed_kibana_space_id: 'default',
+ },
},
},
} as ReturnType);
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_dashboard_link.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_dashboard_link.tsx
index 6832f81961ddb..c6a7c6b1a7d43 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_dashboard_link.tsx
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_dashboard_link.tsx
@@ -10,21 +10,49 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { EuiButton, EuiToolTip } from '@elastic/eui';
import styled from 'styled-components';
-import { useGetPackageInfoByKeyQuery, useLink, useDashboardLocator } from '../../../../hooks';
+import type { GetInfoResponse } from '../../../../../../../common/types';
+import {
+ useGetPackageInfoByKeyQuery,
+ useLink,
+ useDashboardLocator,
+ useFleetStatus,
+} from '../../../../hooks';
import type { Agent, AgentPolicy } from '../../../../types';
import {
FLEET_ELASTIC_AGENT_PACKAGE,
DASHBOARD_LOCATORS_IDS,
} from '../../../../../../../common/constants';
+import { getDashboardIdForSpace } from '../../services/dashboard_helpers';
+
+function isKibanaAssetsInstalledInSpace(spaceId: string | undefined, res?: GetInfoResponse) {
+ if (res?.item?.status !== 'installed') {
+ return false;
+ }
+
+ const installationInfo = res.item.installationInfo;
+
+ if (!installationInfo || installationInfo.install_status !== 'installed') {
+ return false;
+ }
+ return (
+ installationInfo.installed_kibana_space_id === spaceId ||
+ (spaceId && installationInfo.additional_spaces_installed_kibana?.[spaceId])
+ );
+}
function useAgentDashboardLink(agent: Agent) {
const { isLoading, data } = useGetPackageInfoByKeyQuery(FLEET_ELASTIC_AGENT_PACKAGE);
+ const { spaceId } = useFleetStatus();
- const isInstalled = data?.item.status === 'installed';
+ const isInstalled = isKibanaAssetsInstalledInSpace(spaceId, data);
const dashboardLocator = useDashboardLocator();
const link = dashboardLocator?.getRedirectUrl({
- dashboardId: DASHBOARD_LOCATORS_IDS.ELASTIC_AGENT_AGENT_METRICS,
+ dashboardId: getDashboardIdForSpace(
+ spaceId,
+ data,
+ DASHBOARD_LOCATORS_IDS.ELASTIC_AGENT_AGENT_METRICS
+ ),
query: {
language: 'kuery',
query: `elastic_agent.id:${agent.id}`,
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/dashboards_buttons.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/dashboards_buttons.tsx
index 25c394e2606b0..3e50258071576 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/dashboards_buttons.tsx
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/dashboards_buttons.tsx
@@ -5,49 +5,69 @@
* 2.0.
*/
-import React, { useEffect } from 'react';
+import React from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
+import { useQuery } from '@tanstack/react-query';
-import { DASHBOARD_LOCATORS_IDS } from '../../../../../../../common/constants';
+import {
+ DASHBOARD_LOCATORS_IDS,
+ FLEET_ELASTIC_AGENT_PACKAGE,
+} from '../../../../../../../common/constants';
-import { useDashboardLocator, useStartServices } from '../../../../hooks';
+import {
+ useDashboardLocator,
+ useFleetStatus,
+ useGetPackageInfoByKeyQuery,
+ useStartServices,
+} from '../../../../hooks';
+
+import { getDashboardIdForSpace } from '../../services/dashboard_helpers';
const useDashboardExists = (dashboardId: string) => {
- const [dashboardExists, setDashboardExists] = React.useState(false);
- const [loading, setLoading] = React.useState(true);
const { dashboard: dashboardPlugin } = useStartServices();
- useEffect(() => {
- const fetchDashboard = async () => {
+ const { data, isLoading } = useQuery({
+ queryKey: ['dashboard_exists', dashboardId],
+ queryFn: async () => {
try {
const findDashboardsService = await dashboardPlugin.findDashboardsService();
const [dashboard] = await findDashboardsService.findByIds([dashboardId]);
- setLoading(false);
- setDashboardExists(dashboard?.status === 'success');
+ return dashboard?.status === 'success';
} catch (e) {
- setLoading(false);
- setDashboardExists(false);
+ return false;
}
- };
-
- fetchDashboard();
- }, [dashboardId, dashboardPlugin]);
-
- return { dashboardExists, loading };
+ },
+ });
+ return { dashboardExists: data ?? false, loading: isLoading };
};
export const DashboardsButtons: React.FunctionComponent = () => {
+ const { data } = useGetPackageInfoByKeyQuery(FLEET_ELASTIC_AGENT_PACKAGE);
+ const { spaceId } = useFleetStatus();
+
const dashboardLocator = useDashboardLocator();
const getDashboardHref = (dashboardId: string) => {
return dashboardLocator?.getRedirectUrl({ dashboardId }) || '';
};
- const { dashboardExists, loading: dashboardLoading } = useDashboardExists(
+ const elasticAgentOverviewDashboardId = getDashboardIdForSpace(
+ spaceId,
+ data,
DASHBOARD_LOCATORS_IDS.ELASTIC_AGENT_OVERVIEW
);
+ const elasticAgentInfoDashboardId = getDashboardIdForSpace(
+ spaceId,
+ data,
+ DASHBOARD_LOCATORS_IDS.ELASTIC_AGENT_AGENT_INFO
+ );
+
+ const { dashboardExists, loading: dashboardLoading } = useDashboardExists(
+ elasticAgentOverviewDashboardId
+ );
+
if (dashboardLoading || !dashboardExists) {
return null;
}
@@ -58,7 +78,7 @@ export const DashboardsButtons: React.FunctionComponent = () => {
{
{
+ it('return the same id if package is installed in the same space', () => {
+ expect(() => getDashboardIdForSpace('default', PKG_INFO, 'test-id-1'));
+ });
+
+ it('return the destination ID if package is installed in an additionnal space', () => {
+ expect(() => getDashboardIdForSpace('test', PKG_INFO, 'test-id-1'));
+ });
+});
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/services/dashboard_helpers.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/services/dashboard_helpers.ts
new file mode 100644
index 0000000000000..bc46118b93fe3
--- /dev/null
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/services/dashboard_helpers.ts
@@ -0,0 +1,32 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
+
+import type { GetInfoResponse } from '../../../../../../common';
+
+export function getDashboardIdForSpace(
+ spaceId: string = DEFAULT_SPACE_ID,
+ res: GetInfoResponse | undefined,
+ dashboardId: string
+) {
+ if (res?.item?.status !== 'installed') {
+ return dashboardId;
+ }
+
+ const installationInfo = res.item.installationInfo;
+
+ if (!installationInfo || installationInfo?.installed_kibana_space_id === spaceId) {
+ return dashboardId;
+ }
+
+ return (
+ installationInfo.additional_spaces_installed_kibana?.[spaceId]?.find(
+ ({ originId }) => originId === dashboardId
+ )?.id ?? dashboardId
+ );
+}
From ad61b9d1010c13dd9c6c3faa5f848ce6d35a9e76 Mon Sep 17 00:00:00 2001
From: Nicolas Chaulet
Date: Fri, 22 Nov 2024 12:00:44 -0600
Subject: [PATCH 16/38] [Fleet] Fix settings response when space awareness
enabled (#201416)
---
.../fleet/server/services/settings.test.ts | 36 ++++++++++++++++
.../plugins/fleet/server/services/settings.ts | 42 +++++++++++--------
2 files changed, 60 insertions(+), 18 deletions(-)
diff --git a/x-pack/plugins/fleet/server/services/settings.test.ts b/x-pack/plugins/fleet/server/services/settings.test.ts
index f88e735dfcb69..9a75dc72abf3e 100644
--- a/x-pack/plugins/fleet/server/services/settings.test.ts
+++ b/x-pack/plugins/fleet/server/services/settings.test.ts
@@ -143,6 +143,42 @@ describe('getSettings', () => {
await getSettings(soClient);
});
+
+ it('should handle null values for space awareness migration fields', async () => {
+ const soClient = savedObjectsClientMock.create();
+
+ soClient.find.mockResolvedValueOnce({
+ saved_objects: [
+ {
+ id: GLOBAL_SETTINGS_ID,
+ attributes: {
+ use_space_awareness_migration_status: null,
+ use_space_awareness_migration_started_at: null,
+ },
+ references: [],
+ type: GLOBAL_SETTINGS_SAVED_OBJECT_TYPE,
+ score: 0,
+ },
+ ],
+ page: 1,
+ per_page: 10,
+ total: 1,
+ });
+
+ const settings = await getSettings(soClient);
+ expect(settings).toEqual({
+ delete_unenrolled_agents: undefined,
+ has_seen_add_data_notice: undefined,
+ id: 'fleet-default-settings',
+ output_secret_storage_requirements_met: undefined,
+ preconfigured_fields: [],
+ prerelease_integrations_enabled: undefined,
+ secret_storage_requirements_met: undefined,
+ use_space_awareness_migration_started_at: undefined,
+ use_space_awareness_migration_status: undefined,
+ version: undefined,
+ });
+ });
});
describe('saveSettings', () => {
diff --git a/x-pack/plugins/fleet/server/services/settings.ts b/x-pack/plugins/fleet/server/services/settings.ts
index 3288ec1090e41..5e1948d5d3797 100644
--- a/x-pack/plugins/fleet/server/services/settings.ts
+++ b/x-pack/plugins/fleet/server/services/settings.ts
@@ -6,7 +6,11 @@
*/
import Boom from '@hapi/boom';
-import type { SavedObjectsClientContract, SavedObjectsUpdateOptions } from '@kbn/core/server';
+import type {
+ SavedObject,
+ SavedObjectsClientContract,
+ SavedObjectsUpdateOptions,
+} from '@kbn/core/server';
import { omit } from 'lodash';
import { GLOBAL_SETTINGS_SAVED_OBJECT_TYPE, GLOBAL_SETTINGS_ID } from '../../common/constants';
@@ -18,21 +22,7 @@ import { DeleteUnenrolledAgentsPreconfiguredError } from '../errors';
import { appContextService } from './app_context';
import { auditLoggingService } from './audit_logging';
-export async function getSettings(soClient: SavedObjectsClientContract): Promise {
- const res = await soClient.find({
- type: GLOBAL_SETTINGS_SAVED_OBJECT_TYPE,
- });
- auditLoggingService.writeCustomSoAuditLog({
- action: 'get',
- id: GLOBAL_SETTINGS_ID,
- savedObjectType: GLOBAL_SETTINGS_SAVED_OBJECT_TYPE,
- });
-
- if (res.total === 0) {
- throw Boom.notFound('Global settings not found');
- }
- const settingsSo = res.saved_objects[0];
-
+function mapSettingsSO(settingsSo: SavedObject): Settings {
return {
id: settingsSo.id,
version: settingsSo.version,
@@ -42,14 +32,30 @@ export async function getSettings(soClient: SavedObjectsClientContract): Promise
has_seen_add_data_notice: settingsSo.attributes.has_seen_add_data_notice,
prerelease_integrations_enabled: settingsSo.attributes.prerelease_integrations_enabled,
use_space_awareness_migration_status:
- settingsSo.attributes.use_space_awareness_migration_status,
+ settingsSo.attributes.use_space_awareness_migration_status ?? undefined,
use_space_awareness_migration_started_at:
- settingsSo.attributes.use_space_awareness_migration_started_at,
+ settingsSo.attributes.use_space_awareness_migration_started_at ?? undefined,
preconfigured_fields: getConfigFleetServerHosts() ? ['fleet_server_hosts'] : [],
delete_unenrolled_agents: settingsSo.attributes.delete_unenrolled_agents,
};
}
+export async function getSettings(soClient: SavedObjectsClientContract): Promise {
+ const res = await soClient.find({
+ type: GLOBAL_SETTINGS_SAVED_OBJECT_TYPE,
+ });
+ auditLoggingService.writeCustomSoAuditLog({
+ action: 'get',
+ id: GLOBAL_SETTINGS_ID,
+ savedObjectType: GLOBAL_SETTINGS_SAVED_OBJECT_TYPE,
+ });
+
+ if (res.total === 0) {
+ throw Boom.notFound('Global settings not found');
+ }
+ return mapSettingsSO(res.saved_objects[0]);
+}
+
export async function getSettingsOrUndefined(
soClient: SavedObjectsClientContract
): Promise {
From 30fb8dd5bb97b5001030ed9eed355ab4fffc9070 Mon Sep 17 00:00:00 2001
From: Kevin Qualters <56408403+kqualters-elastic@users.noreply.github.com>
Date: Fri, 22 Nov 2024 13:24:54 -0500
Subject: [PATCH 17/38] [Security Solution] [Timeline] Consolidate reduces,
remove unneeded async/awaits, other small fixes (#197168)
## Summary
For most of 8.x, both anecdotally from users and in development,
timeline search strategy based apis would often seem slower than the
equivalent search in discover or elsewhere in kibana, and I have long
suspected that this came from how the timeline sever code formatted the
elasticsearch responses for use in the UI, and while working on
something else, noticed even higher than normal occurrences in logs of
"][http.server.Kibana] Event loop utilization for
/internal/search/timelineSearchStrategy exceeded threshold of..." and so
I tried to refactor all of the functions in place as much as possible,
keeping the apis similar, most of the unit tests, etc, but removing as
many as possible of the Promise.alls, reduce within reduce, etc. This
has lead to a substantial improvement in performance, as you can see
below, and with larger result sets, I think the difference would only be
more noticeable.
After fix:
~40 ms for formatTimelineData with ~1000 docs
Before fix:
~18000 ms for formatTimelineData with ~1000 docs
[chrome_profile_timeline_slow.cpuprofile](https://github.com/user-attachments/files/17825602/chrome_profile_timeline_slow.cpuprofile)
[chrome_profile_timeline_fast.cpuprofile](https://github.com/user-attachments/files/17825606/chrome_profile_timeline_fast.cpuprofile)
I've attached the chrome devtools profiles for each, the time was
measured with the function:
```
async function measureAwait(promise: Promise, label: string): Promise {
const start = performance.now();
try {
const result = await promise;
const duration = performance.now() - start;
console.log(`${label} took ${duration}ms`);
return result;
} catch (error) {
const duration = performance.now() - start;
console.log(`${label} failed after ${duration}ms`);
throw error;
}
}
```
Wrapped around the call to formatTimelineData in
x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/all/index.ts
### Checklist
- [ ] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
---
.../src/mock/mock_event_details.ts | 46 +-
.../common/utils/field_formatters.test.ts | 94 ---
.../common/utils/field_formatters.ts | 148 ----
.../common/utils/to_array.ts | 89 ---
.../shared/utils/threat_intelligence.tsx | 2 +-
.../helpers/format_response_object_values.ts | 4 +-
.../helpers/get_flattened_fields.ts | 2 +-
.../factory/hosts/all/helpers.ts | 2 +-
.../factory/hosts/details/helpers.ts | 2 +-
.../factory/users/authentications/helpers.ts | 2 +-
x-pack/plugins/timelines/common/index.ts | 2 +
.../common/utils/field_formatters.test.ts | 35 +-
.../common/utils/field_formatters.ts | 228 +++---
.../plugins/timelines/common/utils/index.ts | 9 +
.../timelines/common/utils/to_array.ts | 106 +--
.../search_strategy/timeline/eql/helpers.ts | 69 +-
.../timeline/factory/events/all/index.ts | 14 +-
.../timeline/factory/events/details/index.ts | 11 +-
.../helpers/format_timeline_data.test.ts | 727 +++++++++---------
.../factory/helpers/format_timeline_data.ts | 208 ++---
20 files changed, 740 insertions(+), 1060 deletions(-)
delete mode 100644 x-pack/plugins/security_solution/common/utils/field_formatters.test.ts
delete mode 100644 x-pack/plugins/security_solution/common/utils/field_formatters.ts
delete mode 100644 x-pack/plugins/security_solution/common/utils/to_array.ts
create mode 100644 x-pack/plugins/timelines/common/utils/index.ts
diff --git a/packages/kbn-securitysolution-t-grid/src/mock/mock_event_details.ts b/packages/kbn-securitysolution-t-grid/src/mock/mock_event_details.ts
index dc2497bb19cec..5152132cda4bb 100644
--- a/packages/kbn-securitysolution-t-grid/src/mock/mock_event_details.ts
+++ b/packages/kbn-securitysolution-t-grid/src/mock/mock_event_details.ts
@@ -291,6 +291,29 @@ export const eventDetailsFormattedFields = [
originalValue: [`{"lon":118.7778,"lat":32.0617}`],
values: [`{"lon":118.7778,"lat":32.0617}`],
},
+ {
+ category: 'threat',
+ field: 'threat.enrichments',
+ isObjectArray: true,
+ originalValue: [
+ '{"matched.field":["matched_field","other_matched_field"],"indicator.first_seen":["2021-02-22T17:29:25.195Z"],"indicator.provider":["yourself"],"indicator.type":["custom"],"matched.atomic":["matched_atomic"],"lazer":[{"great.field":["grrrrr"]},{"great.field":["grrrrr_2"]}]}',
+ '{"matched.field":["matched_field_2"],"indicator.first_seen":["2021-02-22T17:29:25.195Z"],"indicator.provider":["other_you"],"indicator.type":["custom"],"matched.atomic":["matched_atomic_2"],"lazer":[{"great.field":[{"wowoe":[{"fooooo":["grrrrr"]}],"astring":"cool","aNumber":1,"neat":true}]}]}',
+ '{"matched.field":["host.name"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["FFEtSYIBZ61VHL7LvV2j"],"matched.atomic":["MacBook-Pro-de-Gloria.local"]}',
+ '{"matched.field":["host.hostname"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["E1EtSYIBZ61VHL7Ltl3m"],"matched.atomic":["MacBook-Pro-de-Gloria.local"]}',
+ '{"matched.field":["host.architecture"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["E1EtSYIBZ61VHL7Ltl3m"],"matched.atomic":["x86_64"]}',
+ '{"matched.field":["host.name"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["E1EtSYIBZ61VHL7Ltl3m"],"matched.atomic":["MacBook-Pro-de-Gloria.local"]}',
+ '{"matched.field":["host.hostname"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["CFErSYIBZ61VHL7LIV1N"],"matched.atomic":["MacBook-Pro-de-Gloria.local"]}',
+ ],
+ values: [
+ '{"matched.field":["matched_field","other_matched_field"],"indicator.first_seen":["2021-02-22T17:29:25.195Z"],"indicator.provider":["yourself"],"indicator.type":["custom"],"matched.atomic":["matched_atomic"],"lazer":[{"great.field":["grrrrr"]},{"great.field":["grrrrr_2"]}]}',
+ '{"matched.field":["matched_field_2"],"indicator.first_seen":["2021-02-22T17:29:25.195Z"],"indicator.provider":["other_you"],"indicator.type":["custom"],"matched.atomic":["matched_atomic_2"],"lazer":[{"great.field":[{"wowoe":[{"fooooo":["grrrrr"]}],"astring":"cool","aNumber":1,"neat":true}]}]}',
+ '{"matched.field":["host.name"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["FFEtSYIBZ61VHL7LvV2j"],"matched.atomic":["MacBook-Pro-de-Gloria.local"]}',
+ '{"matched.field":["host.hostname"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["E1EtSYIBZ61VHL7Ltl3m"],"matched.atomic":["MacBook-Pro-de-Gloria.local"]}',
+ '{"matched.field":["host.architecture"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["E1EtSYIBZ61VHL7Ltl3m"],"matched.atomic":["x86_64"]}',
+ '{"matched.field":["host.name"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["E1EtSYIBZ61VHL7Ltl3m"],"matched.atomic":["MacBook-Pro-de-Gloria.local"]}',
+ '{"matched.field":["host.hostname"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["CFErSYIBZ61VHL7LIV1N"],"matched.atomic":["MacBook-Pro-de-Gloria.local"]}',
+ ],
+ },
{
category: 'threat',
field: 'threat.enrichments.matched.field',
@@ -376,27 +399,4 @@ export const eventDetailsFormattedFields = [
originalValue: ['FFEtSYIBZ61VHL7LvV2j', 'E1EtSYIBZ61VHL7Ltl3m', 'CFErSYIBZ61VHL7LIV1N'],
values: ['FFEtSYIBZ61VHL7LvV2j', 'E1EtSYIBZ61VHL7Ltl3m', 'CFErSYIBZ61VHL7LIV1N'],
},
- {
- category: 'threat',
- field: 'threat.enrichments',
- isObjectArray: true,
- originalValue: [
- '{"matched.field":["matched_field","other_matched_field"],"indicator.first_seen":["2021-02-22T17:29:25.195Z"],"indicator.provider":["yourself"],"indicator.type":["custom"],"matched.atomic":["matched_atomic"],"lazer":[{"great.field":["grrrrr"]},{"great.field":["grrrrr_2"]}]}',
- '{"matched.field":["matched_field_2"],"indicator.first_seen":["2021-02-22T17:29:25.195Z"],"indicator.provider":["other_you"],"indicator.type":["custom"],"matched.atomic":["matched_atomic_2"],"lazer":[{"great.field":[{"wowoe":[{"fooooo":["grrrrr"]}],"astring":"cool","aNumber":1,"neat":true}]}]}',
- '{"matched.field":["host.name"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["FFEtSYIBZ61VHL7LvV2j"],"matched.atomic":["MacBook-Pro-de-Gloria.local"]}',
- '{"matched.field":["host.hostname"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["E1EtSYIBZ61VHL7Ltl3m"],"matched.atomic":["MacBook-Pro-de-Gloria.local"]}',
- '{"matched.field":["host.architecture"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["E1EtSYIBZ61VHL7Ltl3m"],"matched.atomic":["x86_64"]}',
- '{"matched.field":["host.name"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["E1EtSYIBZ61VHL7Ltl3m"],"matched.atomic":["MacBook-Pro-de-Gloria.local"]}',
- '{"matched.field":["host.hostname"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["CFErSYIBZ61VHL7LIV1N"],"matched.atomic":["MacBook-Pro-de-Gloria.local"]}',
- ],
- values: [
- '{"matched.field":["matched_field","other_matched_field"],"indicator.first_seen":["2021-02-22T17:29:25.195Z"],"indicator.provider":["yourself"],"indicator.type":["custom"],"matched.atomic":["matched_atomic"],"lazer":[{"great.field":["grrrrr"]},{"great.field":["grrrrr_2"]}]}',
- '{"matched.field":["matched_field_2"],"indicator.first_seen":["2021-02-22T17:29:25.195Z"],"indicator.provider":["other_you"],"indicator.type":["custom"],"matched.atomic":["matched_atomic_2"],"lazer":[{"great.field":[{"wowoe":[{"fooooo":["grrrrr"]}],"astring":"cool","aNumber":1,"neat":true}]}]}',
- '{"matched.field":["host.name"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["FFEtSYIBZ61VHL7LvV2j"],"matched.atomic":["MacBook-Pro-de-Gloria.local"]}',
- '{"matched.field":["host.hostname"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["E1EtSYIBZ61VHL7Ltl3m"],"matched.atomic":["MacBook-Pro-de-Gloria.local"]}',
- '{"matched.field":["host.architecture"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["E1EtSYIBZ61VHL7Ltl3m"],"matched.atomic":["x86_64"]}',
- '{"matched.field":["host.name"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["E1EtSYIBZ61VHL7Ltl3m"],"matched.atomic":["MacBook-Pro-de-Gloria.local"]}',
- '{"matched.field":["host.hostname"],"matched.index":["im"],"matched.type":["indicator_match_rule"],"matched.id":["CFErSYIBZ61VHL7LIV1N"],"matched.atomic":["MacBook-Pro-de-Gloria.local"]}',
- ],
- },
];
diff --git a/x-pack/plugins/security_solution/common/utils/field_formatters.test.ts b/x-pack/plugins/security_solution/common/utils/field_formatters.test.ts
deleted file mode 100644
index 33d0c226fc44e..0000000000000
--- a/x-pack/plugins/security_solution/common/utils/field_formatters.test.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import type { EventHit } from '../search_strategy';
-import { getDataFromFieldsHits, getDataSafety } from './field_formatters';
-import { eventDetailsFormattedFields, eventHit } from '@kbn/securitysolution-t-grid';
-
-describe('Events Details Helpers', () => {
- const fields: EventHit['fields'] = eventHit.fields;
- const resultFields = eventDetailsFormattedFields;
- describe('#getDataFromFieldsHits', () => {
- it('happy path', () => {
- const result = getDataFromFieldsHits(fields);
- expect(result).toEqual(resultFields);
- });
- it('lets get weird', () => {
- const whackFields = {
- 'crazy.pants': [
- {
- 'matched.field': ['matched_field'],
- first_seen: ['2021-02-22T17:29:25.195Z'],
- provider: ['yourself'],
- type: ['custom'],
- 'matched.atomic': ['matched_atomic'],
- lazer: [
- {
- 'great.field': ['grrrrr'],
- lazer: [
- {
- lazer: [
- {
- cool: true,
- lazer: [
- {
- lazer: [
- {
- lazer: [
- {
- lazer: [
- {
- whoa: false,
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- },
- {
- lazer: [
- {
- cool: false,
- },
- ],
- },
- ],
- },
- {
- 'great.field': ['grrrrr_2'],
- },
- ],
- },
- ],
- };
- const whackResultFields = [
- {
- category: 'crazy',
- field: 'crazy.pants',
- values: [
- '{"matched.field":["matched_field"],"first_seen":["2021-02-22T17:29:25.195Z"],"provider":["yourself"],"type":["custom"],"matched.atomic":["matched_atomic"],"lazer":[{"great.field":["grrrrr"],"lazer":[{"lazer":[{"cool":true,"lazer":[{"lazer":[{"lazer":[{"lazer":[{"whoa":false}]}]}]}]}]},{"lazer":[{"cool":false}]}]},{"great.field":["grrrrr_2"]}]}',
- ],
- originalValue: [
- '{"matched.field":["matched_field"],"first_seen":["2021-02-22T17:29:25.195Z"],"provider":["yourself"],"type":["custom"],"matched.atomic":["matched_atomic"],"lazer":[{"great.field":["grrrrr"],"lazer":[{"lazer":[{"cool":true,"lazer":[{"lazer":[{"lazer":[{"lazer":[{"whoa":false}]}]}]}]}]},{"lazer":[{"cool":false}]}]},{"great.field":["grrrrr_2"]}]}',
- ],
- isObjectArray: true,
- },
- ];
- const result = getDataFromFieldsHits(whackFields);
- expect(result).toEqual(whackResultFields);
- });
- });
- it('#getDataSafety', async () => {
- const result = await getDataSafety(getDataFromFieldsHits, fields);
- expect(result).toEqual(resultFields);
- });
-});
diff --git a/x-pack/plugins/security_solution/common/utils/field_formatters.ts b/x-pack/plugins/security_solution/common/utils/field_formatters.ts
deleted file mode 100644
index 1d8c05ec9ccf7..0000000000000
--- a/x-pack/plugins/security_solution/common/utils/field_formatters.ts
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { ecsFieldMap } from '@kbn/rule-registry-plugin/common/assets/field_maps/ecs_field_map';
-import { legacyExperimentalFieldMap } from '@kbn/alerts-as-data-utils';
-import { technicalRuleFieldMap } from '@kbn/rule-registry-plugin/common/assets/field_maps/technical_rule_field_map';
-import { isEmpty } from 'lodash/fp';
-import { ENRICHMENT_DESTINATION_PATH } from '../constants';
-
-import type { Fields, TimelineEventsDetailsItem } from '../search_strategy';
-import { toObjectArrayOfStrings, toStringArray } from './to_array';
-
-export const baseCategoryFields = ['@timestamp', 'labels', 'message', 'tags'];
-
-export const getFieldCategory = (field: string): string => {
- const fieldCategory = field.split('.')[0];
- if (!isEmpty(fieldCategory) && baseCategoryFields.includes(fieldCategory)) {
- return 'base';
- }
- return fieldCategory;
-};
-
-export const formatGeoLocation = (item: unknown[]) => {
- const itemGeo = item.length > 0 ? (item[0] as { coordinates: number[] }) : null;
- if (itemGeo != null && !isEmpty(itemGeo.coordinates)) {
- try {
- return toStringArray({
- lon: itemGeo.coordinates[0],
- lat: itemGeo.coordinates[1],
- });
- } catch {
- return toStringArray(item);
- }
- }
- return toStringArray(item);
-};
-
-export const isGeoField = (field: string) =>
- field.includes('geo.location') || field.includes('geoip.location');
-
-export const isThreatEnrichmentFieldOrSubfield = (field: string, prependField?: string) =>
- prependField?.includes(ENRICHMENT_DESTINATION_PATH) || field === ENRICHMENT_DESTINATION_PATH;
-
-export const getDataFromFieldsHits = (
- fields: Fields,
- prependField?: string,
- prependFieldCategory?: string
-): TimelineEventsDetailsItem[] =>
- Object.keys(fields).reduce((accumulator, field) => {
- const item: unknown[] = fields[field];
-
- const fieldCategory =
- prependFieldCategory != null ? prependFieldCategory : getFieldCategory(field);
- if (isGeoField(field)) {
- return [
- ...accumulator,
- {
- category: fieldCategory,
- field,
- values: formatGeoLocation(item),
- originalValue: formatGeoLocation(item),
- isObjectArray: true, // important for UI
- },
- ];
- }
-
- const objArrStr = toObjectArrayOfStrings(item);
- const strArr = objArrStr.map(({ str }) => str);
- const isObjectArray = objArrStr.some((o) => o.isObjectArray);
- const dotField = prependField ? `${prependField}.${field}` : field;
-
- // return simple field value (non-esc object, non-array)
- if (
- !isObjectArray ||
- Object.keys({ ...ecsFieldMap, ...technicalRuleFieldMap, ...legacyExperimentalFieldMap }).find(
- (ecsField) => ecsField === field
- ) === undefined
- ) {
- return [
- ...accumulator,
- {
- category: fieldCategory,
- field: dotField,
- values: strArr,
- originalValue: strArr,
- isObjectArray,
- },
- ];
- }
-
- const threatEnrichmentObject = isThreatEnrichmentFieldOrSubfield(field, prependField)
- ? [
- {
- category: fieldCategory,
- field: dotField,
- values: strArr,
- originalValue: strArr,
- isObjectArray,
- },
- ]
- : [];
-
- // format nested fields
- const nestedFields = Array.isArray(item)
- ? item
- .reduce((acc, curr) => {
- acc.push(getDataFromFieldsHits(curr as Fields, dotField, fieldCategory));
- return acc;
- }, [])
- .flat()
- : getDataFromFieldsHits(item, prependField, fieldCategory);
-
- // combine duplicate fields
- const flat: Record = [
- ...accumulator,
- ...nestedFields,
- ...threatEnrichmentObject,
- ].reduce(
- (acc, f) => ({
- ...acc,
- // acc/flat is hashmap to determine if we already have the field or not without an array iteration
- // its converted back to array in return with Object.values
- ...(acc[f.field] != null
- ? {
- [f.field]: {
- ...f,
- originalValue: acc[f.field].originalValue.includes(f.originalValue[0])
- ? acc[f.field].originalValue
- : [...acc[f.field].originalValue, ...f.originalValue],
- values: acc[f.field].values?.includes(f.values?.[0] || '')
- ? acc[f.field].values
- : [...(acc[f.field].values || []), ...(f.values || [])],
- },
- }
- : { [f.field]: f }),
- }),
- {} as Record
- );
-
- return Object.values(flat);
- }, []);
-
-export const getDataSafety = (fn: (args: A) => T, args: A): Promise =>
- new Promise((resolve) => setTimeout(() => resolve(fn(args))));
diff --git a/x-pack/plugins/security_solution/common/utils/to_array.ts b/x-pack/plugins/security_solution/common/utils/to_array.ts
deleted file mode 100644
index b6945708ff0db..0000000000000
--- a/x-pack/plugins/security_solution/common/utils/to_array.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-export const toArray = (value: T | T[] | null | undefined): T[] =>
- Array.isArray(value) ? value : value == null ? [] : [value];
-
-export const toStringArray = (value: T | T[] | null): string[] => {
- if (Array.isArray(value)) {
- return value.reduce((acc, v) => {
- if (v != null) {
- switch (typeof v) {
- case 'number':
- case 'boolean':
- return [...acc, v.toString()];
- case 'object':
- try {
- return [...acc, JSON.stringify(v)];
- } catch {
- return [...acc, 'Invalid Object'];
- }
- case 'string':
- return [...acc, v];
- default:
- return [...acc, `${v}`];
- }
- }
- return acc;
- }, []);
- } else if (value == null) {
- return [];
- } else if (!Array.isArray(value) && typeof value === 'object') {
- try {
- return [JSON.stringify(value)];
- } catch {
- return ['Invalid Object'];
- }
- } else {
- return [`${value}`];
- }
-};
-
-export const toObjectArrayOfStrings = (
- value: T | T[] | null
-): Array<{
- str: string;
- isObjectArray?: boolean;
-}> => {
- if (Array.isArray(value)) {
- return value.reduce<
- Array<{
- str: string;
- isObjectArray?: boolean;
- }>
- >((acc, v) => {
- if (v != null) {
- switch (typeof v) {
- case 'number':
- case 'boolean':
- return [...acc, { str: v.toString() }];
- case 'object':
- try {
- return [...acc, { str: JSON.stringify(v), isObjectArray: true }]; // need to track when string is not a simple value
- } catch {
- return [...acc, { str: 'Invalid Object' }];
- }
- case 'string':
- return [...acc, { str: v }];
- default:
- return [...acc, { str: `${v}` }];
- }
- }
- return acc;
- }, []);
- } else if (value == null) {
- return [];
- } else if (!Array.isArray(value) && typeof value === 'object') {
- try {
- return [{ str: JSON.stringify(value), isObjectArray: true }];
- } catch {
- return [{ str: 'Invalid Object' }];
- }
- } else {
- return [{ str: `${value}` }];
- }
-};
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/shared/utils/threat_intelligence.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/shared/utils/threat_intelligence.tsx
index 2f5bd6510430b..fefacf3e7fc14 100644
--- a/x-pack/plugins/security_solution/public/flyout/document_details/shared/utils/threat_intelligence.tsx
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/shared/utils/threat_intelligence.tsx
@@ -7,11 +7,11 @@
import { groupBy, isObject } from 'lodash';
import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common';
+import { getDataFromFieldsHits } from '@kbn/timelines-plugin/common';
import { i18n } from '@kbn/i18n';
import type { ThreatDetailsRow } from '../../left/components/threat_details_view_enrichment_accordion';
import type { CtiEnrichment, EventFields } from '../../../../../common/search_strategy';
import { isValidEventField } from '../../../../../common/search_strategy';
-import { getDataFromFieldsHits } from '../../../../../common/utils/field_formatters';
import {
DEFAULT_INDICATOR_SOURCE_PATH,
ENRICHMENT_DESTINATION_PATH,
diff --git a/x-pack/plugins/security_solution/server/search_strategy/helpers/format_response_object_values.ts b/x-pack/plugins/security_solution/server/search_strategy/helpers/format_response_object_values.ts
index f44ad77e67929..d80be5f4a421b 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/helpers/format_response_object_values.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/helpers/format_response_object_values.ts
@@ -7,9 +7,7 @@
import { mapValues, isObject, isArray } from 'lodash/fp';
import { set } from '@kbn/safer-lodash-set';
-
-import { toArray } from '../../../common/utils/to_array';
-import { isGeoField } from '../../../common/utils/field_formatters';
+import { toArray, isGeoField } from '@kbn/timelines-plugin/common';
export const mapObjectValuesToStringArray = (object: object): object =>
mapValues((o) => {
diff --git a/x-pack/plugins/security_solution/server/search_strategy/helpers/get_flattened_fields.ts b/x-pack/plugins/security_solution/server/search_strategy/helpers/get_flattened_fields.ts
index f40edfc5914df..baed5b3c35605 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/helpers/get_flattened_fields.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/helpers/get_flattened_fields.ts
@@ -6,7 +6,7 @@
*/
import { set } from '@kbn/safer-lodash-set';
import { get, isEmpty } from 'lodash/fp';
-import { toObjectArrayOfStrings } from '../../../common/utils/to_array';
+import { toObjectArrayOfStrings } from '@kbn/timelines-plugin/common';
export function getFlattenedFields(
fields: string[],
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/helpers.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/helpers.ts
index 8707f10ed01cb..61ab1c5bca583 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/helpers.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/helpers.ts
@@ -8,12 +8,12 @@
import { set } from '@kbn/safer-lodash-set/fp';
import { get, has } from 'lodash/fp';
import { hostFieldsMap } from '@kbn/securitysolution-ecs';
+import { toObjectArrayOfStrings } from '@kbn/timelines-plugin/common';
import type {
HostAggEsItem,
HostsEdges,
HostValue,
} from '../../../../../../common/search_strategy/security_solution/hosts';
-import { toObjectArrayOfStrings } from '../../../../../../common/utils/to_array';
export const HOSTS_FIELDS: readonly string[] = [
'_id',
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/helpers.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/helpers.ts
index 94d45b2b63e0e..cc1a084f6b5a7 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/helpers.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/helpers.ts
@@ -13,6 +13,7 @@ import type {
SavedObjectsClientContract,
} from '@kbn/core/server';
import { hostFieldsMap } from '@kbn/securitysolution-ecs';
+import { toObjectArrayOfStrings } from '@kbn/timelines-plugin/common';
import { Direction } from '../../../../../../common/search_strategy/common';
import type {
AggregationRequest,
@@ -22,7 +23,6 @@ import type {
HostItem,
HostValue,
} from '../../../../../../common/search_strategy/security_solution/hosts';
-import { toObjectArrayOfStrings } from '../../../../../../common/utils/to_array';
import type { EndpointAppContext } from '../../../../../endpoint/types';
import { getPendingActionsSummary } from '../../../../../endpoint/services';
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/authentications/helpers.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/authentications/helpers.ts
index 06452c915009c..b92b67f244ebe 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/authentications/helpers.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/authentications/helpers.ts
@@ -8,7 +8,7 @@
import { get, getOr, isEmpty } from 'lodash/fp';
import { set } from '@kbn/safer-lodash-set/fp';
import { sourceFieldsMap, hostFieldsMap } from '@kbn/securitysolution-ecs';
-import { toObjectArrayOfStrings } from '../../../../../../common/utils/to_array';
+import { toObjectArrayOfStrings } from '@kbn/timelines-plugin/common';
import type {
AuthenticationsEdges,
AuthenticationHit,
diff --git a/x-pack/plugins/timelines/common/index.ts b/x-pack/plugins/timelines/common/index.ts
index 0a96a22fb2679..3e335a7edd278 100644
--- a/x-pack/plugins/timelines/common/index.ts
+++ b/x-pack/plugins/timelines/common/index.ts
@@ -67,3 +67,5 @@ export type {
} from './search_strategy';
export { Direction, EntityType, EMPTY_BROWSER_FIELDS } from './search_strategy';
+
+export { getDataFromFieldsHits, toArray, isGeoField, toObjectArrayOfStrings } from './utils';
diff --git a/x-pack/plugins/timelines/common/utils/field_formatters.test.ts b/x-pack/plugins/timelines/common/utils/field_formatters.test.ts
index 43babd374d991..46eb77c8f7f32 100644
--- a/x-pack/plugins/timelines/common/utils/field_formatters.test.ts
+++ b/x-pack/plugins/timelines/common/utils/field_formatters.test.ts
@@ -7,7 +7,7 @@
import { eventDetailsFormattedFields, eventHit } from '@kbn/securitysolution-t-grid';
import { EventHit } from '../search_strategy';
-import { getDataFromFieldsHits, getDataSafety } from './field_formatters';
+import { getDataFromFieldsHits } from './field_formatters';
describe('Events Details Helpers', () => {
const fields: EventHit['fields'] = eventHit.fields;
@@ -84,7 +84,7 @@ describe('Events Details Helpers', () => {
},
];
const result = getDataFromFieldsHits(whackFields);
- expect(result).toEqual(whackResultFields);
+ expect(result).toMatchObject(whackResultFields);
});
it('flattens alert parameters', () => {
const ruleParameterFields = {
@@ -191,7 +191,7 @@ describe('Events Details Helpers', () => {
];
const result = getDataFromFieldsHits(ruleParameterFields);
- expect(result).toEqual(ruleParametersResultFields);
+ expect(result).toMatchObject(ruleParametersResultFields);
});
it('get data from threat enrichments', () => {
@@ -546,6 +546,17 @@ describe('Events Details Helpers', () => {
originalValue: ['495ad7a7-316e-4544-8a0f-9c098daee76e'],
values: ['495ad7a7-316e-4544-8a0f-9c098daee76e'],
},
+ {
+ category: 'threat',
+ field: 'threat.enrichments',
+ isObjectArray: true,
+ originalValue: [
+ '{"matched.field":["myhash.mysha256"],"matched.index":["logs-ti_abusech.malware"],"matched.type":["indicator_match_rule"],"feed.name":["AbuseCH malware"],"matched.atomic":["a04ac6d98ad989312783d4fe3456c53730b212c79a426fb215708b6c6daa3de3"]}',
+ ],
+ values: [
+ '{"matched.field":["myhash.mysha256"],"matched.index":["logs-ti_abusech.malware"],"matched.type":["indicator_match_rule"],"feed.name":["AbuseCH malware"],"matched.atomic":["a04ac6d98ad989312783d4fe3456c53730b212c79a426fb215708b6c6daa3de3"]}',
+ ],
+ },
{
category: 'threat',
field: 'threat.enrichments.matched.field',
@@ -581,25 +592,9 @@ describe('Events Details Helpers', () => {
originalValue: ['a04ac6d98ad989312783d4fe3456c53730b212c79a426fb215708b6c6daa3de3'],
values: ['a04ac6d98ad989312783d4fe3456c53730b212c79a426fb215708b6c6daa3de3'],
},
- {
- category: 'threat',
- field: 'threat.enrichments',
- isObjectArray: true,
- originalValue: [
- '{"matched.field":["myhash.mysha256"],"matched.index":["logs-ti_abusech.malware"],"matched.type":["indicator_match_rule"],"feed.name":["AbuseCH malware"],"matched.atomic":["a04ac6d98ad989312783d4fe3456c53730b212c79a426fb215708b6c6daa3de3"]}',
- ],
- values: [
- '{"matched.field":["myhash.mysha256"],"matched.index":["logs-ti_abusech.malware"],"matched.type":["indicator_match_rule"],"feed.name":["AbuseCH malware"],"matched.atomic":["a04ac6d98ad989312783d4fe3456c53730b212c79a426fb215708b6c6daa3de3"]}',
- ],
- },
];
const result = getDataFromFieldsHits(data);
- expect(result).toEqual(ruleParametersResultFields);
+ expect(result).toMatchObject(ruleParametersResultFields);
});
});
-
- it('#getDataSafety', async () => {
- const result = await getDataSafety(getDataFromFieldsHits, fields);
- expect(result).toEqual(resultFields);
- });
});
diff --git a/x-pack/plugins/timelines/common/utils/field_formatters.ts b/x-pack/plugins/timelines/common/utils/field_formatters.ts
index c9292987f59b2..2e3785633bc3f 100644
--- a/x-pack/plugins/timelines/common/utils/field_formatters.ts
+++ b/x-pack/plugins/timelines/common/utils/field_formatters.ts
@@ -8,9 +8,15 @@
import { isEmpty } from 'lodash/fp';
import { ALERT_RULE_PARAMETERS } from '@kbn/rule-data-utils';
-import { ecsFieldMap } from '@kbn/rule-registry-plugin/common/assets/field_maps/ecs_field_map';
-import { technicalRuleFieldMap } from '@kbn/rule-registry-plugin/common/assets/field_maps/technical_rule_field_map';
-import { legacyExperimentalFieldMap } from '@kbn/alerts-as-data-utils';
+import {
+ ecsFieldMap,
+ EcsFieldMap,
+} from '@kbn/rule-registry-plugin/common/assets/field_maps/ecs_field_map';
+import {
+ technicalRuleFieldMap,
+ TechnicalRuleFieldMap,
+} from '@kbn/rule-registry-plugin/common/assets/field_maps/technical_rule_field_map';
+import { legacyExperimentalFieldMap, ExperimentalRuleFieldMap } from '@kbn/alerts-as-data-utils';
import { Fields, TimelineEventsDetailsItem } from '../search_strategy';
import { toObjectArrayOfStrings, toStringArray } from './to_array';
import { ENRICHMENT_DESTINATION_PATH } from '../constants';
@@ -51,117 +57,141 @@ export const isRuleParametersFieldOrSubfield = (field: string, prependField?: st
export const isThreatEnrichmentFieldOrSubfield = (field: string, prependField?: string) =>
prependField?.includes(ENRICHMENT_DESTINATION_PATH) || field === ENRICHMENT_DESTINATION_PATH;
+// Helper functions
+const createFieldItem = (
+ fieldCategory: string,
+ field: string,
+ values: string[],
+ isObjectArray: boolean
+): TimelineEventsDetailsItem => ({
+ category: fieldCategory,
+ field,
+ values,
+ originalValue: values,
+ isObjectArray,
+});
+
+const processGeoField = (
+ field: string,
+ item: unknown[],
+ fieldCategory: string
+): TimelineEventsDetailsItem => {
+ const formattedLocation = formatGeoLocation(item);
+ return createFieldItem(fieldCategory, field, formattedLocation, true);
+};
+
+const processSimpleField = (
+ dotField: string,
+ strArr: string[],
+ isObjectArray: boolean,
+ fieldCategory: string
+): TimelineEventsDetailsItem => createFieldItem(fieldCategory, dotField, strArr, isObjectArray);
+
+const processNestedFields = (
+ item: unknown,
+ dotField: string,
+ fieldCategory: string,
+ prependDotField: boolean
+): TimelineEventsDetailsItem[] => {
+ if (Array.isArray(item)) {
+ return item.flatMap((curr) =>
+ getDataFromFieldsHits(curr as Fields, prependDotField ? dotField : undefined, fieldCategory)
+ );
+ }
+
+ return getDataFromFieldsHits(
+ item as Fields,
+ prependDotField ? dotField : undefined,
+ fieldCategory
+ );
+};
+
+type DisjointFieldNames = 'ecs.version' | 'event.action' | 'event.kind' | 'event.original';
+
+// Memoized field maps
+const fieldMaps: EcsFieldMap &
+ Omit &
+ ExperimentalRuleFieldMap = {
+ ...technicalRuleFieldMap,
+ ...ecsFieldMap,
+ ...legacyExperimentalFieldMap,
+};
+
export const getDataFromFieldsHits = (
fields: Fields,
prependField?: string,
prependFieldCategory?: string
-): TimelineEventsDetailsItem[] =>
- Object.keys(fields).reduce((accumulator, field) => {
+): TimelineEventsDetailsItem[] => {
+ const resultMap = new Map();
+ const fieldNames = Object.keys(fields);
+ for (let i = 0; i < fieldNames.length; i++) {
+ const field = fieldNames[i];
const item: unknown[] = fields[field];
- const fieldCategory =
- prependFieldCategory != null ? prependFieldCategory : getFieldCategory(field);
+ const fieldCategory = prependFieldCategory ?? getFieldCategory(field);
+ const dotField = prependField ? `${prependField}.${field}` : field;
+
+ // Handle geo fields
if (isGeoField(field)) {
- return [
- ...accumulator,
- {
- category: fieldCategory,
- field,
- values: formatGeoLocation(item),
- originalValue: formatGeoLocation(item),
- isObjectArray: true, // important for UI
- },
- ];
+ const geoItem = processGeoField(field, item, fieldCategory);
+ resultMap.set(field, geoItem);
+ // eslint-disable-next-line no-continue
+ continue;
}
+
const objArrStr = toObjectArrayOfStrings(item);
const strArr = objArrStr.map(({ str }) => str);
const isObjectArray = objArrStr.some((o) => o.isObjectArray);
- const dotField = prependField ? `${prependField}.${field}` : field;
- // return simple field value (non-ecs object, non-array)
- if (
- !isObjectArray ||
- (Object.keys({
- ...ecsFieldMap,
- ...technicalRuleFieldMap,
- ...legacyExperimentalFieldMap,
- }).find((ecsField) => ecsField === field) === undefined &&
- !isRuleParametersFieldOrSubfield(field, prependField))
- ) {
- return [
- ...accumulator,
- {
- category: fieldCategory,
- field: dotField,
- values: strArr,
- originalValue: strArr,
- isObjectArray,
- },
- ];
+ const isEcsField = fieldMaps[field as keyof typeof fieldMaps] !== undefined;
+ const isRuleParameters = isRuleParametersFieldOrSubfield(field, prependField);
+
+ // Handle simple fields
+ if (!isObjectArray || (!isEcsField && !isRuleParameters)) {
+ const simpleItem = processSimpleField(dotField, strArr, isObjectArray, fieldCategory);
+ resultMap.set(dotField, simpleItem);
+ // eslint-disable-next-line no-continue
+ continue;
}
- const threatEnrichmentObject = isThreatEnrichmentFieldOrSubfield(field, prependField)
- ? [
- {
- category: fieldCategory,
- field: dotField,
- values: strArr,
- originalValue: strArr,
- isObjectArray,
- },
- ]
- : [];
-
- // format nested fields
- let nestedFields: TimelineEventsDetailsItem[] = [];
- if (isRuleParametersFieldOrSubfield(field, prependField)) {
- nestedFields = Array.isArray(item)
- ? item
- .reduce((acc, curr) => {
- acc.push(getDataFromFieldsHits(curr as Fields, dotField, fieldCategory));
- return acc;
- }, [])
- .flat()
- : getDataFromFieldsHits(item, dotField, fieldCategory);
- } else {
- nestedFields = Array.isArray(item)
- ? item
- .reduce((acc, curr) => {
- acc.push(getDataFromFieldsHits(curr as Fields, dotField, fieldCategory));
- return acc;
- }, [])
- .flat()
- : getDataFromFieldsHits(item, prependField, fieldCategory);
+ // Handle threat enrichment
+ if (isThreatEnrichmentFieldOrSubfield(field, prependField)) {
+ const enrichmentItem = createFieldItem(fieldCategory, dotField, strArr, isObjectArray);
+ resultMap.set(dotField, enrichmentItem);
}
- // combine duplicate fields
- const flat: Record = [
- ...accumulator,
- ...nestedFields,
- ...threatEnrichmentObject,
- ].reduce(
- (acc, f) => ({
- ...acc,
- // acc/flat is hashmap to determine if we already have the field or not without an array iteration
- // its converted back to array in return with Object.values
- ...(acc[f.field] != null
- ? {
- [f.field]: {
- ...f,
- originalValue: acc[f.field].originalValue.includes(f.originalValue[0])
- ? acc[f.field].originalValue
- : [...acc[f.field].originalValue, ...f.originalValue],
- values: acc[f.field].values?.includes(f.values?.[0] || '')
- ? acc[f.field].values
- : [...(acc[f.field].values || []), ...(f.values || [])],
- },
- }
- : { [f.field]: f }),
- }),
- {} as Record
+ // Process nested fields
+ const nestedFields = processNestedFields(
+ item,
+ dotField,
+ fieldCategory,
+ isRuleParameters || isThreatEnrichmentFieldOrSubfield(field, prependField)
);
+ // Merge results
+ for (const nestedItem of nestedFields) {
+ const existing = resultMap.get(nestedItem.field);
+
+ if (!existing) {
+ resultMap.set(nestedItem.field, nestedItem);
+ // eslint-disable-next-line no-continue
+ continue;
+ }
- return Object.values(flat);
- }, []);
+ // Merge values and originalValue arrays
+ const mergedValues = existing.values?.includes(nestedItem.values?.[0] || '')
+ ? existing.values
+ : [...(existing.values || []), ...(nestedItem.values || [])];
-export const getDataSafety = (fn: (args: A) => T, args: A): Promise =>
- new Promise((resolve) => setTimeout(() => resolve(fn(args))));
+ const mergedOriginal = existing.originalValue.includes(nestedItem.originalValue[0])
+ ? existing.originalValue
+ : [...existing.originalValue, ...nestedItem.originalValue];
+
+ resultMap.set(nestedItem.field, {
+ ...nestedItem,
+ values: mergedValues,
+ originalValue: mergedOriginal,
+ });
+ }
+ }
+
+ return Array.from(resultMap.values());
+};
diff --git a/x-pack/plugins/timelines/common/utils/index.ts b/x-pack/plugins/timelines/common/utils/index.ts
new file mode 100644
index 0000000000000..e4b7eefec454f
--- /dev/null
+++ b/x-pack/plugins/timelines/common/utils/index.ts
@@ -0,0 +1,9 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+export { getDataFromFieldsHits, isGeoField } from './field_formatters';
+export { toArray, toObjectArrayOfStrings } from './to_array';
diff --git a/x-pack/plugins/timelines/common/utils/to_array.ts b/x-pack/plugins/timelines/common/utils/to_array.ts
index fbb2b8d48a250..d13eb0578008b 100644
--- a/x-pack/plugins/timelines/common/utils/to_array.ts
+++ b/x-pack/plugins/timelines/common/utils/to_array.ts
@@ -5,83 +5,55 @@
* 2.0.
*/
-export const toArray = (value: T | T[] | null): T[] =>
- Array.isArray(value) ? value : value == null ? [] : [value];
-export const toStringArray = (value: T | T[] | null): string[] => {
- if (Array.isArray(value)) {
- return value.reduce((acc, v) => {
- if (v != null) {
- switch (typeof v) {
- case 'number':
- case 'boolean':
- return [...acc, v.toString()];
- case 'object':
- try {
- return [...acc, JSON.stringify(v)];
- } catch {
- return [...acc, 'Invalid Object'];
- }
- case 'string':
- return [...acc, v];
- default:
- return [...acc, `${v}`];
- }
+export const toArray = (value: T | T[] | null | undefined): T[] =>
+ value == null ? [] : Array.isArray(value) ? value : [value];
+
+export const toStringArray = (value: T | T[] | null): string[] => {
+ if (value == null) return [];
+
+ const arr = Array.isArray(value) ? value : [value];
+ return arr.reduce((acc, v) => {
+ if (v == null) return acc;
+
+ if (typeof v === 'object') {
+ try {
+ acc.push(JSON.stringify(v));
+ } catch {
+ acc.push('Invalid Object');
}
return acc;
- }, []);
- } else if (value == null) {
- return [];
- } else if (!Array.isArray(value) && typeof value === 'object') {
- try {
- return [JSON.stringify(value)];
- } catch {
- return ['Invalid Object'];
}
- } else {
- return [`${value}`];
- }
+
+ acc.push(String(v));
+ return acc;
+ }, []);
};
-export const toObjectArrayOfStrings = (
+
+export const toObjectArrayOfStrings = (
value: T | T[] | null
): Array<{
str: string;
isObjectArray?: boolean;
}> => {
- if (Array.isArray(value)) {
- return value.reduce<
- Array<{
- str: string;
- isObjectArray?: boolean;
- }>
- >((acc, v) => {
- if (v != null) {
- switch (typeof v) {
- case 'number':
- case 'boolean':
- return [...acc, { str: v.toString() }];
- case 'object':
- try {
- return [...acc, { str: JSON.stringify(v), isObjectArray: true }]; // need to track when string is not a simple value
- } catch {
- return [...acc, { str: 'Invalid Object' }];
- }
- case 'string':
- return [...acc, { str: v }];
- default:
- return [...acc, { str: `${v}` }];
- }
+ if (value == null) return [];
+
+ const arr = Array.isArray(value) ? value : [value];
+ return arr.reduce>((acc, v) => {
+ if (v == null) return acc;
+
+ if (typeof v === 'object') {
+ try {
+ acc.push({
+ str: JSON.stringify(v),
+ isObjectArray: true,
+ });
+ } catch {
+ acc.push({ str: 'Invalid Object' });
}
return acc;
- }, []);
- } else if (value == null) {
- return [];
- } else if (!Array.isArray(value) && typeof value === 'object') {
- try {
- return [{ str: JSON.stringify(value), isObjectArray: true }];
- } catch {
- return [{ str: 'Invalid Object' }];
}
- } else {
- return [{ str: `${value}` }];
- }
+
+ acc.push({ str: String(v) });
+ return acc;
+ }, []);
};
diff --git a/x-pack/plugins/timelines/server/search_strategy/timeline/eql/helpers.ts b/x-pack/plugins/timelines/server/search_strategy/timeline/eql/helpers.ts
index 2b4f562954df1..645f6daa5727d 100644
--- a/x-pack/plugins/timelines/server/search_strategy/timeline/eql/helpers.ts
+++ b/x-pack/plugins/timelines/server/search_strategy/timeline/eql/helpers.ts
@@ -17,7 +17,6 @@ import {
} from '../../../../common/search_strategy';
import { TimelineEqlResponse } from '../../../../common/search_strategy/timeline/events/eql';
import { inspectStringifyObject } from '../../../utils/build_query';
-import { TIMELINE_EVENTS_FIELDS } from '../factory/helpers/constants';
import { formatTimelineData } from '../factory/helpers/format_timeline_data';
export const buildEqlDsl = (options: TimelineEqlRequestOptions): Record => {
@@ -68,38 +67,38 @@ export const buildEqlDsl = (options: TimelineEqlRequestOptions): Record>, fieldRequested: string[]) =>
- sequences.reduce>(async (acc, sequence, sequenceIndex) => {
+const parseSequences = async (sequences: Array>, fieldRequested: string[]) => {
+ let result: TimelineEdges[] = [];
+
+ for (const [sequenceIndex, sequence] of sequences.entries()) {
const sequenceParentId = sequence.events[0]?._id ?? null;
- const data = await acc;
- const allData = await Promise.all(
- sequence.events.map(async (event, eventIndex) => {
- const item = await formatTimelineData(
- fieldRequested,
- TIMELINE_EVENTS_FIELDS,
- event as EventHit
- );
- return Promise.resolve({
- ...item,
- node: {
- ...item.node,
- ecs: {
- ...item.node.ecs,
- ...(sequenceParentId != null
- ? {
- eql: {
- parentId: sequenceParentId,
- sequenceNumber: `${sequenceIndex}-${eventIndex}`,
- },
- }
- : {}),
- },
- },
- });
- })
+ const formattedEvents = await formatTimelineData(
+ sequence.events as EventHit[],
+ fieldRequested,
+ false
);
- return Promise.resolve([...data, ...allData]);
- }, Promise.resolve([]));
+
+ const eventsWithEql = formattedEvents.map((item, eventIndex) => ({
+ ...item,
+ node: {
+ ...item.node,
+ ecs: {
+ ...item.node.ecs,
+ ...(sequenceParentId && {
+ eql: {
+ parentId: sequenceParentId,
+ sequenceNumber: `${sequenceIndex}-${eventIndex}`,
+ },
+ }),
+ },
+ },
+ }));
+
+ result = result.concat(eventsWithEql);
+ }
+
+ return result;
+};
export const parseEqlResponse = async (
options: TimelineEqlRequestOptions,
@@ -116,10 +115,10 @@ export const parseEqlResponse = async (
if (response.rawResponse.hits.sequences !== undefined) {
edges = await parseSequences(response.rawResponse.hits.sequences, options.fieldRequested);
} else if (response.rawResponse.hits.events !== undefined) {
- edges = await Promise.all(
- response.rawResponse.hits.events.map(async (event) =>
- formatTimelineData(options.fieldRequested, TIMELINE_EVENTS_FIELDS, event as EventHit)
- )
+ edges = await formatTimelineData(
+ response.rawResponse.hits.events as EventHit[],
+ options.fieldRequested,
+ false
);
}
diff --git a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/all/index.ts b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/all/index.ts
index 4ed857b4885e3..2ee2b64162c13 100644
--- a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/all/index.ts
+++ b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/all/index.ts
@@ -14,13 +14,11 @@ import { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../../../../common/constants
import {
EventHit,
TimelineEventsAllStrategyResponse,
- TimelineEdges,
} from '../../../../../../common/search_strategy';
import { TimelineFactory } from '../../types';
import { buildTimelineEventsAllQuery } from './query.events_all.dsl';
import { inspectStringifyObject } from '../../../../../utils/build_query';
import { formatTimelineData } from '../../helpers/format_timeline_data';
-import { TIMELINE_EVENTS_FIELDS } from '../../helpers/constants';
export const timelineEventsAll: TimelineFactory = {
buildDsl: ({ authFilter, ...options }) => {
@@ -54,14 +52,10 @@ export const timelineEventsAll: TimelineFactory = {
fieldRequested = [...new Set(fieldsReturned)];
}
- const edges: TimelineEdges[] = await Promise.all(
- hits.map((hit) =>
- formatTimelineData(
- fieldRequested,
- options.excludeEcsData ? [] : TIMELINE_EVENTS_FIELDS,
- hit as EventHit
- )
- )
+ const edges = await formatTimelineData(
+ hits as EventHit[],
+ fieldRequested,
+ options.excludeEcsData ?? false
);
const consumers = producerBuckets.reduce(
diff --git a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/details/index.ts b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/details/index.ts
index 46edcf926d061..fcb90b73c241e 100644
--- a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/details/index.ts
+++ b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/details/index.ts
@@ -12,15 +12,11 @@ import { TimelineEventsQueries } from '../../../../../../common/api/search_strat
import {
EventHit,
TimelineEventsDetailsStrategyResponse,
- TimelineEventsDetailsItem,
} from '../../../../../../common/search_strategy';
import { inspectStringifyObject } from '../../../../../utils/build_query';
import { TimelineFactory } from '../../types';
import { buildTimelineDetailsQuery } from './query.events_details.dsl';
-import {
- getDataFromFieldsHits,
- getDataSafety,
-} from '../../../../../../common/utils/field_formatters';
+import { getDataFromFieldsHits } from '../../../../../../common/utils/field_formatters';
import { buildEcsObjects } from '../../helpers/build_ecs_objects';
export const timelineEventsDetails: TimelineFactory = {
@@ -57,10 +53,7 @@ export const timelineEventsDetails: TimelineFactory(
- getDataFromFieldsHits,
- merge(fields, hitsData)
- );
+ const fieldsData = getDataFromFieldsHits(merge(fields, hitsData));
const rawEventData = response.rawResponse.hits.hits[0];
const ecs = buildEcsObjects(rawEventData as EventHit);
diff --git a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/format_timeline_data.test.ts b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/format_timeline_data.test.ts
index 5117f8dc889ed..3e96494c88313 100644
--- a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/format_timeline_data.test.ts
+++ b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/format_timeline_data.test.ts
@@ -7,12 +7,12 @@
import { eventHit } from '@kbn/securitysolution-t-grid';
import { EventHit } from '../../../../../common/search_strategy';
-import { TIMELINE_EVENTS_FIELDS } from './constants';
import { formatTimelineData } from './format_timeline_data';
describe('formatTimelineData', () => {
it('should properly format the timeline data', async () => {
const res = await formatTimelineData(
+ [eventHit],
[
'@timestamp',
'host.name',
@@ -21,187 +21,188 @@ describe('formatTimelineData', () => {
'source.geo.location',
'threat.enrichments.matched.field',
],
- TIMELINE_EVENTS_FIELDS,
- eventHit
+ false
);
- expect(res).toEqual({
- cursor: {
- tiebreaker: 'beats-ci-immutable-ubuntu-1804-1605624279743236239',
- value: '1605624488922',
- },
- node: {
- _id: 'tkCt1nUBaEgqnrVSZ8R_',
- _index: 'auditbeat-7.8.0-2020.11.05-000003',
- data: [
- {
- field: '@timestamp',
- value: ['2020-11-17T14:48:08.922Z'],
- },
- {
- field: 'host.name',
- value: ['beats-ci-immutable-ubuntu-1804-1605624279743236239'],
- },
- {
- field: 'threat.enrichments.matched.field',
- value: [
- 'matched_field',
- 'other_matched_field',
- 'matched_field_2',
- 'host.name',
- 'host.hostname',
- 'host.architecture',
- ],
- },
- {
- field: 'source.geo.location',
- value: [`{"lon":118.7778,"lat":32.0617}`],
- },
- ],
- ecs: {
- '@timestamp': ['2020-11-17T14:48:08.922Z'],
+ expect(res).toEqual([
+ {
+ cursor: {
+ tiebreaker: 'beats-ci-immutable-ubuntu-1804-1605624279743236239',
+ value: '1605624488922',
+ },
+ node: {
_id: 'tkCt1nUBaEgqnrVSZ8R_',
_index: 'auditbeat-7.8.0-2020.11.05-000003',
- agent: {
- type: ['auditbeat'],
- },
- event: {
- action: ['process_started'],
- category: ['process'],
- dataset: ['process'],
- kind: ['event'],
- module: ['system'],
- type: ['start'],
- },
- host: {
- id: ['e59991e835905c65ed3e455b33e13bd6'],
- ip: ['10.224.1.237', 'fe80::4001:aff:fee0:1ed', '172.17.0.1'],
- name: ['beats-ci-immutable-ubuntu-1804-1605624279743236239'],
- os: {
- family: ['debian'],
+ data: [
+ {
+ field: '@timestamp',
+ value: ['2020-11-17T14:48:08.922Z'],
},
- },
- message: ['Process go (PID: 4313) by user jenkins STARTED'],
- process: {
- args: ['go', 'vet', './...'],
- entity_id: ['Z59cIkAAIw8ZoK0H'],
- executable: [
- '/var/lib/jenkins/workspace/Beats_beats_PR-22624/.gvm/versions/go1.14.7.linux.amd64/bin/go',
- ],
- hash: {
- sha1: ['1eac22336a41e0660fb302add9d97daa2bcc7040'],
- },
- name: ['go'],
- pid: ['4313'],
- ppid: ['3977'],
- working_directory: [
- '/var/lib/jenkins/workspace/Beats_beats_PR-22624/src/github.com/elastic/beats/libbeat',
- ],
- },
- timestamp: '2020-11-17T14:48:08.922Z',
- user: {
- name: ['jenkins'],
- },
- threat: {
- enrichments: [
- {
- feed: { name: [] },
- indicator: {
- provider: ['yourself'],
- reference: [],
- },
- matched: {
- atomic: ['matched_atomic'],
- field: ['matched_field', 'other_matched_field'],
- type: [],
- },
- },
- {
- feed: { name: [] },
- indicator: {
- provider: ['other_you'],
- reference: [],
- },
- matched: {
- atomic: ['matched_atomic_2'],
- field: ['matched_field_2'],
- type: [],
- },
- },
- {
- feed: {
- name: [],
- },
- indicator: {
- provider: [],
- reference: [],
- },
- matched: {
- atomic: ['MacBook-Pro-de-Gloria.local'],
- field: ['host.name'],
- type: ['indicator_match_rule'],
- },
+ {
+ field: 'host.name',
+ value: ['beats-ci-immutable-ubuntu-1804-1605624279743236239'],
+ },
+ {
+ field: 'threat.enrichments.matched.field',
+ value: [
+ 'matched_field',
+ 'other_matched_field',
+ 'matched_field_2',
+ 'host.name',
+ 'host.hostname',
+ 'host.architecture',
+ ],
+ },
+ {
+ field: 'source.geo.location',
+ value: [`{"lon":118.7778,"lat":32.0617}`],
+ },
+ ],
+ ecs: {
+ '@timestamp': ['2020-11-17T14:48:08.922Z'],
+ _id: 'tkCt1nUBaEgqnrVSZ8R_',
+ _index: 'auditbeat-7.8.0-2020.11.05-000003',
+ agent: {
+ type: ['auditbeat'],
+ },
+ event: {
+ action: ['process_started'],
+ category: ['process'],
+ dataset: ['process'],
+ kind: ['event'],
+ module: ['system'],
+ type: ['start'],
+ },
+ host: {
+ id: ['e59991e835905c65ed3e455b33e13bd6'],
+ ip: ['10.224.1.237', 'fe80::4001:aff:fee0:1ed', '172.17.0.1'],
+ name: ['beats-ci-immutable-ubuntu-1804-1605624279743236239'],
+ os: {
+ family: ['debian'],
},
- {
- feed: {
- name: [],
- },
- indicator: {
- provider: [],
- reference: [],
- },
- matched: {
- atomic: ['MacBook-Pro-de-Gloria.local'],
- field: ['host.hostname'],
- type: ['indicator_match_rule'],
- },
+ },
+ message: ['Process go (PID: 4313) by user jenkins STARTED'],
+ process: {
+ args: ['go', 'vet', './...'],
+ entity_id: ['Z59cIkAAIw8ZoK0H'],
+ executable: [
+ '/var/lib/jenkins/workspace/Beats_beats_PR-22624/.gvm/versions/go1.14.7.linux.amd64/bin/go',
+ ],
+ hash: {
+ sha1: ['1eac22336a41e0660fb302add9d97daa2bcc7040'],
},
- {
- feed: {
- name: [],
- },
- indicator: {
- provider: [],
- reference: [],
+ name: ['go'],
+ pid: ['4313'],
+ ppid: ['3977'],
+ working_directory: [
+ '/var/lib/jenkins/workspace/Beats_beats_PR-22624/src/github.com/elastic/beats/libbeat',
+ ],
+ },
+ timestamp: '2020-11-17T14:48:08.922Z',
+ user: {
+ name: ['jenkins'],
+ },
+ threat: {
+ enrichments: [
+ {
+ feed: { name: [] },
+ indicator: {
+ provider: ['yourself'],
+ reference: [],
+ },
+ matched: {
+ atomic: ['matched_atomic'],
+ field: ['matched_field', 'other_matched_field'],
+ type: [],
+ },
},
- matched: {
- atomic: ['x86_64'],
- field: ['host.architecture'],
- type: ['indicator_match_rule'],
+ {
+ feed: { name: [] },
+ indicator: {
+ provider: ['other_you'],
+ reference: [],
+ },
+ matched: {
+ atomic: ['matched_atomic_2'],
+ field: ['matched_field_2'],
+ type: [],
+ },
},
- },
- {
- feed: {
- name: [],
+ {
+ feed: {
+ name: [],
+ },
+ indicator: {
+ provider: [],
+ reference: [],
+ },
+ matched: {
+ atomic: ['MacBook-Pro-de-Gloria.local'],
+ field: ['host.name'],
+ type: ['indicator_match_rule'],
+ },
},
- indicator: {
- provider: [],
- reference: [],
+ {
+ feed: {
+ name: [],
+ },
+ indicator: {
+ provider: [],
+ reference: [],
+ },
+ matched: {
+ atomic: ['MacBook-Pro-de-Gloria.local'],
+ field: ['host.hostname'],
+ type: ['indicator_match_rule'],
+ },
},
- matched: {
- atomic: ['MacBook-Pro-de-Gloria.local'],
- field: ['host.name'],
- type: ['indicator_match_rule'],
+ {
+ feed: {
+ name: [],
+ },
+ indicator: {
+ provider: [],
+ reference: [],
+ },
+ matched: {
+ atomic: ['x86_64'],
+ field: ['host.architecture'],
+ type: ['indicator_match_rule'],
+ },
},
- },
- {
- feed: {
- name: [],
+ {
+ feed: {
+ name: [],
+ },
+ indicator: {
+ provider: [],
+ reference: [],
+ },
+ matched: {
+ atomic: ['MacBook-Pro-de-Gloria.local'],
+ field: ['host.name'],
+ type: ['indicator_match_rule'],
+ },
},
- indicator: {
- provider: [],
- reference: [],
+ {
+ feed: {
+ name: [],
+ },
+ indicator: {
+ provider: [],
+ reference: [],
+ },
+ matched: {
+ atomic: ['MacBook-Pro-de-Gloria.local'],
+ field: ['host.hostname'],
+ type: ['indicator_match_rule'],
+ },
},
- matched: {
- atomic: ['MacBook-Pro-de-Gloria.local'],
- field: ['host.hostname'],
- type: ['indicator_match_rule'],
- },
- },
- ],
+ ],
+ },
},
},
},
- });
+ ]);
});
it('should properly format the rule signal results', async () => {
@@ -240,57 +241,61 @@ describe('formatTimelineData', () => {
expect(
await formatTimelineData(
+ [response],
['@timestamp', 'host.name', 'destination.ip', 'source.ip'],
- TIMELINE_EVENTS_FIELDS,
- response
+ false
)
- ).toEqual({
- cursor: {
- tiebreaker: null,
- value: '',
- },
- node: {
- _id: 'a77040f198355793c35bf22b900902371309be615381f0a2ec92c208b6132562',
- _index: '.siem-signals-patrykkopycinski-default-000007',
- data: [
- {
- field: '@timestamp',
- value: ['2021-01-09T13:41:40.517Z'],
- },
- ],
- ecs: {
- '@timestamp': ['2021-01-09T13:41:40.517Z'],
- timestamp: '2021-01-09T13:41:40.517Z',
+ ).toEqual([
+ {
+ cursor: {
+ tiebreaker: null,
+ value: '',
+ },
+ node: {
_id: 'a77040f198355793c35bf22b900902371309be615381f0a2ec92c208b6132562',
_index: '.siem-signals-patrykkopycinski-default-000007',
- event: {
- kind: ['signal'],
- },
- kibana: {
- alert: {
- original_time: ['2021-01-09T13:39:32.595Z'],
- workflow_status: ['open'],
- threshold_result: ['{"count":10000,"value":"2a990c11-f61b-4c8e-b210-da2574e9f9db"}'],
- severity: ['low'],
- risk_score: ['21'],
- rule: {
- building_block_type: [],
- exceptions_list: [],
- from: ['now-360s'],
- uuid: ['696c24e0-526d-11eb-836c-e1620268b945'],
- name: ['Threshold test'],
- to: ['now'],
- type: ['threshold'],
- version: ['1'],
- timeline_id: [],
- timeline_title: [],
- note: [],
+ data: [
+ {
+ field: '@timestamp',
+ value: ['2021-01-09T13:41:40.517Z'],
+ },
+ ],
+ ecs: {
+ '@timestamp': ['2021-01-09T13:41:40.517Z'],
+ timestamp: '2021-01-09T13:41:40.517Z',
+ _id: 'a77040f198355793c35bf22b900902371309be615381f0a2ec92c208b6132562',
+ _index: '.siem-signals-patrykkopycinski-default-000007',
+ event: {
+ kind: ['signal'],
+ },
+ kibana: {
+ alert: {
+ original_time: ['2021-01-09T13:39:32.595Z'],
+ workflow_status: ['open'],
+ threshold_result: [
+ '{"count":10000,"value":"2a990c11-f61b-4c8e-b210-da2574e9f9db"}',
+ ],
+ severity: ['low'],
+ risk_score: ['21'],
+ rule: {
+ building_block_type: [],
+ exceptions_list: [],
+ from: ['now-360s'],
+ uuid: ['696c24e0-526d-11eb-836c-e1620268b945'],
+ name: ['Threshold test'],
+ to: ['now'],
+ type: ['threshold'],
+ version: ['1'],
+ timeline_id: [],
+ timeline_title: [],
+ note: [],
+ },
},
},
},
},
},
- });
+ ]);
});
it('should properly format the inventory rule signal results', async () => {
@@ -347,6 +352,7 @@ describe('formatTimelineData', () => {
expect(
await formatTimelineData(
+ [response],
[
'kibana.alert.status',
'@timestamp',
@@ -376,168 +382,169 @@ describe('formatTimelineData', () => {
'event.kind',
'kibana.alert.rule.parameters',
],
- TIMELINE_EVENTS_FIELDS,
- response
+ false
)
- ).toEqual({
- cursor: {
- tiebreaker: null,
- value: '',
- },
- node: {
- _id: '3fef4a4c-3d96-4e79-b4e5-158a0461d577',
- _index: '.internal.alerts-observability.metrics.alerts-default-000001',
- data: [
- {
- field: 'kibana.alert.rule.consumer',
- value: ['infrastructure'],
- },
- {
- field: '@timestamp',
- value: ['2022-07-21T22:38:57.888Z'],
- },
- {
- field: 'kibana.alert.workflow_status',
- value: ['open'],
- },
- {
- field: 'kibana.alert.reason',
- value: [
- 'CPU usage is 37.8% in the last 1 day for gke-edge-oblt-pool-1-9a60016d-7dvq. Alert when > 10%.',
- ],
- },
- {
- field: 'kibana.alert.rule.name',
- value: ['test 1212'],
- },
- {
- field: 'kibana.alert.rule.uuid',
- value: ['15d82f10-0926-11ed-bece-6b0c033d0075'],
- },
- {
- field: 'kibana.alert.rule.parameters.sourceId',
- value: ['default'],
- },
- {
- field: 'kibana.alert.rule.parameters.nodeType',
- value: ['host'],
- },
- {
- field: 'kibana.alert.rule.parameters.criteria.comparator',
- value: ['>'],
- },
- {
- field: 'kibana.alert.rule.parameters.criteria.timeSize',
- value: ['1'],
- },
- {
- field: 'kibana.alert.rule.parameters.criteria.metric',
- value: ['cpu'],
- },
- {
- field: 'kibana.alert.rule.parameters.criteria.threshold',
- value: ['10'],
- },
- {
- field: 'kibana.alert.rule.parameters.criteria.customMetric.aggregation',
- value: ['avg'],
- },
- {
- field: 'kibana.alert.rule.parameters.criteria.customMetric.id',
- value: ['alert-custom-metric'],
- },
- {
- field: 'kibana.alert.rule.parameters.criteria.customMetric.field',
- value: [''],
- },
- {
- field: 'kibana.alert.rule.parameters.criteria.customMetric.type',
- value: ['custom'],
- },
- {
- field: 'kibana.alert.rule.parameters.criteria.timeUnit',
- value: ['d'],
- },
- {
- field: 'event.action',
- value: ['active'],
- },
- {
- field: 'event.kind',
- value: ['signal'],
- },
- {
- field: 'kibana.alert.status',
- value: ['active'],
- },
- {
- field: 'kibana.alert.duration.us',
- value: ['9502040000'],
- },
- {
- field: 'kibana.alert.rule.category',
- value: ['Inventory'],
- },
- {
- field: 'kibana.alert.uuid',
- value: ['3fef4a4c-3d96-4e79-b4e5-158a0461d577'],
- },
- {
- field: 'kibana.alert.start',
- value: ['2022-07-21T20:00:35.848Z'],
- },
- {
- field: 'kibana.alert.rule.producer',
- value: ['infrastructure'],
- },
- {
- field: 'kibana.alert.rule.rule_type_id',
- value: ['metrics.alert.inventory.threshold'],
- },
- {
- field: 'kibana.alert.instance.id',
- value: ['gke-edge-oblt-pool-1-9a60016d-7dvq'],
- },
- {
- field: 'kibana.alert.rule.execution.uuid',
- value: ['37498c42-0190-4a83-adfa-c7e5f817f977'],
- },
- {
- field: 'kibana.space_ids',
- value: ['default'],
- },
- {
- field: 'kibana.version',
- value: ['8.4.0'],
- },
- ],
- ecs: {
- '@timestamp': ['2022-07-21T22:38:57.888Z'],
+ ).toEqual([
+ {
+ cursor: {
+ tiebreaker: null,
+ value: '',
+ },
+ node: {
_id: '3fef4a4c-3d96-4e79-b4e5-158a0461d577',
_index: '.internal.alerts-observability.metrics.alerts-default-000001',
- event: {
- action: ['active'],
- kind: ['signal'],
- },
- kibana: {
- alert: {
- reason: [
+ data: [
+ {
+ field: 'kibana.alert.rule.consumer',
+ value: ['infrastructure'],
+ },
+ {
+ field: '@timestamp',
+ value: ['2022-07-21T22:38:57.888Z'],
+ },
+ {
+ field: 'kibana.alert.workflow_status',
+ value: ['open'],
+ },
+ {
+ field: 'kibana.alert.reason',
+ value: [
'CPU usage is 37.8% in the last 1 day for gke-edge-oblt-pool-1-9a60016d-7dvq. Alert when > 10%.',
],
- rule: {
- consumer: ['infrastructure'],
- name: ['test 1212'],
- uuid: ['15d82f10-0926-11ed-bece-6b0c033d0075'],
- parameters: [
- '{"sourceId":"default","nodeType":"host","criteria":[{"comparator":">","timeSize":1,"metric":"cpu","threshold":[10],"customMetric":{"aggregation":"avg","id":"alert-custom-metric","field":"","type":"custom"},"timeUnit":"d"}]}',
+ },
+ {
+ field: 'kibana.alert.rule.name',
+ value: ['test 1212'],
+ },
+ {
+ field: 'kibana.alert.rule.uuid',
+ value: ['15d82f10-0926-11ed-bece-6b0c033d0075'],
+ },
+ {
+ field: 'kibana.alert.rule.parameters.sourceId',
+ value: ['default'],
+ },
+ {
+ field: 'kibana.alert.rule.parameters.nodeType',
+ value: ['host'],
+ },
+ {
+ field: 'kibana.alert.rule.parameters.criteria.comparator',
+ value: ['>'],
+ },
+ {
+ field: 'kibana.alert.rule.parameters.criteria.timeSize',
+ value: ['1'],
+ },
+ {
+ field: 'kibana.alert.rule.parameters.criteria.metric',
+ value: ['cpu'],
+ },
+ {
+ field: 'kibana.alert.rule.parameters.criteria.threshold',
+ value: ['10'],
+ },
+ {
+ field: 'kibana.alert.rule.parameters.criteria.customMetric.aggregation',
+ value: ['avg'],
+ },
+ {
+ field: 'kibana.alert.rule.parameters.criteria.customMetric.id',
+ value: ['alert-custom-metric'],
+ },
+ {
+ field: 'kibana.alert.rule.parameters.criteria.customMetric.field',
+ value: [''],
+ },
+ {
+ field: 'kibana.alert.rule.parameters.criteria.customMetric.type',
+ value: ['custom'],
+ },
+ {
+ field: 'kibana.alert.rule.parameters.criteria.timeUnit',
+ value: ['d'],
+ },
+ {
+ field: 'event.action',
+ value: ['active'],
+ },
+ {
+ field: 'event.kind',
+ value: ['signal'],
+ },
+ {
+ field: 'kibana.alert.status',
+ value: ['active'],
+ },
+ {
+ field: 'kibana.alert.duration.us',
+ value: ['9502040000'],
+ },
+ {
+ field: 'kibana.alert.rule.category',
+ value: ['Inventory'],
+ },
+ {
+ field: 'kibana.alert.uuid',
+ value: ['3fef4a4c-3d96-4e79-b4e5-158a0461d577'],
+ },
+ {
+ field: 'kibana.alert.start',
+ value: ['2022-07-21T20:00:35.848Z'],
+ },
+ {
+ field: 'kibana.alert.rule.producer',
+ value: ['infrastructure'],
+ },
+ {
+ field: 'kibana.alert.rule.rule_type_id',
+ value: ['metrics.alert.inventory.threshold'],
+ },
+ {
+ field: 'kibana.alert.instance.id',
+ value: ['gke-edge-oblt-pool-1-9a60016d-7dvq'],
+ },
+ {
+ field: 'kibana.alert.rule.execution.uuid',
+ value: ['37498c42-0190-4a83-adfa-c7e5f817f977'],
+ },
+ {
+ field: 'kibana.space_ids',
+ value: ['default'],
+ },
+ {
+ field: 'kibana.version',
+ value: ['8.4.0'],
+ },
+ ],
+ ecs: {
+ '@timestamp': ['2022-07-21T22:38:57.888Z'],
+ _id: '3fef4a4c-3d96-4e79-b4e5-158a0461d577',
+ _index: '.internal.alerts-observability.metrics.alerts-default-000001',
+ event: {
+ action: ['active'],
+ kind: ['signal'],
+ },
+ kibana: {
+ alert: {
+ reason: [
+ 'CPU usage is 37.8% in the last 1 day for gke-edge-oblt-pool-1-9a60016d-7dvq. Alert when > 10%.',
],
+ rule: {
+ consumer: ['infrastructure'],
+ name: ['test 1212'],
+ uuid: ['15d82f10-0926-11ed-bece-6b0c033d0075'],
+ parameters: [
+ '{"sourceId":"default","nodeType":"host","criteria":[{"comparator":">","timeSize":1,"metric":"cpu","threshold":[10],"customMetric":{"aggregation":"avg","id":"alert-custom-metric","field":"","type":"custom"},"timeUnit":"d"}]}',
+ ],
+ },
+ workflow_status: ['open'],
},
- workflow_status: ['open'],
},
+ timestamp: '2022-07-21T22:38:57.888Z',
},
- timestamp: '2022-07-21T22:38:57.888Z',
},
},
- });
+ ]);
});
});
diff --git a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/format_timeline_data.ts b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/format_timeline_data.ts
index f56cfd32391d4..485ec64badd5c 100644
--- a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/format_timeline_data.ts
+++ b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/format_timeline_data.ts
@@ -5,118 +5,130 @@
* 2.0.
*/
-import { get, has, merge, uniq } from 'lodash/fp';
-import { EventHit, TimelineEdges, TimelineNonEcsData } from '../../../../../common/search_strategy';
+import { get, has } from 'lodash/fp';
+import {
+ EventHit,
+ TimelineEdges,
+ TimelineNonEcsData,
+ EventSource,
+} from '../../../../../common/search_strategy';
import { toStringArray } from '../../../../../common/utils/to_array';
-import { getDataFromFieldsHits, getDataSafety } from '../../../../../common/utils/field_formatters';
+import { getDataFromFieldsHits } from '../../../../../common/utils/field_formatters';
import { getTimestamp } from './get_timestamp';
import { getNestedParentPath } from './get_nested_parent_path';
import { buildObjectRecursive } from './build_object_recursive';
-import { ECS_METADATA_FIELDS } from './constants';
+import { ECS_METADATA_FIELDS, TIMELINE_EVENTS_FIELDS } from './constants';
-export const formatTimelineData = async (
- dataFields: readonly string[],
- ecsFields: readonly string[],
- hit: EventHit
-) =>
- uniq([...ecsFields, ...dataFields]).reduce>(
- async (acc, fieldName) => {
- const flattenedFields: TimelineEdges = await acc;
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- flattenedFields.node._id = hit._id!;
- flattenedFields.node._index = hit._index;
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- flattenedFields.node.ecs._id = hit._id!;
- flattenedFields.node.ecs.timestamp = getTimestamp(hit);
- flattenedFields.node.ecs._index = hit._index;
- if (hit.sort && hit.sort.length > 1) {
- flattenedFields.cursor.value = hit.sort[0];
- flattenedFields.cursor.tiebreaker = hit.sort[1];
- }
- const waitForIt = await mergeTimelineFieldsWithHit(
- fieldName,
- flattenedFields,
- hit,
- dataFields,
- ecsFields
- );
- return Promise.resolve(waitForIt);
- },
- Promise.resolve({
- node: { ecs: { _id: '' }, data: [], _id: '', _index: '' },
- cursor: {
- value: '',
- tiebreaker: null,
- },
- })
- );
-
-const getValuesFromFields = async (
+const createBaseTimelineEdges = (): TimelineEdges => ({
+ node: {
+ ecs: { _id: '' },
+ data: [],
+ _id: '',
+ _index: '',
+ },
+ cursor: {
+ value: '',
+ tiebreaker: null,
+ },
+});
+
+function deepMerge(target: EventSource, source: EventSource) {
+ for (const key in source) {
+ if (source[key] instanceof Object && key in target) {
+ deepMerge(target[key], source[key]);
+ } else {
+ target[key] = source[key];
+ }
+ }
+ return target;
+}
+
+const processMetadataField = (fieldName: string, hit: EventHit): TimelineNonEcsData[] => [
+ {
+ field: fieldName,
+ value: toStringArray(get(fieldName, hit)),
+ },
+];
+
+const processFieldData = (
fieldName: string,
hit: EventHit,
nestedParentFieldName?: string
-): Promise => {
- if (ECS_METADATA_FIELDS.includes(fieldName)) {
- return [{ field: fieldName, value: toStringArray(get(fieldName, hit)) }];
- }
+): TimelineNonEcsData[] => {
+ const fieldToEval = nestedParentFieldName
+ ? { [nestedParentFieldName]: hit.fields[nestedParentFieldName] }
+ : { [fieldName]: hit.fields[fieldName] };
- let fieldToEval;
-
- if (nestedParentFieldName == null) {
- fieldToEval = {
- [fieldName]: hit.fields[fieldName],
- };
- } else {
- fieldToEval = {
- [nestedParentFieldName]: hit.fields[nestedParentFieldName],
- };
- }
- const formattedData = await getDataSafety(getDataFromFieldsHits, fieldToEval);
- return formattedData.reduce((acc: TimelineNonEcsData[], { field, values }) => {
- // nested fields return all field values, pick only the one we asked for
+ const formattedData = getDataFromFieldsHits(fieldToEval);
+ const fieldsData: TimelineNonEcsData[] = [];
+ return formattedData.reduce((agg, { field, values }) => {
if (field.includes(fieldName)) {
- acc.push({ field, value: values });
+ agg.push({
+ field,
+ value: values,
+ });
}
- return acc;
- }, []);
+ return agg;
+ }, fieldsData);
};
-const mergeTimelineFieldsWithHit = async (
- fieldName: string,
- flattenedFields: T,
- hit: EventHit,
- dataFields: readonly string[],
- ecsFields: readonly string[]
-) => {
- if (fieldName != null) {
- const nestedParentPath = getNestedParentPath(fieldName, hit.fields);
- if (
- nestedParentPath != null ||
- has(fieldName, hit.fields) ||
- ECS_METADATA_FIELDS.includes(fieldName)
- ) {
- const objectWithProperty = {
- node: {
- ...get('node', flattenedFields),
- data: dataFields.includes(fieldName)
- ? [
- ...get('node.data', flattenedFields),
- ...(await getValuesFromFields(fieldName, hit, nestedParentPath)),
- ]
- : get('node.data', flattenedFields),
- ecs: ecsFields.includes(fieldName)
- ? {
- ...get('node.ecs', flattenedFields),
- ...buildObjectRecursive(fieldName, hit.fields),
- }
- : get('node.ecs', flattenedFields),
- },
- };
- return merge(flattenedFields, objectWithProperty);
+export const formatTimelineData = async (
+ hits: EventHit[],
+ fieldRequested: readonly string[],
+ excludeEcsData: boolean
+): Promise => {
+ const ecsFields = excludeEcsData ? [] : TIMELINE_EVENTS_FIELDS;
+
+ const uniqueFields = new Set([...ecsFields, ...fieldRequested]);
+ const dataFieldSet = new Set(fieldRequested);
+ const ecsFieldSet = new Set(ecsFields);
+
+ const results: TimelineEdges[] = new Array(hits.length);
+
+ for (let i = 0; i < hits.length; i++) {
+ const hit = hits[i];
+ if (hit._id) {
+ const result = createBaseTimelineEdges();
+
+ result.node._id = hit._id;
+ result.node._index = hit._index;
+ result.node.ecs._id = hit._id;
+ result.node.ecs.timestamp = getTimestamp(hit);
+ result.node.ecs._index = hit._index;
+
+ if (hit.sort?.length > 1) {
+ result.cursor.value = hit.sort[0];
+ result.cursor.tiebreaker = hit.sort[1];
+ }
+
+ result.node.data = [];
+
+ for (const fieldName of uniqueFields) {
+ const nestedParentPath = getNestedParentPath(fieldName, hit.fields);
+ const isEcs = ECS_METADATA_FIELDS.includes(fieldName);
+ if (!nestedParentPath && !has(fieldName, hit.fields) && !isEcs) {
+ // eslint-disable-next-line no-continue
+ continue;
+ }
+
+ if (dataFieldSet.has(fieldName)) {
+ const values = isEcs
+ ? processMetadataField(fieldName, hit)
+ : processFieldData(fieldName, hit, nestedParentPath);
+
+ result.node.data.push(...values);
+ }
+
+ if (ecsFieldSet.has(fieldName)) {
+ deepMerge(result.node.ecs, buildObjectRecursive(fieldName, hit.fields));
+ }
+ }
+
+ results[i] = result;
} else {
- return flattenedFields;
+ results[i] = createBaseTimelineEdges();
}
- } else {
- return flattenedFields;
}
+
+ return results;
};
From 8b6ed1757cb6185f8d03dceca6656df76d19b9c7 Mon Sep 17 00:00:00 2001
From: Sandra G
Date: Fri, 22 Nov 2024 13:58:09 -0500
Subject: [PATCH 18/38] [Data Usage] don't display action menu for Total
(#201423)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Summary
"Total" should not have an action menu because its not a data stream
### Checklist
Check the PR satisfies following conditions.
Reviewers should verify this PR satisfies this list as well.
- [ ] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [ ] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [ ] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [ ] This was checked for breaking HTTP API changes, and any breaking
changes have been approved by the breaking-change committee. The
`release_note:breaking` label should be applied in these situations.
- [ ] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [ ] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
### Identify risks
Does this PR introduce any risks? For example, consider risks like hard
to test bugs, performance regression, potential of data loss.
Describe the risk, its severity, and mitigation for each identified
risk. Invite stakeholders and evaluate how to proceed before merging.
- [ ] [See some risk
examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx)
- [ ] ...
---
.../plugins/data_usage/public/app/components/chart_panel.tsx | 3 +++
1 file changed, 3 insertions(+)
diff --git a/x-pack/plugins/data_usage/public/app/components/chart_panel.tsx b/x-pack/plugins/data_usage/public/app/components/chart_panel.tsx
index 31ae68244e982..bb0df29e22fff 100644
--- a/x-pack/plugins/data_usage/public/app/components/chart_panel.tsx
+++ b/x-pack/plugins/data_usage/public/app/components/chart_panel.tsx
@@ -74,6 +74,9 @@ export const ChartPanel: React.FC = ({
}, [series]);
const renderLegendAction = useCallback(
({ label }: { label: string }) => {
+ if (label === 'Total') {
+ return null;
+ }
return (
Date: Fri, 22 Nov 2024 14:10:45 -0500
Subject: [PATCH 19/38] [Search][ES3] Enable Inference Management UI in ES3
(#200109)
## Summary
This PR:
- Enables Inference Management in ES3
- Fixes small issues to make sure it works in ES3.
- Added FTR tests.
### Checklist
Check the PR satisfies following conditions.
Reviewers should verify this PR satisfies this list as well.
- [X] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [X] This was checked for breaking HTTP API changes, and any breaking
changes have been approved by the breaking-change committee. The
`release_note:breaking` label should be applied in these situations.
- [X] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [X] The PR description includes the appropriate Release Notes section,
and the correct `release_node:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
---
config/serverless.es.yml | 2 +-
packages/kbn-doc-links/src/get_doc_links.ts | 3 +
packages/kbn-doc-links/src/types.ts | 3 +
.../enterprise_search/common/constants.ts | 2 +-
.../common/locators/index.ts | 3 +
.../common/locators/inference_locator.tsx | 30 +++++
.../applications/shared/layout/nav.test.tsx | 4 +-
.../index_details_page.test.tsx | 23 +++-
.../select_inference_id.test.tsx | 23 +++-
.../field_parameters/select_inference_id.tsx | 50 ++++---
.../common/doc_links.ts | 2 +-
.../common/translations.ts | 62 ---------
.../search_inference_endpoints/kibana.jsonc | 1 +
.../all_inference_endpoints/constants.ts | 1 +
.../filter/multi_select_filter.tsx | 4 +-
.../filter/service_provider_filter.tsx | 1 +
.../filter/task_type_filter.tsx | 1 +
.../actions/component/index_item.test.tsx | 48 +++++++
.../{usage_item.tsx => index_item.tsx} | 29 ++--
.../actions/component/list_usage_results.tsx | 13 +-
...e_item.test.tsx => pipeline_item.test.tsx} | 41 +-----
.../actions/component/pipeline_item.tsx | 69 ++++++++++
.../actions/component/scan_usage_results.tsx | 17 ++-
.../delete/confirm_delete_endpoint/index.tsx | 1 +
.../all_inference_endpoints/tabular_page.tsx | 4 +
.../empty_prompt/add_empty_prompt.scss | 3 -
.../empty_prompt/add_empty_prompt.test.tsx | 47 -------
.../empty_prompt/add_empty_prompt.tsx | 103 --------------
.../empty_prompt/endpoint_prompt.tsx | 27 ----
.../public/components/empty_prompt/index.ts | 8 --
.../public/components/inference_endpoints.tsx | 11 +-
.../public/locators.ts | 29 ++++
.../public/plugin.ts | 20 ++-
.../public/types.ts | 15 ++-
.../search_inference_endpoints/tsconfig.json | 4 +-
.../translations/translations/fr-FR.json | 9 --
.../translations/translations/ja-JP.json | 9 --
.../translations/translations/zh-CN.json | 9 --
.../functional/page_objects/index.ts | 2 +
.../svl_search_inference_management_page.ts | 127 ++++++++++++++++++
.../services/svl_search_navigation.ts | 5 +
.../functional/test_suites/search/config.ts | 3 +
.../functional/test_suites/search/index.ts | 1 +
.../search/inference_management.ts | 103 ++++++++++++++
.../test_suites/search/navigation.ts | 30 ++---
45 files changed, 609 insertions(+), 393 deletions(-)
create mode 100644 x-pack/plugins/enterprise_search/common/locators/inference_locator.tsx
create mode 100644 x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.test.tsx
rename x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/{usage_item.tsx => index_item.tsx} (77%)
rename x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/{usage_item.test.tsx => pipeline_item.test.tsx} (59%)
create mode 100644 x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.tsx
delete mode 100644 x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.scss
delete mode 100644 x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.test.tsx
delete mode 100644 x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.tsx
delete mode 100644 x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/endpoint_prompt.tsx
delete mode 100644 x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/index.ts
create mode 100644 x-pack/plugins/search_inference_endpoints/public/locators.ts
create mode 100644 x-pack/test_serverless/functional/page_objects/svl_search_inference_management_page.ts
create mode 100644 x-pack/test_serverless/functional/test_suites/search/inference_management.ts
diff --git a/config/serverless.es.yml b/config/serverless.es.yml
index eafa7f3113395..4b0d416bacdfc 100644
--- a/config/serverless.es.yml
+++ b/config/serverless.es.yml
@@ -113,7 +113,7 @@ data_visualizer.resultLinks.fileBeat.enabled: false
xpack.searchPlayground.ui.enabled: true
# Search InferenceEndpoints
-xpack.searchInferenceEndpoints.ui.enabled: false
+xpack.searchInferenceEndpoints.ui.enabled: true
# Search Notebooks
xpack.search.notebooks.catalog.url: https://elastic-enterprise-search.s3.us-east-2.amazonaws.com/serverless/catalog.json
diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts
index a31e1f1641e8b..44bd57ed8f3d1 100644
--- a/packages/kbn-doc-links/src/get_doc_links.ts
+++ b/packages/kbn-doc-links/src/get_doc_links.ts
@@ -1001,5 +1001,8 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D
context: `${KIBANA_DOCS}playground-context.html`,
hiddenFields: `${KIBANA_DOCS}playground-query.html#playground-hidden-fields`,
},
+ inferenceManagement: {
+ inferenceAPIDocumentation: `${ELASTIC_WEBSITE_URL}docs/api/doc/elasticsearch/operation/operation-inference-put`,
+ },
});
};
diff --git a/packages/kbn-doc-links/src/types.ts b/packages/kbn-doc-links/src/types.ts
index ac0f66d83b705..a344d2d694c05 100644
--- a/packages/kbn-doc-links/src/types.ts
+++ b/packages/kbn-doc-links/src/types.ts
@@ -676,6 +676,9 @@ export interface DocLinks {
readonly context: string;
readonly hiddenFields: string;
};
+ readonly inferenceManagement: {
+ readonly inferenceAPIDocumentation: string;
+ };
}
export type BuildFlavor = 'serverless' | 'traditional';
diff --git a/x-pack/plugins/enterprise_search/common/constants.ts b/x-pack/plugins/enterprise_search/common/constants.ts
index 0c13a772862b8..2603ea3d89018 100644
--- a/x-pack/plugins/enterprise_search/common/constants.ts
+++ b/x-pack/plugins/enterprise_search/common/constants.ts
@@ -211,7 +211,7 @@ export const SEARCH_RELEVANCE_PLUGIN = {
DESCRIPTION: i18n.translate('xpack.enterpriseSearch.inferenceEndpoints.description', {
defaultMessage: 'Manage your inference endpoints for semantic search and AI use cases.',
}),
- URL: '/app/enterprise_search/relevance',
+ URL: '/app/elasticsearch/relevance',
LOGO: 'logoEnterpriseSearch',
SUPPORT_URL: 'https://discuss.elastic.co/c/enterprise-search/',
};
diff --git a/x-pack/plugins/enterprise_search/common/locators/index.ts b/x-pack/plugins/enterprise_search/common/locators/index.ts
index 0f9d2060cd829..35c1d43b3b30a 100644
--- a/x-pack/plugins/enterprise_search/common/locators/index.ts
+++ b/x-pack/plugins/enterprise_search/common/locators/index.ts
@@ -6,14 +6,17 @@
*/
import type { SharePluginSetup } from '@kbn/share-plugin/public';
+import { SerializableRecord } from '@kbn/utility-types';
import {
CreateIndexLocatorDefinition,
type CreateIndexLocatorParams,
} from './create_index_locator';
+import { SearchInferenceEndpointLocatorDefinition } from './inference_locator';
import { PlaygroundLocatorDefinition, type PlaygroundLocatorParams } from './playground_locator';
export function registerLocators(share: SharePluginSetup) {
share.url.locators.create(new CreateIndexLocatorDefinition());
share.url.locators.create(new PlaygroundLocatorDefinition());
+ share.url.locators.create(new SearchInferenceEndpointLocatorDefinition());
}
diff --git a/x-pack/plugins/enterprise_search/common/locators/inference_locator.tsx b/x-pack/plugins/enterprise_search/common/locators/inference_locator.tsx
new file mode 100644
index 0000000000000..f20d628bf1899
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/common/locators/inference_locator.tsx
@@ -0,0 +1,30 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import type { LocatorDefinition } from '@kbn/share-plugin/common';
+import type { SharePluginSetup } from '@kbn/share-plugin/public';
+import type { SerializableRecord } from '@kbn/utility-types';
+
+import { SEARCH_RELEVANCE_PLUGIN } from '../constants';
+
+export function registerLocators(share: SharePluginSetup) {
+ share.url.locators.create(new SearchInferenceEndpointLocatorDefinition());
+}
+
+export class SearchInferenceEndpointLocatorDefinition
+ implements LocatorDefinition
+{
+ public readonly getLocation = async () => {
+ return {
+ app: SEARCH_RELEVANCE_PLUGIN.ID,
+ path: '/inference_endpoints',
+ state: {},
+ };
+ };
+
+ public readonly id = 'SEARCH_INFERENCE_ENDPOINTS';
+}
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx
index 3305e92dd8d9e..a6cbf56691735 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx
@@ -101,7 +101,7 @@ const baseNavItems = [
items: [
{
'data-test-subj': 'searchSideNav-InferenceEndpoints',
- href: '/app/enterprise_search/relevance/inference_endpoints',
+ href: '/app/elasticsearch/relevance/inference_endpoints',
id: 'inference_endpoints',
items: undefined,
name: 'Inference Endpoints',
@@ -205,7 +205,7 @@ const mockNavLinks = [
{
id: 'searchInferenceEndpoints:inferenceEndpoints',
title: 'Inference Endpoints',
- url: '/app/enterprise_search/relevance/inference_endpoints',
+ url: '/app/elasticsearch/relevance/inference_endpoints',
},
{
id: 'appSearch:engines',
diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx
index 5a97dadc870cb..4badcc04540b1 100644
--- a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx
+++ b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx
@@ -727,6 +727,11 @@ describe('', () => {
isActive: true,
hasAtLeast: jest.fn((type) => true),
};
+ const INFERENCE_LOCATOR = 'SEARCH_INFERENCE_ENDPOINTS';
+ const createMockLocator = (id: string) => ({
+ useUrl: jest.fn().mockReturnValue('https://redirect.me/to/inference_endpoints'),
+ });
+ const mockInferenceManagementLocator = createMockLocator(INFERENCE_LOCATOR);
beforeEach(async () => {
httpRequestsMockHelpers.setInferenceModels({
data: [
@@ -750,7 +755,9 @@ describe('', () => {
docLinks: {
links: {
ml: '',
- enterpriseSearch: '',
+ inferenceManagement: {
+ inferenceAPIDocumentation: 'https://abc.com/inference-api-create',
+ },
},
},
core: {
@@ -819,6 +826,20 @@ describe('', () => {
},
},
},
+ share: {
+ url: {
+ locators: {
+ get: jest.fn((id) => {
+ switch (id) {
+ case INFERENCE_LOCATOR:
+ return mockInferenceManagementLocator;
+ default:
+ throw new Error(`Unknown locator id: ${id}`);
+ }
+ }),
+ },
+ },
+ },
},
},
});
diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/select_inference_id.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/select_inference_id.test.tsx
index 2fb9165e8fd10..1c9633f829bc3 100644
--- a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/select_inference_id.test.tsx
+++ b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/select_inference_id.test.tsx
@@ -20,6 +20,11 @@ import { InferenceAPIConfigResponse } from '@kbn/ml-trained-models-utils';
const createInferenceEndpointMock = jest.fn();
const mockDispatch = jest.fn();
+const INFERENCE_LOCATOR = 'SEARCH_INFERENCE_ENDPOINTS';
+const createMockLocator = (id: string) => ({
+ useUrl: jest.fn().mockReturnValue('https://redirect.me/to/inference_endpoints'),
+});
+const mockInferenceManagementLocator = createMockLocator(INFERENCE_LOCATOR);
jest.mock('../../../public/application/app_context', () => ({
useAppContext: jest.fn().mockReturnValue({
@@ -33,8 +38,8 @@ jest.mock('../../../public/application/app_context', () => ({
},
docLinks: {
links: {
- enterpriseSearch: {
- inferenceApiCreate: 'https://abc.com/inference-api-create',
+ inferenceManagement: {
+ inferenceAPIDocumentation: 'https://abc.com/inference-api-create',
},
},
},
@@ -47,6 +52,20 @@ jest.mock('../../../public/application/app_context', () => ({
},
},
},
+ share: {
+ url: {
+ locators: {
+ get: jest.fn((id) => {
+ switch (id) {
+ case INFERENCE_LOCATOR:
+ return mockInferenceManagementLocator;
+ default:
+ throw new Error(`Unknown locator id: ${id}`);
+ }
+ }),
+ },
+ },
+ },
},
}),
}));
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx
index a9c54aee80360..51cd2b5f14789 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx
@@ -80,13 +80,15 @@ const SelectInferenceIdContent: React.FC = ({
value,
}) => {
const {
- core: { application, http },
+ core: { application },
docLinks,
- plugins: { ml },
+ plugins: { ml, share },
} = useAppContext();
const config = getFieldConfig('inference_id');
- const inferenceEndpointsPageLink = `${http.basePath.get()}/app/enterprise_search/relevance/inference_endpoints`;
+ const inferenceEndpointsPageLink = share?.url.locators
+ .get('SEARCH_INFERENCE_ENDPOINTS')
+ ?.useUrl({});
const [isInferenceFlyoutVisible, setIsInferenceFlyoutVisible] = useState(false);
const [availableTrainedModels, setAvailableTrainedModels] = useState<
@@ -224,24 +226,28 @@ const SelectInferenceIdContent: React.FC = ({
panelPaddingSize="m"
closePopover={() => setIsInferencePopoverVisible(!isInferencePopoverVisible)}
>
-
- {
- application.navigateToUrl(inferenceEndpointsPageLink);
- }}
- >
- {i18n.translate(
- 'xpack.idxMgmt.mappingsEditor.parameters.inferenceId.popover.manageInferenceEndpointButton',
- {
- defaultMessage: 'Manage Inference Endpoints',
- }
- )}
-
-
+ {inferenceEndpointsPageLink && (
+
+ {
+ e.preventDefault();
+ application.navigateToUrl(inferenceEndpointsPageLink);
+ }}
+ >
+ {i18n.translate(
+ 'xpack.idxMgmt.mappingsEditor.parameters.inferenceId.popover.manageInferenceEndpointButton',
+ {
+ defaultMessage: 'Manage Inference Endpoints',
+ }
+ )}
+
+
+ )}
@@ -292,7 +298,7 @@ const SelectInferenceIdContent: React.FC = ({
} size="s">
diff --git a/x-pack/plugins/search_inference_endpoints/common/doc_links.ts b/x-pack/plugins/search_inference_endpoints/common/doc_links.ts
index bb426180a36e8..483803e970d82 100644
--- a/x-pack/plugins/search_inference_endpoints/common/doc_links.ts
+++ b/x-pack/plugins/search_inference_endpoints/common/doc_links.ts
@@ -15,7 +15,7 @@ class InferenceEndpointsDocLinks {
constructor() {}
setDocLinks(newDocLinks: DocLinks) {
- this.createInferenceEndpoint = newDocLinks.enterpriseSearch.inferenceApiCreate;
+ this.createInferenceEndpoint = newDocLinks.inferenceManagement.inferenceAPIDocumentation;
this.semanticSearchElser = newDocLinks.enterpriseSearch.elser;
this.semanticSearchE5 = newDocLinks.enterpriseSearch.e5Model;
}
diff --git a/x-pack/plugins/search_inference_endpoints/common/translations.ts b/x-pack/plugins/search_inference_endpoints/common/translations.ts
index 0f1aa4a8abcfc..8b63725c59f96 100644
--- a/x-pack/plugins/search_inference_endpoints/common/translations.ts
+++ b/x-pack/plugins/search_inference_endpoints/common/translations.ts
@@ -26,49 +26,6 @@ export const MANAGE_INFERENCE_ENDPOINTS_LABEL = i18n.translate(
}
);
-export const CREATE_FIRST_INFERENCE_ENDPOINT_DESCRIPTION = i18n.translate(
- 'xpack.searchInferenceEndpoints.addEmptyPrompt.createFirstInferenceEndpointDescription',
- {
- defaultMessage:
- "Inference endpoints enable you to perform inference tasks using NLP models provided by third-party services or Elastic's built-in models like ELSER and E5. Set up tasks such as text embedding, completions, reranking, and more by using the Create Inference API.",
- }
-);
-
-export const START_WITH_PREPARED_ENDPOINTS_LABEL = i18n.translate(
- 'xpack.searchInferenceEndpoints.addEmptyPrompt.startWithPreparedEndpointsLabel',
- {
- defaultMessage: 'Learn more about built-in NLP models:',
- }
-);
-
-export const ELSER_TITLE = i18n.translate(
- 'xpack.searchInferenceEndpoints.addEmptyPrompt.elserTitle',
- {
- defaultMessage: 'ELSER',
- }
-);
-
-export const LEARN_HOW_TO_CREATE_INFERENCE_ENDPOINTS_LINK = i18n.translate(
- 'xpack.searchInferenceEndpoints.addEmptyPrompt.learnHowToCreateInferenceEndpoints',
- {
- defaultMessage: 'Learn how to create inference endpoints',
- }
-);
-
-export const SEMANTIC_SEARCH_WITH_ELSER_LINK = i18n.translate(
- 'xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithElser',
- {
- defaultMessage: 'Semantic search with ELSER',
- }
-);
-
-export const SEMANTIC_SEARCH_WITH_E5_LINK = i18n.translate(
- 'xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithE5',
- {
- defaultMessage: 'Semantic search with E5 Multilingual',
- }
-);
-
export const VIEW_YOUR_MODELS_LINK = i18n.translate(
'xpack.searchInferenceEndpoints.viewYourModels',
{
@@ -83,25 +40,6 @@ export const API_DOCUMENTATION_LINK = i18n.translate(
}
);
-export const ELSER_DESCRIPTION = i18n.translate(
- 'xpack.searchInferenceEndpoints.addEmptyPrompt.elserDescription',
- {
- defaultMessage: "ELSER is Elastic's sparse vector NLP model for semantic search in English.",
- }
-);
-
-export const E5_TITLE = i18n.translate('xpack.searchInferenceEndpoints.addEmptyPrompt.e5Title', {
- defaultMessage: 'E5 Multilingual',
-});
-
-export const E5_DESCRIPTION = i18n.translate(
- 'xpack.searchInferenceEndpoints.addEmptyPrompt.e5Description',
- {
- defaultMessage:
- 'E5 is a third-party NLP model that enables you to perform multilingual semantic search by using dense vector representations.',
- }
-);
-
export const ERROR_TITLE = i18n.translate('xpack.searchInferenceEndpoints.inferenceId.errorTitle', {
defaultMessage: 'Error adding inference endpoint',
});
diff --git a/x-pack/plugins/search_inference_endpoints/kibana.jsonc b/x-pack/plugins/search_inference_endpoints/kibana.jsonc
index f535a9df27e99..25b7b391b955a 100644
--- a/x-pack/plugins/search_inference_endpoints/kibana.jsonc
+++ b/x-pack/plugins/search_inference_endpoints/kibana.jsonc
@@ -24,6 +24,7 @@
"optionalPlugins": [
"cloud",
"console",
+ "serverless"
],
"requiredBundles": [
"kibanaReact"
diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/constants.ts b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/constants.ts
index 7ce1e578f1db0..931994c46afca 100644
--- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/constants.ts
+++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/constants.ts
@@ -34,3 +34,4 @@ export const DEFAULT_INFERENCE_ENDPOINTS_TABLE_STATE: AllInferenceEndpointsTable
};
export const PIPELINE_URL = 'ingest/ingest_pipelines';
+export const SERVERLESS_INDEX_MANAGEMENT_URL = 'index_details';
diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/filter/multi_select_filter.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/filter/multi_select_filter.tsx
index 790bb5ec09913..371b204e0acd6 100644
--- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/filter/multi_select_filter.tsx
+++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/filter/multi_select_filter.tsx
@@ -33,6 +33,7 @@ interface UseFilterParams {
options: MultiSelectFilterOption[];
renderOption?: (option: MultiSelectFilterOption) => React.ReactNode;
selectedOptionKeys?: string[];
+ dataTestSubj?: string;
}
export const MultiSelectFilter: React.FC = ({
@@ -41,6 +42,7 @@ export const MultiSelectFilter: React.FC = ({
options: rawOptions,
selectedOptionKeys = [],
renderOption,
+ dataTestSubj,
}) => {
const { euiTheme } = useEuiTheme();
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
@@ -55,7 +57,7 @@ export const MultiSelectFilter: React.FC = ({
);
return (
-
+
= ({ optionKeys, onChange })
options={options}
renderOption={(option) => option.label}
selectedOptionKeys={optionKeys}
+ dataTestSubj="service-field-endpoints"
/>
);
};
diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/filter/task_type_filter.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/filter/task_type_filter.tsx
index e9c32503dba73..071069a880b3c 100644
--- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/filter/task_type_filter.tsx
+++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/filter/task_type_filter.tsx
@@ -38,6 +38,7 @@ export const TaskTypeFilter: React.FC = ({ optionKeys, onChange }) => {
options={options}
renderOption={(option) => option.label}
selectedOptionKeys={optionKeys}
+ dataTestSubj="type-field-endpoints"
/>
);
};
diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.test.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.test.tsx
new file mode 100644
index 0000000000000..bfdc1edd31bd6
--- /dev/null
+++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.test.tsx
@@ -0,0 +1,48 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { render, fireEvent, screen } from '@testing-library/react';
+import React from 'react';
+
+import { IndexItem } from './index_item';
+import { InferenceUsageInfo } from '../../../../types';
+import { useKibana } from '../../../../../../hooks/use_kibana';
+
+jest.mock('../../../../../../hooks/use_kibana');
+const mockUseKibana = useKibana as jest.Mock;
+const mockNavigateToApp = jest.fn();
+
+describe('Index Item', () => {
+ const item: InferenceUsageInfo = {
+ id: 'index-1',
+ type: 'Index',
+ };
+ beforeEach(() => {
+ mockUseKibana.mockReturnValue({
+ services: {
+ application: {
+ navigateToApp: mockNavigateToApp,
+ },
+ },
+ });
+
+ render();
+ });
+
+ it('renders', () => {
+ expect(screen.getByText('index-1')).toBeInTheDocument();
+ expect(screen.getByText('Index')).toBeInTheDocument();
+ });
+
+ it('opens index in a new tab', () => {
+ fireEvent.click(screen.getByRole('button'));
+ expect(mockNavigateToApp).toHaveBeenCalledWith('enterpriseSearchContent', {
+ openInNewTab: true,
+ path: 'search_indices/index-1',
+ });
+ });
+});
diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/usage_item.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.tsx
similarity index 77%
rename from x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/usage_item.tsx
rename to x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.tsx
index 577b9f8aa0e29..a62a9b9f3caed 100644
--- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/usage_item.tsx
+++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/index_item.tsx
@@ -16,34 +16,35 @@ import {
EuiIcon,
EuiSpacer,
} from '@elastic/eui';
-import React from 'react';
+import React, { useCallback } from 'react';
import { ENTERPRISE_SEARCH_CONTENT_APP_ID } from '@kbn/deeplinks-search';
-import { MANAGEMENT_APP_ID } from '@kbn/deeplinks-management/constants';
+
+import { SEARCH_INDICES } from '@kbn/deeplinks-search/constants';
import { useKibana } from '../../../../../../hooks/use_kibana';
import { InferenceUsageInfo } from '../../../../types';
-import { PIPELINE_URL } from '../../../../constants';
+import { SERVERLESS_INDEX_MANAGEMENT_URL } from '../../../../constants';
interface UsageProps {
usageItem: InferenceUsageInfo;
}
-export const UsageItem: React.FC = ({ usageItem }) => {
+export const IndexItem: React.FC = ({ usageItem }) => {
const {
- services: { application },
+ services: { application, serverless },
} = useKibana();
- const handleNavigateToIndex = () => {
- if (usageItem.type === 'Index') {
- application?.navigateToApp(ENTERPRISE_SEARCH_CONTENT_APP_ID, {
- path: `search_indices/${usageItem.id}`,
+ const navigateToIndex = useCallback(() => {
+ if (serverless) {
+ application?.navigateToApp(SEARCH_INDICES, {
+ path: `${SERVERLESS_INDEX_MANAGEMENT_URL}/${usageItem.id}/data`,
openInNewTab: true,
});
- } else if (usageItem.type === 'Pipeline') {
- application?.navigateToApp(MANAGEMENT_APP_ID, {
- path: `${PIPELINE_URL}?pipeline=${usageItem.id}`,
+ } else {
+ application?.navigateToApp(ENTERPRISE_SEARCH_CONTENT_APP_ID, {
+ path: `search_indices/${usageItem.id}`,
openInNewTab: true,
});
}
- };
+ }, [application, serverless, usageItem.id]);
return (
@@ -62,7 +63,7 @@ export const UsageItem: React.FC = ({ usageItem }) => {
-
+
diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/list_usage_results.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/list_usage_results.tsx
index d42b0f6735252..05aaaa8bb9eaf 100644
--- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/list_usage_results.tsx
+++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/list_usage_results.tsx
@@ -10,7 +10,8 @@ import { EuiFieldSearch, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { InferenceUsageInfo } from '../../../../types';
import * as i18n from '../delete/confirm_delete_endpoint/translations';
-import { UsageItem } from './usage_item';
+import { IndexItem } from './index_item';
+import { PipelineItem } from './pipeline_item';
interface ListUsageResultsProps {
list: InferenceUsageInfo[];
@@ -35,9 +36,13 @@ export const ListUsageResults: React.FC = ({ list }) => {
{list
.filter((item) => item.id.toLowerCase().includes(term.toLowerCase()))
- .map((item, id) => (
-
- ))}
+ .map((item, id) => {
+ if (item.type === 'Pipeline') {
+ return ;
+ } else {
+ return ;
+ }
+ })}
);
diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/usage_item.test.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.test.tsx
similarity index 59%
rename from x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/usage_item.test.tsx
rename to x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.test.tsx
index 6c6899c71922d..8a1bc7a78cab2 100644
--- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/usage_item.test.tsx
+++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.test.tsx
@@ -8,7 +8,7 @@
import { render, fireEvent, screen } from '@testing-library/react';
import React from 'react';
-import { UsageItem } from './usage_item';
+import { PipelineItem } from './pipeline_item';
import { InferenceUsageInfo } from '../../../../types';
import { useKibana } from '../../../../../../hooks/use_kibana';
@@ -16,7 +16,11 @@ jest.mock('../../../../../../hooks/use_kibana');
const mockUseKibana = useKibana as jest.Mock;
const mockNavigateToApp = jest.fn();
-describe('UsageItem', () => {
+describe('Pipeline item', () => {
+ const item: InferenceUsageInfo = {
+ id: 'pipeline-1',
+ type: 'Pipeline',
+ };
beforeEach(() => {
mockUseKibana.mockReturnValue({
services: {
@@ -25,41 +29,10 @@ describe('UsageItem', () => {
},
},
});
- });
-
- describe('index', () => {
- const item: InferenceUsageInfo = {
- id: 'index-1',
- type: 'Index',
- };
-
- beforeEach(() => {
- render();
- });
-
- it('renders', () => {
- expect(screen.getByText('index-1')).toBeInTheDocument();
- expect(screen.getByText('Index')).toBeInTheDocument();
- });
-
- it('opens index in a new tab', () => {
- fireEvent.click(screen.getByRole('button'));
- expect(mockNavigateToApp).toHaveBeenCalledWith('enterpriseSearchContent', {
- openInNewTab: true,
- path: 'search_indices/index-1',
- });
- });
+ render();
});
describe('pipeline', () => {
- const item: InferenceUsageInfo = {
- id: 'pipeline-1',
- type: 'Pipeline',
- };
-
- beforeEach(() => {
- render();
- });
it('renders', () => {
expect(screen.getByText('pipeline-1')).toBeInTheDocument();
expect(screen.getByText('Pipeline')).toBeInTheDocument();
diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.tsx
new file mode 100644
index 0000000000000..1a2e8ead29080
--- /dev/null
+++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/pipeline_item.tsx
@@ -0,0 +1,69 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import {
+ EuiBadge,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiHorizontalRule,
+ EuiLink,
+ EuiText,
+ EuiTextTruncate,
+ EuiIcon,
+ EuiSpacer,
+} from '@elastic/eui';
+import React, { useCallback } from 'react';
+import { MANAGEMENT_APP_ID } from '@kbn/deeplinks-management/constants';
+
+import { useKibana } from '../../../../../../hooks/use_kibana';
+import { InferenceUsageInfo } from '../../../../types';
+import { PIPELINE_URL } from '../../../../constants';
+
+interface UsageProps {
+ usageItem: InferenceUsageInfo;
+}
+export const PipelineItem: React.FC = ({ usageItem }) => {
+ const {
+ services: { application },
+ } = useKibana();
+ const navigateToPipeline = useCallback(() => {
+ application?.navigateToApp(MANAGEMENT_APP_ID, {
+ path: `${PIPELINE_URL}?pipeline=${usageItem.id}`,
+ openInNewTab: true,
+ });
+ }, [application, usageItem.id]);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ {usageItem.type}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/scan_usage_results.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/scan_usage_results.tsx
index 33d7a4dae891f..cab278f5e1ed9 100644
--- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/scan_usage_results.tsx
+++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/component/scan_usage_results.tsx
@@ -19,6 +19,7 @@ import { euiThemeVars } from '@kbn/ui-theme';
import { css } from '@emotion/react';
import { ENTERPRISE_SEARCH_CONTENT_APP_ID } from '@kbn/deeplinks-search';
+import { SEARCH_INDICES } from '@kbn/deeplinks-search/constants';
import { InferenceUsageInfo } from '../../../../types';
import { useKibana } from '../../../../../../hooks/use_kibana';
import { RenderMessageWithIcon } from './render_message_with_icon';
@@ -37,13 +38,19 @@ export const ScanUsageResults: React.FC = ({
onIgnoreWarningCheckboxChange,
}) => {
const {
- services: { application },
+ services: { application, serverless },
} = useKibana();
const handleNavigateToIndexManagement = () => {
- application?.navigateToApp(ENTERPRISE_SEARCH_CONTENT_APP_ID, {
- path: 'search_indices',
- openInNewTab: true,
- });
+ if (serverless) {
+ application?.navigateToApp(SEARCH_INDICES, {
+ openInNewTab: true,
+ });
+ } else {
+ application?.navigateToApp(ENTERPRISE_SEARCH_CONTENT_APP_ID, {
+ path: `search_indices`,
+ openInNewTab: true,
+ });
+ }
};
return (
diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/delete/confirm_delete_endpoint/index.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/delete/confirm_delete_endpoint/index.tsx
index 06bd585c0eb28..345f0f81b0927 100644
--- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/delete/confirm_delete_endpoint/index.tsx
+++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_actions/actions/delete/confirm_delete_endpoint/index.tsx
@@ -86,6 +86,7 @@ export const ConfirmDeleteEndpointModal: React.FC
{inferenceEndpoint.endpoint}
diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/tabular_page.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/tabular_page.tsx
index 4cf4b3112396d..0ea17fa6408a0 100644
--- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/tabular_page.tsx
+++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/tabular_page.tsx
@@ -52,6 +52,7 @@ export const TabularPage: React.FC = ({ inferenceEndpoints })
{
field: 'endpoint',
name: i18n.ENDPOINT,
+ 'data-test-subj': 'endpointCell',
render: (endpoint: string) => {
if (endpoint) {
return ;
@@ -65,6 +66,7 @@ export const TabularPage: React.FC = ({ inferenceEndpoints })
{
field: 'provider',
name: i18n.SERVICE_PROVIDER,
+ 'data-test-subj': 'providerCell',
render: (provider: InferenceAPIConfigResponse) => {
if (provider) {
return ;
@@ -78,6 +80,7 @@ export const TabularPage: React.FC = ({ inferenceEndpoints })
{
field: 'type',
name: i18n.TASK_TYPE,
+ 'data-test-subj': 'typeCell',
render: (type: TaskTypes) => {
if (type) {
return ;
@@ -149,6 +152,7 @@ export const TabularPage: React.FC = ({ inferenceEndpoints })
onChange={handleTableChange}
pagination={pagination}
sorting={sorting}
+ data-test-subj="inferenceEndpointTable"
/>
diff --git a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.scss b/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.scss
deleted file mode 100644
index b85859948b0be..0000000000000
--- a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.addEmptyPrompt {
- max-width: 860px;
-}
\ No newline at end of file
diff --git a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.test.tsx b/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.test.tsx
deleted file mode 100644
index 755c1f0a1de54..0000000000000
--- a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.test.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import React from 'react';
-import { screen } from '@testing-library/react';
-import { AddEmptyPrompt } from './add_empty_prompt';
-
-import { renderReactTestingLibraryWithI18n as render } from '@kbn/test-jest-helpers';
-import '@testing-library/jest-dom';
-
-describe('When empty prompt is loaded', () => {
- beforeEach(() => {
- render();
- });
-
- it('should display the description for creation of the first inference endpoint', () => {
- expect(
- screen.getByText(
- /Inference endpoints enable you to perform inference tasks using NLP models provided by third-party services/
- )
- ).toBeInTheDocument();
- });
-
- it('should have a learn-more link', () => {
- const learnMoreLink = screen.getByTestId('learn-how-to-create-inference-endpoints');
- expect(learnMoreLink).toBeInTheDocument();
- });
-
- it('should have a view-your-models link', () => {
- const learnMoreLink = screen.getByTestId('view-your-models');
- expect(learnMoreLink).toBeInTheDocument();
- });
-
- it('should have a semantic-search-with-elser link', () => {
- const learnMoreLink = screen.getByTestId('semantic-search-with-elser');
- expect(learnMoreLink).toBeInTheDocument();
- });
-
- it('should have a semantic-search-with-e5 link', () => {
- const learnMoreLink = screen.getByTestId('semantic-search-with-e5');
- expect(learnMoreLink).toBeInTheDocument();
- });
-});
diff --git a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.tsx b/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.tsx
deleted file mode 100644
index 782994975ada4..0000000000000
--- a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.tsx
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import React from 'react';
-
-import {
- EuiPageTemplate,
- EuiFlexGroup,
- EuiFlexItem,
- EuiImage,
- EuiSpacer,
- EuiLink,
-} from '@elastic/eui';
-import { docLinks } from '../../../common/doc_links';
-
-import * as i18n from '../../../common/translations';
-
-import inferenceEndpoint from '../../assets/images/inference_endpoint.svg';
-
-import { EndpointPrompt } from './endpoint_prompt';
-import { useTrainedModelPageUrl } from '../../hooks/use_trained_model_page_url';
-
-import './add_empty_prompt.scss';
-
-export const AddEmptyPrompt: React.FC = () => {
- const trainedModelPageUrl = useTrainedModelPageUrl();
-
- return (
- }
- title={{i18n.INFERENCE_ENDPOINT_LABEL}
}
- body={
-
-
- {i18n.CREATE_FIRST_INFERENCE_ENDPOINT_DESCRIPTION}
-
-
-
- {i18n.LEARN_HOW_TO_CREATE_INFERENCE_ENDPOINTS_LINK}
-
-
-
-
- {i18n.VIEW_YOUR_MODELS_LINK}
-
-
-
- }
- footer={
-
-
- {i18n.START_WITH_PREPARED_ENDPOINTS_LABEL}
-
-
-
-
-
- {i18n.SEMANTIC_SEARCH_WITH_ELSER_LINK}
-
- }
- />
-
-
-
- {i18n.SEMANTIC_SEARCH_WITH_E5_LINK}
-
- }
- />
-
-
-
- }
- />
- );
-};
diff --git a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/endpoint_prompt.tsx b/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/endpoint_prompt.tsx
deleted file mode 100644
index aa6ff9d582e10..0000000000000
--- a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/endpoint_prompt.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import React from 'react';
-import { EuiCard } from '@elastic/eui';
-
-interface EndpointPromptProps {
- title: string;
- description: string;
- footer: React.ReactElement;
-}
-
-export const EndpointPrompt: React.FC = ({ title, description, footer }) => (
-
-);
diff --git a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/index.ts b/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/index.ts
deleted file mode 100644
index dcb2d12f6c986..0000000000000
--- a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/index.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-export { AddEmptyPrompt } from './add_empty_prompt';
diff --git a/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints.tsx b/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints.tsx
index e1dae72d402f7..c39bc69fc300b 100644
--- a/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints.tsx
+++ b/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints.tsx
@@ -11,7 +11,6 @@ import { EuiPageTemplate } from '@elastic/eui';
import { useQueryInferenceEndpoints } from '../hooks/use_inference_endpoints';
import { TabularPage } from './all_inference_endpoints/tabular_page';
-import { AddEmptyPrompt } from './empty_prompt/add_empty_prompt';
import { InferenceEndpointsHeader } from './inference_endpoints_header';
export const InferenceEndpoints: React.FC = () => {
@@ -21,13 +20,9 @@ export const InferenceEndpoints: React.FC = () => {
return (
<>
- {inferenceEndpoints.length > 0 && }
-
- {inferenceEndpoints.length === 0 ? (
-
- ) : (
-
- )}
+
+
+
>
);
diff --git a/x-pack/plugins/search_inference_endpoints/public/locators.ts b/x-pack/plugins/search_inference_endpoints/public/locators.ts
new file mode 100644
index 0000000000000..5b32e5648cc7c
--- /dev/null
+++ b/x-pack/plugins/search_inference_endpoints/public/locators.ts
@@ -0,0 +1,29 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import type { LocatorDefinition } from '@kbn/share-plugin/common';
+import type { SharePluginSetup } from '@kbn/share-plugin/public';
+import type { SerializableRecord } from '@kbn/utility-types';
+
+import { PLUGIN_ID } from '../common/constants';
+import { SEARCH_INFERENCE_ENDPOINTS_PATH } from './routes';
+
+export function registerLocators(share: SharePluginSetup) {
+ share.url.locators.create(new SearchInferenceEndpointLocatorDefinition());
+}
+
+class SearchInferenceEndpointLocatorDefinition implements LocatorDefinition {
+ public readonly getLocation = async () => {
+ return {
+ app: PLUGIN_ID,
+ path: SEARCH_INFERENCE_ENDPOINTS_PATH,
+ state: {},
+ };
+ };
+
+ public readonly id = 'SEARCH_INFERENCE_ENDPOINTS';
+}
diff --git a/x-pack/plugins/search_inference_endpoints/public/plugin.ts b/x-pack/plugins/search_inference_endpoints/public/plugin.ts
index a864b7c0fcdd6..cb60f611b3bb3 100644
--- a/x-pack/plugins/search_inference_endpoints/public/plugin.ts
+++ b/x-pack/plugins/search_inference_endpoints/public/plugin.ts
@@ -12,16 +12,20 @@ import {
Plugin,
PluginInitializerContext,
} from '@kbn/core/public';
+import { i18n } from '@kbn/i18n';
import { PLUGIN_ID, PLUGIN_NAME } from '../common/constants';
import { docLinks } from '../common/doc_links';
import { InferenceEndpoints, getInferenceEndpointsProvider } from './embeddable';
import {
+ AppPluginSetupDependencies,
AppPluginStartDependencies,
SearchInferenceEndpointsConfigType,
SearchInferenceEndpointsPluginSetup,
SearchInferenceEndpointsPluginStart,
} from './types';
import { INFERENCE_ENDPOINTS_UI_FLAG } from '.';
+import { registerLocators } from './locators';
+import { INFERENCE_ENDPOINTS_PATH } from './components/routes';
export class SearchInferenceEndpointsPlugin
implements Plugin
@@ -33,7 +37,8 @@ export class SearchInferenceEndpointsPlugin
}
public setup(
- core: CoreSetup
+ core: CoreSetup,
+ plugins: AppPluginSetupDependencies
): SearchInferenceEndpointsPluginSetup {
if (
!this.config.ui?.enabled &&
@@ -42,7 +47,16 @@ export class SearchInferenceEndpointsPlugin
return {};
core.application.register({
id: PLUGIN_ID,
- appRoute: '/app/search_inference_endpoints',
+ appRoute: '/app/elasticsearch/relevance',
+ deepLinks: [
+ {
+ id: 'inferenceEndpoints',
+ path: `/${INFERENCE_ENDPOINTS_PATH}`,
+ title: i18n.translate('xpack.searchInferenceEndpoints.InferenceEndpointsLinkLabel', {
+ defaultMessage: 'Inference Endpoints',
+ }),
+ },
+ ],
title: PLUGIN_NAME,
async mount({ element, history }: AppMountParameters) {
const { renderApp } = await import('./application');
@@ -56,6 +70,8 @@ export class SearchInferenceEndpointsPlugin
},
});
+ registerLocators(plugins.share);
+
return {};
}
diff --git a/x-pack/plugins/search_inference_endpoints/public/types.ts b/x-pack/plugins/search_inference_endpoints/public/types.ts
index 4bd83521cf8d6..9f73d0d0033b0 100644
--- a/x-pack/plugins/search_inference_endpoints/public/types.ts
+++ b/x-pack/plugins/search_inference_endpoints/public/types.ts
@@ -5,12 +5,14 @@
* 2.0.
*/
-import type { ConsolePluginStart } from '@kbn/console-plugin/public';
+import type { ConsolePluginSetup, ConsolePluginStart } from '@kbn/console-plugin/public';
import { HttpStart } from '@kbn/core-http-browser';
import { AppMountParameters } from '@kbn/core/public';
import { MlPluginStart } from '@kbn/ml-plugin/public';
-import { SharePluginStart } from '@kbn/share-plugin/public';
+import { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public';
import React from 'react';
+
+import type { ServerlessPluginStart } from '@kbn/serverless/public';
import type { App } from './components/app';
import type { InferenceEndpointsProvider } from './providers/inference_endpoints_provider';
@@ -27,12 +29,21 @@ export interface AppPluginStartDependencies {
history: AppMountParameters['history'];
share: SharePluginStart;
console?: ConsolePluginStart;
+ serverless?: ServerlessPluginStart;
+}
+
+export interface AppPluginSetupDependencies {
+ history: AppMountParameters['history'];
+ share: SharePluginSetup;
+ console?: ConsolePluginSetup;
}
export interface AppServicesContext {
http: HttpStart;
ml?: MlPluginStart;
console?: ConsolePluginStart;
+ serverless?: ServerlessPluginStart;
+ share: SharePluginStart;
}
export interface InferenceUsageResponse {
diff --git a/x-pack/plugins/search_inference_endpoints/tsconfig.json b/x-pack/plugins/search_inference_endpoints/tsconfig.json
index d454be99b65f0..9a5b160779e7a 100644
--- a/x-pack/plugins/search_inference_endpoints/tsconfig.json
+++ b/x-pack/plugins/search_inference_endpoints/tsconfig.json
@@ -33,7 +33,9 @@
"@kbn/features-plugin",
"@kbn/ui-theme",
"@kbn/deeplinks-search",
- "@kbn/deeplinks-management"
+ "@kbn/deeplinks-management",
+ "@kbn/serverless",
+ "@kbn/utility-types"
],
"exclude": [
"target/**/*",
diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json
index ada6529e8d325..77cb502273850 100644
--- a/x-pack/plugins/translations/translations/fr-FR.json
+++ b/x-pack/plugins/translations/translations/fr-FR.json
@@ -36024,15 +36024,6 @@
"xpack.searchInferenceEndpoints.actions.endpointAddedSuccess": "Point de terminaison ajouté",
"xpack.searchInferenceEndpoints.actions.endpointAddedSuccessDescription": "Le point de terminaison d'inférence \"{endpointId}\" a été ajouté.",
"xpack.searchInferenceEndpoints.actions.trainedModelsStatGatherFailed": "Échec de la récupération des statistiques du modèle entraîné",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.createFirstInferenceEndpointDescription": "Les points de terminaison d'inférence vous permettent d'effectuer des tâches d'inférence à l'aide de modèles NLP fournis par des services tiers ou de modèles intégrés d'Elastic comme ELSER et E5. Configurez des tâches telles que l'incorporation de texte, les complétions, le reclassement et bien plus encore à l'aide de la fonction Créer une API d'inférence.",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.e5Description": "E5 est un modèle NLP tiers qui vous permet de réaliser des recherches sémantiques multilingues en utilisant des représentations vectorielles denses.",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.e5Title": "E5 multilingue",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.elserDescription": "ELSER est le modèle NLP vectoriel creux d'Elastic pour la recherche sémantique en anglais.",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.elserTitle": "ELSER",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.learnHowToCreateInferenceEndpoints": "Découvrez comment créer des points de terminaison d'inférence",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithE5": "Recherche sémantique avec E5 multilingue",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithElser": "Recherche sémantique avec ELSER",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.startWithPreparedEndpointsLabel": "En savoir plus sur les modèles NLP intégrés :",
"xpack.searchInferenceEndpoints.allInferenceEndpoints.description": "Les points de terminaison d'inférence rationalisent le déploiement et la gestion des modèles d'apprentissage automatique dans Elasticsearch. Configurez et gérez des tâches NLP à l'aide de points de terminaison uniques afin de créer une recherche basée sur l'IA.",
"xpack.searchInferenceEndpoints.apiDocumentationLink": "Documentation sur les API",
"xpack.searchInferenceEndpoints.cancel": "Annuler",
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 00e756f7bbfd8..c199283dd34af 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -35993,15 +35993,6 @@
"xpack.searchInferenceEndpoints.actions.endpointAddedSuccess": "エンドポイントが追加されました",
"xpack.searchInferenceEndpoints.actions.endpointAddedSuccessDescription": "インターフェースエンドポイント\"{endpointId}\"が追加されました。",
"xpack.searchInferenceEndpoints.actions.trainedModelsStatGatherFailed": "学習済みモデル統計情報を取得できませんでした",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.createFirstInferenceEndpointDescription": "推論エンドポイントを使用すると、サードパーティサービスが提供するNLPモデルや、ELSERやE5などのElasticの組み込みモデルを使用して推論タスクを実行できます。Create Inference APIを使用して、テキスト埋め込み、入力、再ランク付けなどのタスクを設定します。",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.e5Description": "E5は、密ベクトル表現を使用して、多言語のセマンティック検索を可能にするサードパーティNLPモデルです。",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.e5Title": "E5 Multilingual",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.elserDescription": "ELSERは、英語でのセマンティック検索向けにElasticの疎ベクトルNLPモデルです。",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.elserTitle": "ELSER",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.learnHowToCreateInferenceEndpoints": "推論エンドポイントを作成する方法",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithE5": "E5 Multilingualを使用したセマンティック検索",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithElser": "ELSERを使用したセマンティック検索",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.startWithPreparedEndpointsLabel": "組み込まれたNLPモデルの詳細:",
"xpack.searchInferenceEndpoints.allInferenceEndpoints.description": "推論エンドポイントは、Elasticsearchにおける機械学習モデルのデプロイと管理を合理化します。独自のエンドポイントを使用してNLPタスクを設定および管理し、AIを活用した検索を構築します。",
"xpack.searchInferenceEndpoints.apiDocumentationLink": "APIドキュメント",
"xpack.searchInferenceEndpoints.cancel": "キャンセル",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 3c58620180775..0588fe925cb72 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -35433,15 +35433,6 @@
"xpack.searchInferenceEndpoints.actions.endpointAddedFailure": "终端创建失败",
"xpack.searchInferenceEndpoints.actions.endpointAddedSuccess": "已添加终端",
"xpack.searchInferenceEndpoints.actions.trainedModelsStatGatherFailed": "无法检索已训练模型统计信息",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.createFirstInferenceEndpointDescription": "利用推理终端,您可以使用由第三方服务提供的 NLP 模型或 ELSER 和 E5 等 Elastic 内置模型来执行推理任务。通过使用创建推理 API 来设置任务,如文本嵌入、完成、重新排名等。",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.e5Description": "E5 是一个第三方 NLP 模型,它允许您通过使用密集向量表示方法来执行多语言语义搜索。",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.e5Title": "E5 多语言",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.elserDescription": "ELSER 是 Elastic 的英文版稀疏向量语义搜索 NLP 模型。",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.elserTitle": "ELSER",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.learnHowToCreateInferenceEndpoints": "了解如何创建推理终端",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithE5": "利用 E5 多语言版进行语义搜索",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithElser": "利用 ELSER 进行语义搜索",
- "xpack.searchInferenceEndpoints.addEmptyPrompt.startWithPreparedEndpointsLabel": "详细了解内置 NLP 模型:",
"xpack.searchInferenceEndpoints.allInferenceEndpoints.description": "推理终端简化了 Elasticsearch 中的 Machine Learning 模型部署和管理。使用唯一的终端来设置和管理 NLP 任务,以构建 AI 驱动式搜索。",
"xpack.searchInferenceEndpoints.apiDocumentationLink": "API 文档",
"xpack.searchInferenceEndpoints.cancel": "取消",
diff --git a/x-pack/test_serverless/functional/page_objects/index.ts b/x-pack/test_serverless/functional/page_objects/index.ts
index 2c894b28b065f..e10e98529b8bf 100644
--- a/x-pack/test_serverless/functional/page_objects/index.ts
+++ b/x-pack/test_serverless/functional/page_objects/index.ts
@@ -25,6 +25,7 @@ import { SvlSearchIndexDetailPageProvider } from './svl_search_index_detail_page
import { SvlSearchElasticsearchStartPageProvider } from './svl_search_elasticsearch_start_page';
import { SvlApiKeysProvider } from './svl_api_keys';
import { SvlSearchCreateIndexPageProvider } from './svl_search_create_index_page';
+import { SvlSearchInferenceManagementPageProvider } from './svl_search_inference_management_page';
export const pageObjects = {
...xpackFunctionalPageObjects,
@@ -47,4 +48,5 @@ export const pageObjects = {
svlSearchElasticsearchStartPage: SvlSearchElasticsearchStartPageProvider,
svlApiKeys: SvlApiKeysProvider,
svlSearchCreateIndexPage: SvlSearchCreateIndexPageProvider,
+ svlSearchInferenceManagementPage: SvlSearchInferenceManagementPageProvider,
};
diff --git a/x-pack/test_serverless/functional/page_objects/svl_search_inference_management_page.ts b/x-pack/test_serverless/functional/page_objects/svl_search_inference_management_page.ts
new file mode 100644
index 0000000000000..4424238a9c809
--- /dev/null
+++ b/x-pack/test_serverless/functional/page_objects/svl_search_inference_management_page.ts
@@ -0,0 +1,127 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import expect from '@kbn/expect';
+import { FtrProviderContext } from '../ftr_provider_context';
+
+export function SvlSearchInferenceManagementPageProvider({ getService }: FtrProviderContext) {
+ const testSubjects = getService('testSubjects');
+ const browser = getService('browser');
+
+ return {
+ InferenceTabularPage: {
+ async expectHeaderToBeExist() {
+ await testSubjects.existOrFail('allInferenceEndpointsPage');
+ await testSubjects.existOrFail('api-documentation');
+ await testSubjects.existOrFail('view-your-models');
+ },
+
+ async expectTabularViewToBeLoaded() {
+ await testSubjects.existOrFail('search-field-endpoints');
+ await testSubjects.existOrFail('type-field-endpoints');
+ await testSubjects.existOrFail('service-field-endpoints');
+
+ const table = await testSubjects.find('inferenceEndpointTable');
+ const rows = await table.findAllByClassName('euiTableRow');
+ expect(rows.length).to.equal(2);
+
+ const elserEndpointCell = await rows[0].findByTestSubject('endpointCell');
+ const elserEndpointName = await elserEndpointCell.getVisibleText();
+ expect(elserEndpointName).to.contain('.elser-2-elasticsearch');
+
+ const elserProviderCell = await rows[0].findByTestSubject('providerCell');
+ const elserProviderName = await elserProviderCell.getVisibleText();
+ expect(elserProviderName).to.contain('Elasticsearch');
+ expect(elserProviderName).to.contain('.elser_model_2');
+
+ const elserTypeCell = await rows[0].findByTestSubject('typeCell');
+ const elserTypeName = await elserTypeCell.getVisibleText();
+ expect(elserTypeName).to.contain('sparse_embedding');
+
+ const e5EndpointCell = await rows[1].findByTestSubject('endpointCell');
+ const e5EndpointName = await e5EndpointCell.getVisibleText();
+ expect(e5EndpointName).to.contain('.multilingual-e5-small-elasticsearch');
+
+ const e5ProviderCell = await rows[1].findByTestSubject('providerCell');
+ const e5ProviderName = await e5ProviderCell.getVisibleText();
+ expect(e5ProviderName).to.contain('Elasticsearch');
+ expect(e5ProviderName).to.contain('.multilingual-e5-small');
+
+ const e5TypeCell = await rows[1].findByTestSubject('typeCell');
+ const e5TypeName = await e5TypeCell.getVisibleText();
+ expect(e5TypeName).to.contain('text_embedding');
+ },
+
+ async expectPreconfiguredEndpointsCannotBeDeleted() {
+ const table = await testSubjects.find('inferenceEndpointTable');
+ const rows = await table.findAllByClassName('euiTableRow');
+
+ const elserDeleteAction = await rows[0].findByTestSubject('inferenceUIDeleteAction');
+ const e5DeleteAction = await rows[1].findByTestSubject('inferenceUIDeleteAction');
+
+ expect(await elserDeleteAction.isEnabled()).to.be(false);
+ expect(await e5DeleteAction.isEnabled()).to.be(false);
+ },
+
+ async expectEndpointWithoutUsageTobeDelete() {
+ const table = await testSubjects.find('inferenceEndpointTable');
+ const rows = await table.findAllByClassName('euiTableRow');
+
+ const userCreatedEndpoint = await rows[2].findByTestSubject('inferenceUIDeleteAction');
+
+ await userCreatedEndpoint.click();
+ await testSubjects.existOrFail('deleteModalForInferenceUI');
+ await testSubjects.existOrFail('deleteModalInferenceEndpointName');
+
+ await testSubjects.click('confirmModalConfirmButton');
+
+ await testSubjects.existOrFail('inferenceEndpointTable');
+ },
+
+ async expectEndpointWithUsageTobeDelete() {
+ const table = await testSubjects.find('inferenceEndpointTable');
+ const rows = await table.findAllByClassName('euiTableRow');
+
+ const userCreatedEndpoint = await rows[2].findByTestSubject('inferenceUIDeleteAction');
+
+ await userCreatedEndpoint.click();
+ await testSubjects.existOrFail('deleteModalForInferenceUI');
+ await testSubjects.existOrFail('deleteModalInferenceEndpointName');
+
+ const items = await testSubjects.findAll('usageItem');
+ expect(items.length).to.equal(2);
+
+ const index = await items[0].getVisibleText();
+ const pipeline = await items[1].getVisibleText();
+
+ expect(index.includes('elser_index')).to.be(true);
+ expect(pipeline.includes('endpoint-1')).to.be(true);
+
+ expect(await testSubjects.isEnabled('confirmModalConfirmButton')).to.be(false);
+
+ await testSubjects.click('warningCheckbox');
+
+ expect(await testSubjects.isEnabled('confirmModalConfirmButton')).to.be(true);
+ await testSubjects.click('confirmModalConfirmButton');
+
+ await testSubjects.existOrFail('inferenceEndpointTable');
+ },
+
+ async expectToCopyEndpoint() {
+ const table = await testSubjects.find('inferenceEndpointTable');
+ const rows = await table.findAllByClassName('euiTableRow');
+
+ const elserCopyEndpointId = await rows[0].findByTestSubject(
+ 'inference-endpoints-action-copy-id-label'
+ );
+
+ await elserCopyEndpointId.click();
+ expect((await browser.getClipboardValue()).includes('.elser-2-elasticsearch')).to.be(true);
+ },
+ },
+ };
+}
diff --git a/x-pack/test_serverless/functional/services/svl_search_navigation.ts b/x-pack/test_serverless/functional/services/svl_search_navigation.ts
index 1f27cf18ec8cb..434a5bd4e42ab 100644
--- a/x-pack/test_serverless/functional/services/svl_search_navigation.ts
+++ b/x-pack/test_serverless/functional/services/svl_search_navigation.ts
@@ -47,5 +47,10 @@ export function SvlSearchNavigationServiceProvider({
});
await testSubjects.existOrFail('searchIndicesDetailsPage', { timeout: 2000 });
},
+ async navigateToInferenceManagementPage(expectRedirect: boolean = false) {
+ await PageObjects.common.navigateToApp('searchInferenceEndpoints', {
+ shouldLoginIfPrompted: false,
+ });
+ },
};
}
diff --git a/x-pack/test_serverless/functional/test_suites/search/config.ts b/x-pack/test_serverless/functional/test_suites/search/config.ts
index 5c52828a11659..47763068455b5 100644
--- a/x-pack/test_serverless/functional/test_suites/search/config.ts
+++ b/x-pack/test_serverless/functional/test_suites/search/config.ts
@@ -45,5 +45,8 @@ export default createTestConfig({
elasticsearchIndices: {
pathname: '/app/elasticsearch/indices',
},
+ searchInferenceEndpoints: {
+ pathname: '/app/elasticsearch/relevance/inference_endpoints',
+ },
},
});
diff --git a/x-pack/test_serverless/functional/test_suites/search/index.ts b/x-pack/test_serverless/functional/test_suites/search/index.ts
index 99190ae0cc072..dd7021aebe800 100644
--- a/x-pack/test_serverless/functional/test_suites/search/index.ts
+++ b/x-pack/test_serverless/functional/test_suites/search/index.ts
@@ -28,5 +28,6 @@ export default function ({ loadTestFile }: FtrProviderContext) {
loadTestFile(require.resolve('./search_playground/playground_overview'));
loadTestFile(require.resolve('./ml'));
loadTestFile(require.resolve('./custom_role_access'));
+ loadTestFile(require.resolve('./inference_management'));
});
}
diff --git a/x-pack/test_serverless/functional/test_suites/search/inference_management.ts b/x-pack/test_serverless/functional/test_suites/search/inference_management.ts
new file mode 100644
index 0000000000000..f820b9bb08085
--- /dev/null
+++ b/x-pack/test_serverless/functional/test_suites/search/inference_management.ts
@@ -0,0 +1,103 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
+
+import { testHasEmbeddedConsole } from './embedded_console';
+
+import { FtrProviderContext } from '../../ftr_provider_context';
+
+export default function ({ getPageObjects, getService }: FtrProviderContext) {
+ const pageObjects = getPageObjects([
+ 'svlCommonPage',
+ 'embeddedConsole',
+ 'svlSearchInferenceManagementPage',
+ ]);
+ const svlSearchNavigation = getService('svlSearchNavigation');
+ const browser = getService('browser');
+ const ml = getService('ml');
+
+ describe('Serverless Inference Management UI', function () {
+ const endpoint = 'endpoint-1';
+ const taskType = 'sparse_embedding';
+ const modelConfig = {
+ service: 'elser',
+ service_settings: {
+ num_allocations: 1,
+ num_threads: 1,
+ },
+ };
+
+ before(async () => {
+ await pageObjects.svlCommonPage.loginWithRole('developer');
+ });
+
+ after(async () => {
+ await ml.api.cleanMlIndices();
+ });
+
+ beforeEach(async () => {
+ await svlSearchNavigation.navigateToInferenceManagementPage();
+ });
+
+ describe('endpoint tabular view', () => {
+ it('is loaded successfully', async () => {
+ await pageObjects.svlSearchInferenceManagementPage.InferenceTabularPage.expectHeaderToBeExist();
+ await pageObjects.svlSearchInferenceManagementPage.InferenceTabularPage.expectTabularViewToBeLoaded();
+ });
+
+ it('preconfigured endpoints can not be deleted', async () => {
+ await pageObjects.svlSearchInferenceManagementPage.InferenceTabularPage.expectPreconfiguredEndpointsCannotBeDeleted();
+ });
+ });
+
+ describe('copy endpoint id action', () => {
+ it('can copy an endpoint id', async () => {
+ await pageObjects.svlSearchInferenceManagementPage.InferenceTabularPage.expectToCopyEndpoint();
+ });
+ });
+
+ describe('delete action', () => {
+ const usageIndex = 'elser_index';
+ beforeEach(async () => {
+ await ml.api.createInferenceEndpoint(endpoint, taskType, modelConfig);
+ await browser.refresh();
+ });
+
+ after(async () => {
+ await ml.api.deleteIndices(usageIndex);
+ await ml.api.deleteIngestPipeline(endpoint);
+ });
+
+ it('deletes modal successfully without any usage', async () => {
+ await pageObjects.svlSearchInferenceManagementPage.InferenceTabularPage.expectEndpointWithoutUsageTobeDelete();
+ });
+
+ it('deletes modal successfully with usage', async () => {
+ const indexMapping: estypes.MappingTypeMapping = {
+ properties: {
+ content: {
+ type: 'text',
+ },
+ content_embedding: {
+ type: 'semantic_text',
+ inference_id: endpoint,
+ },
+ },
+ };
+ await ml.api.createIngestPipeline(endpoint);
+ await ml.api.createIndex(usageIndex, indexMapping);
+
+ await pageObjects.svlSearchInferenceManagementPage.InferenceTabularPage.expectEndpointWithUsageTobeDelete();
+ });
+ });
+
+ it('has embedded dev console', async () => {
+ await testHasEmbeddedConsole(pageObjects);
+ });
+ });
+}
diff --git a/x-pack/test_serverless/functional/test_suites/search/navigation.ts b/x-pack/test_serverless/functional/test_suites/search/navigation.ts
index 24009866b2b15..74d1c59cbc8e5 100644
--- a/x-pack/test_serverless/functional/test_suites/search/navigation.ts
+++ b/x-pack/test_serverless/functional/test_suites/search/navigation.ts
@@ -95,17 +95,17 @@ export default function ({ getPageObject, getService }: FtrProviderContext) {
});
// check Relevance
// > Inference Endpoints
- // await solutionNavigation.sidenav.clickLink({
- // deepLinkId: 'searchInferenceEndpoints',
- // });
- // await solutionNavigation.sidenav.expectLinkActive({
- // deepLinkId: 'searchInferenceEndpoints',
- // });
- // await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Relevance' });
- // await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Inference Endpoints' });
- // await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
- // deepLinkId: 'searchInferenceEndpoints',
- // });
+ await solutionNavigation.sidenav.clickLink({
+ deepLinkId: 'searchInferenceEndpoints',
+ });
+ await solutionNavigation.sidenav.expectLinkActive({
+ deepLinkId: 'searchInferenceEndpoints',
+ });
+ await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Relevance' });
+ await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Inference Endpoints' });
+ await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
+ deepLinkId: 'searchInferenceEndpoints',
+ });
// check Analyze
// > Discover
@@ -245,8 +245,8 @@ export default function ({ getPageObject, getService }: FtrProviderContext) {
await solutionNavigation.sidenav.expectLinkExists({ text: 'Build' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Dev Tools' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Playground' });
- // await solutionNavigation.sidenav.expectLinkExists({ text: 'Relevance' });
- // await solutionNavigation.sidenav.expectLinkExists({ text: 'Inference Endpoints' });
+ await solutionNavigation.sidenav.expectLinkExists({ text: 'Relevance' });
+ await solutionNavigation.sidenav.expectLinkExists({ text: 'Inference Endpoints' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Analyze' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Discover' });
await solutionNavigation.sidenav.expectLinkExists({ text: 'Dashboards' });
@@ -270,8 +270,8 @@ export default function ({ getPageObject, getService }: FtrProviderContext) {
'build',
'dev_tools',
'searchPlayground',
- // 'relevance',
- // 'searchInferenceEndpoints',
+ 'relevance',
+ 'searchInferenceEndpoints',
'analyze',
'discover',
'dashboards',
From 1b742e77f41c6b0674ee01c28b17171508cb5784 Mon Sep 17 00:00:00 2001
From: Alexey Antonov
Date: Fri, 22 Nov 2024 21:38:24 +0200
Subject: [PATCH 20/38] fix: [Search:Search Applications page]Popover for
Create button is inaccessible via keyboard (#201193)
Closes: #199760
Popovers, dialogs which are accessible with mouse, should also be
accessible with keyboard. Otherwise users using only keyboard will miss
the information present in popover, dialog.
Closes: #199749
User reaches the same button two times when navigating using only
keyboard and it can get confusing. Better for element to get focus only
one time when navigating in sequence from one element to another and for
the user only to hear one announcement of the element.
## What was changed:
1. `CreateSearchApplicationButton` component:
- `EuiPopover` was replaced to more a11y-friendly `EuiToolTip`
- extra `div` element with `tabindex` was removed.
## Screen
https://github.com/user-attachments/assets/fbb62841-6f2f-45d0-bee3-39a11a4fc777
---
...search_applications_create_button.test.tsx | 41 ++++++++++
.../search_applications_list.test.tsx | 79 +-----------------
.../search_applications_list.tsx | 80 ++++++++-----------
3 files changed, 74 insertions(+), 126 deletions(-)
create mode 100644 x-pack/plugins/enterprise_search/public/applications/applications/components/search_applications/search_applications_create_button.test.tsx
diff --git a/x-pack/plugins/enterprise_search/public/applications/applications/components/search_applications/search_applications_create_button.test.tsx b/x-pack/plugins/enterprise_search/public/applications/applications/components/search_applications/search_applications_create_button.test.tsx
new file mode 100644
index 0000000000000..548314dcda43b
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/applications/components/search_applications/search_applications_create_button.test.tsx
@@ -0,0 +1,41 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { type ReactNode } from 'react';
+
+import { render, screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+
+import { waitForEuiToolTipVisible } from '@elastic/eui/lib/test/rtl';
+
+import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';
+
+import { CreateSearchApplicationButton } from './search_applications_list';
+
+function Container({ children }: { children?: ReactNode }) {
+ return {children};
+}
+
+describe('CreateSearchApplicationButton', () => {
+ test('disabled={false}', async () => {
+ render(
+
+
+
+ );
+
+ await userEvent.hover(
+ await screen.findByTestId('enterprise-search-search-applications-creation-button')
+ );
+
+ await waitForEuiToolTipVisible();
+
+ expect(
+ await screen.findByTestId('create-search-application-button-popover-content')
+ ).toBeInTheDocument();
+ });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/applications/components/search_applications/search_applications_list.test.tsx b/x-pack/plugins/enterprise_search/public/applications/applications/components/search_applications/search_applications_list.test.tsx
index f34aac9e4359c..2683a0afc0caa 100644
--- a/x-pack/plugins/enterprise_search/public/applications/applications/components/search_applications/search_applications_list.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/applications/components/search_applications/search_applications_list.test.tsx
@@ -9,7 +9,7 @@ import { setMockActions, setMockValues } from '../../../__mocks__/kea_logic';
import React from 'react';
-import { mountWithIntl, shallowWithIntl } from '@kbn/test-jest-helpers';
+import { shallowWithIntl } from '@kbn/test-jest-helpers';
import { Status } from '../../../../../common/types/api';
@@ -116,80 +116,3 @@ describe('SearchApplicationsList', () => {
expect(wrapper.find(LicensingCallout)).toHaveLength(0);
});
});
-
-describe('CreateSearchApplicationButton', () => {
- describe('disabled={true}', () => {
- it('renders a disabled button that shows a popover when hovered', () => {
- const wrapper = mountWithIntl();
-
- const button = wrapper.find(
- 'button[data-test-subj="enterprise-search-search-applications-creation-button"]'
- );
-
- expect(button).toHaveLength(1);
- expect(button.prop('disabled')).toBeTruthy();
-
- let popover = wrapper.find(
- 'div[data-test-subj="create-search-application-button-popover-content"]'
- );
-
- expect(popover).toHaveLength(0);
-
- const hoverTarget = wrapper.find(
- 'div[data-test-subj="create-search-application-button-hover-target"]'
- );
-
- expect(hoverTarget).toHaveLength(1);
-
- hoverTarget.simulate('mouseEnter');
-
- wrapper.update();
-
- popover = wrapper.find(
- 'div[data-test-subj="create-search-application-button-popover-content"]'
- );
-
- expect(popover).toHaveLength(1);
- expect(popover.text()).toMatch(
- 'This functionality may be changed or removed completely in a future release.'
- );
- });
- });
- describe('disabled={false}', () => {
- it('renders a button and shows a popover when hovered', () => {
- const wrapper = mountWithIntl();
-
- const button = wrapper.find(
- 'button[data-test-subj="enterprise-search-search-applications-creation-button"]'
- );
-
- expect(button).toHaveLength(1);
- expect(button.prop('disabled')).toBeFalsy();
-
- let popover = wrapper.find(
- 'div[data-test-subj="create-search-application-button-popover-content"]'
- );
-
- expect(popover).toHaveLength(0);
-
- const hoverTarget = wrapper.find(
- 'div[data-test-subj="create-search-application-button-hover-target"]'
- );
-
- expect(hoverTarget).toHaveLength(1);
-
- hoverTarget.simulate('mouseEnter');
-
- wrapper.update();
-
- popover = wrapper.find(
- 'div[data-test-subj="create-search-application-button-popover-content"]'
- );
-
- expect(popover).toHaveLength(1);
- expect(popover.text()).toMatch(
- 'This functionality may be changed or removed completely in a future release.'
- );
- });
- });
-});
diff --git a/x-pack/plugins/enterprise_search/public/applications/applications/components/search_applications/search_applications_list.tsx b/x-pack/plugins/enterprise_search/public/applications/applications/components/search_applications/search_applications_list.tsx
index 126c44b6b5dca..fbc07eef5c5e1 100644
--- a/x-pack/plugins/enterprise_search/public/applications/applications/components/search_applications/search_applications_list.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/applications/components/search_applications/search_applications_list.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import React, { useEffect, useState } from 'react';
+import React, { useEffect } from 'react';
import { useActions, useValues } from 'kea';
import useThrottle from 'react-use/lib/useThrottle';
@@ -17,10 +17,9 @@ import {
EuiFlexItem,
EuiIcon,
EuiLink,
- EuiPopover,
- EuiPopoverTitle,
EuiSpacer,
EuiText,
+ EuiToolTip,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
@@ -53,38 +52,10 @@ interface CreateSearchApplicationButtonProps {
export const CreateSearchApplicationButton: React.FC = ({
disabled,
}) => {
- const [showPopover, setShowPopover] = useState(false);
-
return (
- setShowPopover(false)}
- button={
- setShowPopover(true)}
- onMouseLeave={() => setShowPopover(false)}
- tabIndex={0}
- >
- KibanaLogic.values.navigateToUrl(SEARCH_APPLICATION_CREATION_PATH)}
- >
- {i18n.translate(
- 'xpack.enterpriseSearch.searchApplications.list.createSearchApplicationButton.label',
- {
- defaultMessage: 'Create',
- }
- )}
-
-
- }
- >
-
+
@@ -96,23 +67,35 @@ export const CreateSearchApplicationButton: React.FC
-
-
+
+
+ }
+ >
+ KibanaLogic.values.navigateToUrl(SEARCH_APPLICATION_CREATION_PATH)}
>
-
-
-
-
-
-
-
+ {i18n.translate(
+ 'xpack.enterpriseSearch.searchApplications.list.createSearchApplicationButton.label',
+ {
+ defaultMessage: 'Create',
+ }
+ )}
+
+
);
};
+
interface ListProps {
createSearchApplicationFlyoutOpen?: boolean;
}
@@ -223,6 +206,7 @@ export const SearchApplicationsList: React.FC = ({
<>
Date: Fri, 22 Nov 2024 20:04:04 +0000
Subject: [PATCH 21/38] chore(NA): update mocha to v10.8 in buildkite deps
(#201460)
Simple updates mocha in buildkite dependencies.
---
.buildkite/package-lock.json | 243 +++++++++++++++--------------------
.buildkite/package.json | 2 +-
2 files changed, 106 insertions(+), 139 deletions(-)
diff --git a/.buildkite/package-lock.json b/.buildkite/package-lock.json
index 92231d27ea50f..ffec5b75fca68 100644
--- a/.buildkite/package-lock.json
+++ b/.buildkite/package-lock.json
@@ -22,7 +22,7 @@
"@types/mocha": "^10.0.1",
"@types/node": "^15.12.2",
"chai": "^4.3.10",
- "mocha": "^10.3.0",
+ "mocha": "^10.8.2",
"nock": "^12.0.2",
"ts-node": "^10.9.2",
"typescript": "^5.1.6"
@@ -280,6 +280,15 @@
"node": ">=0.4.0"
}
},
+ "node_modules/ansi-colors": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
+ "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
@@ -536,12 +545,12 @@
"dev": true
},
"node_modules/debug": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
- "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"dev": true,
"dependencies": {
- "ms": "2.1.2"
+ "ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
@@ -590,9 +599,9 @@
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
},
"node_modules/diff": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
- "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz",
+ "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
"dev": true,
"engines": {
"node": ">=0.3.1"
@@ -1042,9 +1051,9 @@
}
},
"node_modules/minimatch": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
- "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
"dependencies": {
"brace-expansion": "^2.0.1"
},
@@ -1053,31 +1062,31 @@
}
},
"node_modules/mocha": {
- "version": "10.3.0",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.3.0.tgz",
- "integrity": "sha512-uF2XJs+7xSLsrmIvn37i/wnc91nw7XjOQB8ccyx5aEgdnohr7n+rEiZP23WkCYHjilR6+EboEnbq/ZQDz4LSbg==",
- "dev": true,
- "dependencies": {
- "ansi-colors": "4.1.1",
- "browser-stdout": "1.3.1",
- "chokidar": "3.5.3",
- "debug": "4.3.4",
- "diff": "5.0.0",
- "escape-string-regexp": "4.0.0",
- "find-up": "5.0.0",
- "glob": "8.1.0",
- "he": "1.2.0",
- "js-yaml": "4.1.0",
- "log-symbols": "4.1.0",
- "minimatch": "5.0.1",
- "ms": "2.1.3",
- "serialize-javascript": "6.0.0",
- "strip-json-comments": "3.1.1",
- "supports-color": "8.1.1",
- "workerpool": "6.2.1",
- "yargs": "16.2.0",
- "yargs-parser": "20.2.4",
- "yargs-unparser": "2.0.0"
+ "version": "10.8.2",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz",
+ "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-colors": "^4.1.3",
+ "browser-stdout": "^1.3.1",
+ "chokidar": "^3.5.3",
+ "debug": "^4.3.5",
+ "diff": "^5.2.0",
+ "escape-string-regexp": "^4.0.0",
+ "find-up": "^5.0.0",
+ "glob": "^8.1.0",
+ "he": "^1.2.0",
+ "js-yaml": "^4.1.0",
+ "log-symbols": "^4.1.0",
+ "minimatch": "^5.1.6",
+ "ms": "^2.1.3",
+ "serialize-javascript": "^6.0.2",
+ "strip-json-comments": "^3.1.1",
+ "supports-color": "^8.1.1",
+ "workerpool": "^6.5.1",
+ "yargs": "^16.2.0",
+ "yargs-parser": "^20.2.9",
+ "yargs-unparser": "^2.0.0"
},
"bin": {
"_mocha": "bin/_mocha",
@@ -1087,33 +1096,6 @@
"node": ">= 14.0.0"
}
},
- "node_modules/mocha/node_modules/ansi-colors": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
- "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/mocha/node_modules/minimatch": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
- "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
- "dev": true,
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/mocha/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "dev": true
- },
"node_modules/mocha/node_modules/supports-color": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
@@ -1130,9 +1112,9 @@
}
},
"node_modules/ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
},
"node_modules/nock": {
@@ -1567,9 +1549,9 @@
}
},
"node_modules/workerpool": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
- "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz",
+ "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==",
"dev": true
},
"node_modules/wrap-ansi": {
@@ -1622,9 +1604,9 @@
}
},
"node_modules/yargs-parser": {
- "version": "20.2.4",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
- "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
+ "version": "20.2.9",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
+ "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
"dev": true,
"engines": {
"node": ">=10"
@@ -1893,6 +1875,12 @@
"integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
"dev": true
},
+ "ansi-colors": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
+ "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
+ "dev": true
+ },
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
@@ -2090,12 +2078,12 @@
"dev": true
},
"debug": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
- "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"dev": true,
"requires": {
- "ms": "2.1.2"
+ "ms": "^2.1.3"
}
},
"decamelize": {
@@ -2124,9 +2112,9 @@
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
},
"diff": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
- "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz",
+ "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
"dev": true
},
"dir-glob": {
@@ -2438,62 +2426,41 @@
}
},
"minimatch": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
- "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
"requires": {
"brace-expansion": "^2.0.1"
}
},
"mocha": {
- "version": "10.3.0",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.3.0.tgz",
- "integrity": "sha512-uF2XJs+7xSLsrmIvn37i/wnc91nw7XjOQB8ccyx5aEgdnohr7n+rEiZP23WkCYHjilR6+EboEnbq/ZQDz4LSbg==",
- "dev": true,
- "requires": {
- "ansi-colors": "4.1.1",
- "browser-stdout": "1.3.1",
- "chokidar": "3.5.3",
- "debug": "4.3.4",
- "diff": "5.0.0",
- "escape-string-regexp": "4.0.0",
- "find-up": "5.0.0",
- "glob": "8.1.0",
- "he": "1.2.0",
- "js-yaml": "4.1.0",
- "log-symbols": "4.1.0",
- "minimatch": "5.0.1",
- "ms": "2.1.3",
+ "version": "10.8.2",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz",
+ "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "^4.1.3",
+ "browser-stdout": "^1.3.1",
+ "chokidar": "^3.5.3",
+ "debug": "^4.3.5",
+ "diff": "^5.2.0",
+ "escape-string-regexp": "^4.0.0",
+ "find-up": "^5.0.0",
+ "glob": "^8.1.0",
+ "he": "^1.2.0",
+ "js-yaml": "^4.1.0",
+ "log-symbols": "^4.1.0",
+ "minimatch": "^5.1.6",
+ "ms": "^2.1.3",
"serialize-javascript": "^6.0.2",
- "strip-json-comments": "3.1.1",
- "supports-color": "8.1.1",
- "workerpool": "6.2.1",
- "yargs": "16.2.0",
- "yargs-parser": "20.2.4",
- "yargs-unparser": "2.0.0"
- },
- "dependencies": {
- "ansi-colors": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
- "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
- "dev": true
- },
- "minimatch": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
- "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
- "dev": true,
- "requires": {
- "brace-expansion": "^2.0.1"
- }
- },
- "ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "dev": true
- },
+ "strip-json-comments": "^3.1.1",
+ "supports-color": "^8.1.1",
+ "workerpool": "^6.5.1",
+ "yargs": "^16.2.0",
+ "yargs-parser": "^20.2.9",
+ "yargs-unparser": "^2.0.0"
+ },
+ "dependencies": {
"supports-color": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
@@ -2506,9 +2473,9 @@
}
},
"ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
},
"nock": {
@@ -2784,9 +2751,9 @@
}
},
"workerpool": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
- "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz",
+ "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==",
"dev": true
},
"wrap-ansi": {
@@ -2827,9 +2794,9 @@
}
},
"yargs-parser": {
- "version": "20.2.4",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
- "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
+ "version": "20.2.9",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
+ "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
"dev": true
},
"yargs-unparser": {
diff --git a/.buildkite/package.json b/.buildkite/package.json
index 158a55c777e6a..5d5293971833a 100644
--- a/.buildkite/package.json
+++ b/.buildkite/package.json
@@ -24,7 +24,7 @@
"@types/mocha": "^10.0.1",
"@types/node": "^15.12.2",
"chai": "^4.3.10",
- "mocha": "^10.3.0",
+ "mocha": "^10.8.2",
"nock": "^12.0.2",
"ts-node": "^10.9.2",
"typescript": "^5.1.6"
From 4f7fd39b655314542613864a1463e59810b3f6db Mon Sep 17 00:00:00 2001
From: Tiago Costa
Date: Fri, 22 Nov 2024 20:04:33 +0000
Subject: [PATCH 22/38] chore(NA): bump and update archiver, pac-resolver
dependencies (#201447)
This PR simply bumps and updates the mentioned dependencies.
---
package.json | 2 +-
yarn.lock | 102 +++++----------------------------------------------
2 files changed, 11 insertions(+), 93 deletions(-)
diff --git a/package.json b/package.json
index 981a947a9a91f..a4fa7916d0584 100644
--- a/package.json
+++ b/package.json
@@ -1082,7 +1082,7 @@
"ajv": "^8.12.0",
"ansi-regex": "^6.1.0",
"antlr4": "^4.13.1-patch-1",
- "archiver": "^5.3.1",
+ "archiver": "^7.0.1",
"async": "^3.2.3",
"aws4": "^1.12.0",
"axios": "^1.7.4",
diff --git a/yarn.lock b/yarn.lock
index 07783adc79447..b3fefd9566533 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -13438,22 +13438,6 @@ arch@^2.2.0:
resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11"
integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==
-archiver-utils@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2"
- integrity sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==
- dependencies:
- glob "^7.1.4"
- graceful-fs "^4.2.0"
- lazystream "^1.0.0"
- lodash.defaults "^4.2.0"
- lodash.difference "^4.5.0"
- lodash.flatten "^4.4.0"
- lodash.isplainobject "^4.0.6"
- lodash.union "^4.6.0"
- normalize-path "^3.0.0"
- readable-stream "^2.0.0"
-
archiver-utils@^5.0.0, archiver-utils@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-5.0.2.tgz#63bc719d951803efc72cf961a56ef810760dd14d"
@@ -13467,19 +13451,6 @@ archiver-utils@^5.0.0, archiver-utils@^5.0.2:
normalize-path "^3.0.0"
readable-stream "^4.0.0"
-archiver@^5.3.1:
- version "5.3.1"
- resolved "https://registry.yarnpkg.com/archiver/-/archiver-5.3.1.tgz#21e92811d6f09ecfce649fbefefe8c79e57cbbb6"
- integrity sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==
- dependencies:
- archiver-utils "^2.1.0"
- async "^3.2.3"
- buffer-crc32 "^0.2.1"
- readable-stream "^3.6.0"
- readdir-glob "^1.0.0"
- tar-stream "^2.2.0"
- zip-stream "^4.1.0"
-
archiver@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/archiver/-/archiver-7.0.1.tgz#c9d91c350362040b8927379c7aa69c0655122f61"
@@ -14619,16 +14590,16 @@ buffer-builder@^0.2.0:
resolved "https://registry.yarnpkg.com/buffer-builder/-/buffer-builder-0.2.0.tgz#3322cd307d8296dab1f604618593b261a3fade8f"
integrity sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==
-buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3:
- version "0.2.13"
- resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
- integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
-
buffer-crc32@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-1.0.0.tgz#a10993b9055081d55304bd9feb4a072de179f405"
integrity sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==
+buffer-crc32@~0.2.3:
+ version "0.2.13"
+ resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
+ integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
+
buffer-equal-constant-time@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
@@ -15602,16 +15573,6 @@ component-emitter@^1.2.1, component-emitter@^1.3.0:
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
-compress-commons@^4.1.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-4.1.1.tgz#df2a09a7ed17447642bad10a85cc9a19e5c42a7d"
- integrity sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==
- dependencies:
- buffer-crc32 "^0.2.13"
- crc32-stream "^4.0.2"
- normalize-path "^3.0.0"
- readable-stream "^3.6.0"
-
compress-commons@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-6.0.2.tgz#26d31251a66b9d6ba23a84064ecd3a6a71d2609e"
@@ -15898,14 +15859,6 @@ crc-32@^1.2.0:
exit-on-epipe "~1.0.1"
printj "~1.1.0"
-crc32-stream@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-4.0.2.tgz#c922ad22b38395abe9d3870f02fa8134ed709007"
- integrity sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==
- dependencies:
- crc-32 "^1.2.0"
- readable-stream "^3.4.0"
-
crc32-stream@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-6.0.0.tgz#8529a3868f8b27abb915f6c3617c0fadedbf9430"
@@ -21059,11 +21012,6 @@ ip-regex@^4.1.0:
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5"
integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==
-ip@^1.1.8:
- version "1.1.9"
- resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.9.tgz#8dfbcc99a754d07f425310b86a99546b1151e396"
- integrity sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==
-
ip@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
@@ -23184,26 +23132,11 @@ lodash.debounce@^4.0.8:
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
-lodash.defaults@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
- integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=
-
-lodash.difference@^4.5.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c"
- integrity sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=
-
lodash.escape@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98"
integrity sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=
-lodash.flatten@^4.4.0:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
- integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=
-
lodash.flattendeep@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2"
@@ -23304,11 +23237,6 @@ lodash.truncate@^4.4.2:
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
-lodash.union@^4.6.0:
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
- integrity sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=
-
lodash.uniq@4.5.0, lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
@@ -25692,12 +25620,11 @@ pac-proxy-agent@^7.0.1:
socks-proxy-agent "^8.0.2"
pac-resolver@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-7.0.0.tgz#79376f1ca26baf245b96b34c339d79bff25e900c"
- integrity sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-7.0.1.tgz#54675558ea368b64d210fd9c92a640b5f3b8abb6"
+ integrity sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==
dependencies:
degenerator "^5.0.0"
- ip "^1.1.8"
netmask "^2.0.2"
package-hash@^4.0.0:
@@ -27887,7 +27814,7 @@ readable-stream@~2.0.0:
string_decoder "~0.10.x"
util-deprecate "~1.0.1"
-readdir-glob@^1.0.0, readdir-glob@^1.1.2:
+readdir-glob@^1.1.2:
version "1.1.3"
resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-1.1.3.tgz#c3d831f51f5e7bfa62fa2ffbe4b508c640f09584"
integrity sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==
@@ -30769,7 +30696,7 @@ tar-fs@^3.0.4, tar-fs@^3.0.6:
bare-fs "^2.1.1"
bare-path "^2.1.0"
-tar-stream@^2.1.4, tar-stream@^2.2.0:
+tar-stream@^2.1.4:
version "2.2.0"
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==
@@ -33574,15 +33501,6 @@ z-schema@^5.0.1:
optionalDependencies:
commander "^2.7.1"
-zip-stream@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-4.1.0.tgz#51dd326571544e36aa3f756430b313576dc8fc79"
- integrity sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==
- dependencies:
- archiver-utils "^2.1.0"
- compress-commons "^4.1.0"
- readable-stream "^3.6.0"
-
zip-stream@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-6.0.1.tgz#e141b930ed60ccaf5d7fa9c8260e0d1748a2bbfb"
From 9c4785bfa18a7a149f746a300f69f9b36cf81c7f Mon Sep 17 00:00:00 2001
From: Ania Kowalska <63072419+akowalska622@users.noreply.github.com>
Date: Fri, 22 Nov 2024 21:52:51 +0100
Subject: [PATCH 23/38] [Discover][Alerts] fix: add mobile width and fix title
row wrap (#201354)
## Summary
Closes [#200162](https://github.com/elastic/kibana/issues/200162)
Long data view names weren't truncated on mobile view. Also noticed the
"X" icon to go on the second row - fixed it within the same PR.
Before:
![image](https://github.com/user-attachments/assets/de30a487-8025-41a3-8487-eb8f43108f79)
After:
### Checklist
Check the PR satisfies following conditions.
Reviewers should verify this PR satisfies this list as well.
- [ ] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [ ] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [ ] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [ ] This was checked for breaking HTTP API changes, and any breaking
changes have been approved by the breaking-change committee. The
`release_note:breaking` label should be applied in these situations.
- [ ] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [x] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
### Identify risks
Does this PR introduce any risks? For example, consider risks like hard
to test bugs, performance regression, potential of data loss.
Describe the risk, its severity, and mitigation for each identified
risk. Invite stakeholders and evaluate how to proceed before merging.
- [x] No risks identified
---
.../components/data_view_select_popover.tsx | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/x-pack/plugins/stack_alerts/public/rule_types/components/data_view_select_popover.tsx b/x-pack/plugins/stack_alerts/public/rule_types/components/data_view_select_popover.tsx
index acb65de2a9a16..988afb8d2182b 100644
--- a/x-pack/plugins/stack_alerts/public/rule_types/components/data_view_select_popover.tsx
+++ b/x-pack/plugins/stack_alerts/public/rule_types/components/data_view_select_popover.tsx
@@ -8,6 +8,7 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
+import { css } from '@emotion/react';
import {
EuiButtonEmpty,
EuiButtonIcon,
@@ -19,6 +20,7 @@ import {
EuiPopoverTitle,
EuiText,
useEuiPaddingCSS,
+ useIsWithinBreakpoints,
} from '@elastic/eui';
import { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public';
import type {
@@ -30,6 +32,9 @@ import { DataViewSelector } from '@kbn/unified-search-plugin/public';
import type { DataViewListItemEnhanced } from '@kbn/unified-search-plugin/public/dataview_picker/dataview_list';
import { EsQueryRuleMetaData } from '../es_query/types';
+const DESKTOP_WIDTH = 450;
+const MOBILE_WIDTH = 350;
+
export interface DataViewSelectPopoverProps {
dependencies: {
dataViews: DataViewsPublicPluginStart;
@@ -61,6 +66,8 @@ export const DataViewSelectPopover: React.FunctionComponent([]);
const [dataViewPopoverOpen, setDataViewPopoverOpen] = useState(false);
+ const isMobile = useIsWithinBreakpoints(['xs']);
+
const closeDataViewEditor = useRef<() => void | undefined>();
const allDataViewItems = useMemo(
@@ -179,9 +186,14 @@ export const DataViewSelectPopover: React.FunctionComponent
-
+
-
+
{i18n.translate('xpack.stackAlerts.components.ui.alertParams.dataViewPopoverTitle', {
defaultMessage: 'Data view',
From c6976b4fd0d8ea4269e3462b64e9758cefcb2062 Mon Sep 17 00:00:00 2001
From: "elastic-renovate-prod[bot]"
<174716857+elastic-renovate-prod[bot]@users.noreply.github.com>
Date: Fri, 22 Nov 2024 16:17:57 -0600
Subject: [PATCH 24/38] Update dependency @testing-library/jest-dom to ^6.6.3
(main) (#191816)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
|
[@testing-library/jest-dom](https://togithub.com/testing-library/jest-dom)
| devDependencies | minor | [`^6.5.0` ->
`^6.6.3`](https://renovatebot.com/diffs/npm/@testing-library%2fjest-dom/6.5.0/6.6.3)
|
---
### Release Notes
testing-library/jest-dom
(@testing-library/jest-dom)
###
[`v6.6.3`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.6.3)
[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.6.2...v6.6.3)
##### Bug Fixes
- add vitest import when extending vitest matchers
([#646](https://togithub.com/testing-library/jest-dom/issues/646))
([5ba0156](https://togithub.com/testing-library/jest-dom/commit/5ba015651c7b10c154e5a4ae54f85df6010c5295))
###
[`v6.6.2`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.6.2)
[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.6.1...v6.6.2)
##### Bug Fixes
- remove recursive type reference in vitest types
([#636](https://togithub.com/testing-library/jest-dom/issues/636))
([4468378](https://togithub.com/testing-library/jest-dom/commit/4468378fb4986018e0bacdebd02244decb9f0718))
###
[`v6.6.1`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.6.1)
[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.6.0...v6.6.1)
##### Bug Fixes
- fix lodash import in to-have-selection.js
([#642](https://togithub.com/testing-library/jest-dom/issues/642))
([ced792e](https://togithub.com/testing-library/jest-dom/commit/ced792e2f2773f16c249c6ce59fa8df968d28a20))
###
[`v6.6.0`](https://togithub.com/testing-library/jest-dom/releases/tag/v6.6.0)
[Compare
Source](https://togithub.com/testing-library/jest-dom/compare/v6.5.0...v6.6.0)
##### Features
- implement toHaveSelection
([#637](https://togithub.com/testing-library/jest-dom/issues/637))
([9b14804](https://togithub.com/testing-library/jest-dom/commit/9b148043d082a83f0ae5cdc03cdfc6a7c4573e6e))
---
### Configuration
📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] If you want to rebase/retry this PR, check
this box
---
This PR has been generated by [Renovate
Bot](https://togithub.com/renovatebot/renovate).
Co-authored-by: elastic-renovate-prod[bot] <174716857+elastic-renovate-prod[bot]@users.noreply.github.com>
Co-authored-by: Brad White
---
package.json | 2 +-
yarn.lock | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package.json b/package.json
index a4fa7916d0584..fe04f6e65bbc5 100644
--- a/package.json
+++ b/package.json
@@ -1531,7 +1531,7 @@
"@storybook/testing-react": "^1.3.0",
"@storybook/theming": "^6.5.16",
"@testing-library/dom": "^10.4.0",
- "@testing-library/jest-dom": "^6.5.0",
+ "@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.0.1",
"@testing-library/react-hooks": "^8.0.1",
"@testing-library/user-event": "^14.5.2",
diff --git a/yarn.lock b/yarn.lock
index b3fefd9566533..f811bb6c93c20 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -10802,10 +10802,10 @@
lz-string "^1.5.0"
pretty-format "^27.0.2"
-"@testing-library/jest-dom@^6.5.0":
- version "6.5.0"
- resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.5.0.tgz#50484da3f80fb222a853479f618a9ce5c47bfe54"
- integrity sha512-xGGHpBXYSHUUr6XsKBfs85TWlYKpTc37cSBBVrXcib2MkHLboWlkClhWF37JKlDb9KEq3dHs+f2xR7XJEWGBxA==
+"@testing-library/jest-dom@^6.6.3":
+ version "6.6.3"
+ resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz#26ba906cf928c0f8172e182c6fe214eb4f9f2bd2"
+ integrity sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==
dependencies:
"@adobe/css-tools" "^4.4.0"
aria-query "^5.0.0"
From b28740ee5bcdc8e74d0abf26a268668aa2abcd23 Mon Sep 17 00:00:00 2001
From: Rickyanto Ang
Date: Fri, 22 Nov 2024 14:56:22 -0800
Subject: [PATCH 25/38] [Cloud Security] Remove Unused KSPM Option (#201463)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Summary
This PR is to remove unused KSPM option
---
.../public/common/constants.ts | 30 -------------------
.../translations/translations/fr-FR.json | 6 ----
.../translations/translations/ja-JP.json | 6 ----
.../translations/translations/zh-CN.json | 6 ----
4 files changed, 48 deletions(-)
diff --git a/x-pack/plugins/cloud_security_posture/public/common/constants.ts b/x-pack/plugins/cloud_security_posture/public/common/constants.ts
index ea3866cbe1256..ff4f51fc0b47a 100644
--- a/x-pack/plugins/cloud_security_posture/public/common/constants.ts
+++ b/x-pack/plugins/cloud_security_posture/public/common/constants.ts
@@ -23,8 +23,6 @@ import {
} from '../../common/constants';
import eksLogo from '../assets/icons/cis_eks_logo.svg';
-import aksLogo from '../assets/icons/cis_aks_logo.svg';
-import gkeLogo from '../assets/icons/cis_gke_logo.svg';
import googleCloudLogo from '../assets/icons/google_cloud_logo.svg';
export const CSP_MOMENT_FORMAT = 'MMMM D, YYYY @ HH:mm:ss.SSS';
@@ -145,34 +143,6 @@ export const cloudPostureIntegrations: CloudPostureIntegrations = {
}),
testId: 'cisEksTestId',
},
- {
- type: CLOUDBEAT_AKS,
- name: i18n.translate('xpack.csp.kspmIntegration.aksOption.nameTitle', {
- defaultMessage: 'AKS',
- }),
- benchmark: i18n.translate('xpack.csp.kspmIntegration.aksOption.benchmarkTitle', {
- defaultMessage: 'CIS AKS',
- }),
- disabled: true,
- icon: aksLogo,
- tooltip: i18n.translate('xpack.csp.kspmIntegration.aksOption.tooltipContent', {
- defaultMessage: 'Azure Kubernetes Service - Coming soon',
- }),
- },
- {
- type: CLOUDBEAT_GKE,
- name: i18n.translate('xpack.csp.kspmIntegration.gkeOption.nameTitle', {
- defaultMessage: 'GKE',
- }),
- benchmark: i18n.translate('xpack.csp.kspmIntegration.gkeOption.benchmarkTitle', {
- defaultMessage: 'CIS GKE',
- }),
- disabled: true,
- icon: gkeLogo,
- tooltip: i18n.translate('xpack.csp.kspmIntegration.gkeOption.tooltipContent', {
- defaultMessage: 'Google Kubernetes Engine - Coming soon',
- }),
- },
],
},
vuln_mgmt: {
diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json
index 77cb502273850..dc6ae26d7f798 100644
--- a/x-pack/plugins/translations/translations/fr-FR.json
+++ b/x-pack/plugins/translations/translations/fr-FR.json
@@ -15105,15 +15105,9 @@
"xpack.csp.grouping.nullGroupTooltip.groupingTitle": "regrouper par",
"xpack.csp.integrationDashboard.noFindings.promptTitle": "Statut d'évaluation des résultats",
"xpack.csp.integrationDashboard.noFindingsPrompt.promptDescription": "En attente de la collecte et de l'indexation des données. Si ce processus prend plus de temps que prévu, veuillez contacter notre support technique",
- "xpack.csp.kspmIntegration.aksOption.benchmarkTitle": "CIS AKS",
- "xpack.csp.kspmIntegration.aksOption.nameTitle": "AKS",
- "xpack.csp.kspmIntegration.aksOption.tooltipContent": "Azure Kubernetes Service - Bientôt disponible",
"xpack.csp.kspmIntegration.eksOption.benchmarkTitle": "CIS EKS",
"xpack.csp.kspmIntegration.eksOption.nameTitle": "EKS",
"xpack.csp.kspmIntegration.eksOption.tooltipContent": "EKS (Elastic Kubernetes Service)",
- "xpack.csp.kspmIntegration.gkeOption.benchmarkTitle": "CIS GKE",
- "xpack.csp.kspmIntegration.gkeOption.nameTitle": "GKE",
- "xpack.csp.kspmIntegration.gkeOption.tooltipContent": "Google Kubernetes Engine - Bientôt disponible",
"xpack.csp.kspmIntegration.integration.nameTitle": "Gestion du niveau de sécurité Kubernetes",
"xpack.csp.kspmIntegration.integration.shortNameTitle": "KSPM",
"xpack.csp.kspmIntegration.vanillaOption.benchmarkTitle": "CIS Kubernetes",
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index c199283dd34af..b060c39d5f1b8 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -15084,15 +15084,9 @@
"xpack.csp.grouping.nullGroupTooltip.groupingTitle": "グループ分けの条件",
"xpack.csp.integrationDashboard.noFindings.promptTitle": "調査結果評価ステータス",
"xpack.csp.integrationDashboard.noFindingsPrompt.promptDescription": "データの収集とインデックス作成を待機しています。このプロセスに想定よりも時間がかかる場合は、サポートまでお問い合わせください",
- "xpack.csp.kspmIntegration.aksOption.benchmarkTitle": "CIS AKS",
- "xpack.csp.kspmIntegration.aksOption.nameTitle": "AKS",
- "xpack.csp.kspmIntegration.aksOption.tooltipContent": "Azure Kubernetes Service - まもなくリリース",
"xpack.csp.kspmIntegration.eksOption.benchmarkTitle": "CIS EKS",
"xpack.csp.kspmIntegration.eksOption.nameTitle": "EKS",
"xpack.csp.kspmIntegration.eksOption.tooltipContent": "Elastic Kubernetes Service",
- "xpack.csp.kspmIntegration.gkeOption.benchmarkTitle": "CIS GKE",
- "xpack.csp.kspmIntegration.gkeOption.nameTitle": "GKE",
- "xpack.csp.kspmIntegration.gkeOption.tooltipContent": "Google Kubernetes Engine - まもなくリリース",
"xpack.csp.kspmIntegration.integration.nameTitle": "Kubernetesセキュリティ態勢管理",
"xpack.csp.kspmIntegration.integration.shortNameTitle": "KSPM",
"xpack.csp.kspmIntegration.vanillaOption.benchmarkTitle": "CIS Kubernetes",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 0588fe925cb72..4b5f21d04c964 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -14779,15 +14779,9 @@
"xpack.csp.grouping.nullGroupTooltip.groupingTitle": "分组依据",
"xpack.csp.integrationDashboard.noFindings.promptTitle": "结果评估状态",
"xpack.csp.integrationDashboard.noFindingsPrompt.promptDescription": "正在等待要收集和索引的数据。如果此进程花费的时间长于预期,请联系我们的支持人员",
- "xpack.csp.kspmIntegration.aksOption.benchmarkTitle": "CIS AKS",
- "xpack.csp.kspmIntegration.aksOption.nameTitle": "AKS",
- "xpack.csp.kspmIntegration.aksOption.tooltipContent": "Azure Kubernetes 服务 - 即将推出",
"xpack.csp.kspmIntegration.eksOption.benchmarkTitle": "CIS EKS",
"xpack.csp.kspmIntegration.eksOption.nameTitle": "EKS",
"xpack.csp.kspmIntegration.eksOption.tooltipContent": "Elastic Kubernetes 服务",
- "xpack.csp.kspmIntegration.gkeOption.benchmarkTitle": "CIS GKE",
- "xpack.csp.kspmIntegration.gkeOption.nameTitle": "GKE",
- "xpack.csp.kspmIntegration.gkeOption.tooltipContent": "Google Kubernetes Engine - 即将推出",
"xpack.csp.kspmIntegration.integration.nameTitle": "Kubernetes 安全态势管理",
"xpack.csp.kspmIntegration.integration.shortNameTitle": "KSPM",
"xpack.csp.kspmIntegration.vanillaOption.benchmarkTitle": "CIS Kubernetes",
From c6cb05996188ec7613d38f10de57dade356d12f7 Mon Sep 17 00:00:00 2001
From: Kevin Qualters <56408403+kqualters-elastic@users.noreply.github.com>
Date: Fri, 22 Nov 2024 19:11:12 -0500
Subject: [PATCH 26/38] [Security Solution] Fix an error with nested fields
being treated as keyword (#201473)
## Summary
When formatting elasticsearch responses for the frontend, the timelines
search strategies will treat unmapped fields as type: keyword. If the
underlying field is actually an object, but is seen as a string in the
code, this for (key in source) loop will fail, as it's trying to loop
over a string. Fix below should have minimal effect as the data is
accessible at the further nested keys.
### Checklist
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
---
.../timeline/factory/helpers/format_timeline_data.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/format_timeline_data.ts b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/format_timeline_data.ts
index 485ec64badd5c..481b74a802fec 100644
--- a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/format_timeline_data.ts
+++ b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/helpers/format_timeline_data.ts
@@ -34,7 +34,7 @@ const createBaseTimelineEdges = (): TimelineEdges => ({
function deepMerge(target: EventSource, source: EventSource) {
for (const key in source) {
- if (source[key] instanceof Object && key in target) {
+ if (source && source[key] instanceof Object && target && target[key] instanceof Object) {
deepMerge(target[key], source[key]);
} else {
target[key] = source[key];
From e48f930ab32b5c325ad38175e41f93ec0b8c4ba7 Mon Sep 17 00:00:00 2001
From: Ash <1849116+ashokaditya@users.noreply.github.com>
Date: Sat, 23 Nov 2024 02:08:24 +0100
Subject: [PATCH 27/38] [DataUsage][Serverless] UX/API changes based on demo
feedback (#200911)
## Summary
Adds a bunch of UX updates based on the feedback after demo.
- [x] Tidy chart legend action popup and links
- [x] fix UX date picker invalid time (UX shows invalid time falsely)
- [ ] Tooltip for date filter
- [ ] send UTC time to requests (1:1 mapping for date-time picked vs
date-time sent)
- [x] Remove unusable common date filter shortcuts
- [x] data stream filter `select all`
- [x] data stream filter `clear all`
- [x] No charts empty state
- [x] filter in datastreams that have greater than `0` bytes storage
size
- [ ] Filter out system indices from data stream filter?
- [x] Taller filter popover list for larger lists
Follow up of https://github.com/elastic/kibana/pull/200731
### Checklist
Check the PR satisfies following conditions.
Reviewers should verify this PR satisfies this list as well.
- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [x] This was checked for breaking HTTP API changes, and any breaking
changes have been approved by the breaking-change committee. The
`release_note:breaking` label should be applied in these situations.
- [ ] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [x] The PR description includes the appropriate Release Notes section,
and the correct `release_node:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
### Identify risks
Does this PR introduce any risks? For example, consider risks like hard
to test bugs, performance regression, potential of data loss.
Describe the risk, its severity, and mitigation for each identified
risk. Invite stakeholders and evaluate how to proceed before merging.
- [ ] [See some risk
examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx)
- [ ] ...
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
---
x-pack/plugins/data_usage/common/constants.ts | 14 +++
x-pack/plugins/data_usage/common/index.ts | 19 ++-
.../data_usage/common/test_utils/index.ts | 10 ++
.../common/test_utils/test_provider.tsx | 13 ++
.../data_usage/common/test_utils/time_ago.ts | 9 ++
x-pack/plugins/data_usage/common/utils.ts | 10 ++
...on_product_no_results_magnifying_glass.svg | 32 +++++
.../public/app/components/chart_panel.tsx | 2 +-
.../public/app/components/charts.tsx | 3 +-
.../public/app/components/charts_loading.tsx | 35 ++++++
.../components/data_usage_metrics.test.tsx | 115 ++++++++++++-----
.../app/components/data_usage_metrics.tsx | 38 ++++--
.../app/components/dataset_quality_link.tsx | 7 +-
.../app/components/filters/charts_filter.tsx | 116 ++++++++++++++----
.../filters/charts_filter_popover.tsx | 2 +-
.../app/components/filters/date_picker.tsx | 30 +++--
.../components/filters/toggle_all_button.tsx | 45 +++++++
.../public/app/components/legend_action.tsx | 26 ++--
.../app/components/legend_action_item.tsx | 17 +++
.../public/app/components/no_data_callout.tsx | 59 +++++++++
.../public/app/data_usage_metrics_page.tsx | 2 +-
.../public/app/hooks/use_charts_filter.tsx | 18 ++-
.../app/hooks/use_charts_url_params.test.tsx | 14 +--
.../app/hooks/use_charts_url_params.tsx | 2 +-
.../public/app/hooks/use_date_picker.tsx | 7 +-
.../plugins/data_usage/public/application.tsx | 2 +-
.../hooks/use_get_data_streams.test.tsx | 2 +-
.../hooks/use_get_usage_metrics.test.tsx | 7 +-
.../public/hooks/use_get_usage_metrics.ts | 10 +-
x-pack/plugins/data_usage/public/plugin.ts | 3 +-
.../public/{app => }/translations.tsx | 21 ++++
.../routes/internal/data_streams.test.ts | 44 ++++++-
.../routes/internal/data_streams_handler.ts | 13 +-
.../routes/internal/usage_metrics.test.ts | 14 +--
.../routes/internal/usage_metrics_handler.ts | 28 +++--
.../data_usage/server/services/autoops_api.ts | 8 +-
.../data_usage/server/services/index.ts | 2 +-
x-pack/plugins/data_usage/tsconfig.json | 2 +
.../translations/translations/fr-FR.json | 11 +-
.../translations/translations/ja-JP.json | 11 +-
.../translations/translations/zh-CN.json | 11 +-
.../common/data_usage/tests/data_streams.ts | 5 +-
42 files changed, 655 insertions(+), 184 deletions(-)
create mode 100644 x-pack/plugins/data_usage/common/constants.ts
create mode 100644 x-pack/plugins/data_usage/common/test_utils/index.ts
create mode 100644 x-pack/plugins/data_usage/common/test_utils/test_provider.tsx
create mode 100644 x-pack/plugins/data_usage/common/test_utils/time_ago.ts
create mode 100644 x-pack/plugins/data_usage/common/utils.ts
create mode 100644 x-pack/plugins/data_usage/public/app/components/assets/illustration_product_no_results_magnifying_glass.svg
create mode 100644 x-pack/plugins/data_usage/public/app/components/charts_loading.tsx
create mode 100644 x-pack/plugins/data_usage/public/app/components/filters/toggle_all_button.tsx
create mode 100644 x-pack/plugins/data_usage/public/app/components/legend_action_item.tsx
create mode 100644 x-pack/plugins/data_usage/public/app/components/no_data_callout.tsx
rename x-pack/plugins/data_usage/public/{app => }/translations.tsx (68%)
diff --git a/x-pack/plugins/data_usage/common/constants.ts b/x-pack/plugins/data_usage/common/constants.ts
new file mode 100644
index 0000000000000..bf8b801cbf92a
--- /dev/null
+++ b/x-pack/plugins/data_usage/common/constants.ts
@@ -0,0 +1,14 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+export const PLUGIN_ID = 'data_usage';
+
+export const DEFAULT_SELECTED_OPTIONS = 50 as const;
+
+export const DATA_USAGE_API_ROUTE_PREFIX = '/api/data_usage/';
+export const DATA_USAGE_METRICS_API_ROUTE = `/internal${DATA_USAGE_API_ROUTE_PREFIX}metrics`;
+export const DATA_USAGE_DATA_STREAMS_API_ROUTE = `/internal${DATA_USAGE_API_ROUTE_PREFIX}data_streams`;
diff --git a/x-pack/plugins/data_usage/common/index.ts b/x-pack/plugins/data_usage/common/index.ts
index 8b952b13d4cc7..63e34f872108c 100644
--- a/x-pack/plugins/data_usage/common/index.ts
+++ b/x-pack/plugins/data_usage/common/index.ts
@@ -5,15 +5,10 @@
* 2.0.
*/
-import { i18n } from '@kbn/i18n';
-
-export const PLUGIN_ID = 'data_usage';
-export const PLUGIN_NAME = i18n.translate('xpack.dataUsage.name', {
- defaultMessage: 'Data Usage',
-});
-
-export const DEFAULT_SELECTED_OPTIONS = 50 as const;
-
-export const DATA_USAGE_API_ROUTE_PREFIX = '/api/data_usage/';
-export const DATA_USAGE_METRICS_API_ROUTE = `/internal${DATA_USAGE_API_ROUTE_PREFIX}metrics`;
-export const DATA_USAGE_DATA_STREAMS_API_ROUTE = `/internal${DATA_USAGE_API_ROUTE_PREFIX}data_streams`;
+export {
+ PLUGIN_ID,
+ DEFAULT_SELECTED_OPTIONS,
+ DATA_USAGE_API_ROUTE_PREFIX,
+ DATA_USAGE_METRICS_API_ROUTE,
+ DATA_USAGE_DATA_STREAMS_API_ROUTE,
+} from './constants';
diff --git a/x-pack/plugins/data_usage/common/test_utils/index.ts b/x-pack/plugins/data_usage/common/test_utils/index.ts
new file mode 100644
index 0000000000000..c3c8e75b29454
--- /dev/null
+++ b/x-pack/plugins/data_usage/common/test_utils/index.ts
@@ -0,0 +1,10 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+export { TestProvider } from './test_provider';
+export { dataUsageTestQueryClientOptions } from './test_query_client_options';
+export { timeXMinutesAgo } from './time_ago';
diff --git a/x-pack/plugins/data_usage/common/test_utils/test_provider.tsx b/x-pack/plugins/data_usage/common/test_utils/test_provider.tsx
new file mode 100644
index 0000000000000..a3d154ba911e0
--- /dev/null
+++ b/x-pack/plugins/data_usage/common/test_utils/test_provider.tsx
@@ -0,0 +1,13 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { memo } from 'react';
+import { I18nProvider } from '@kbn/i18n-react';
+
+export const TestProvider = memo(({ children }: { children?: React.ReactNode }) => {
+ return {children};
+});
diff --git a/x-pack/plugins/data_usage/common/test_utils/time_ago.ts b/x-pack/plugins/data_usage/common/test_utils/time_ago.ts
new file mode 100644
index 0000000000000..7fe74e232bdac
--- /dev/null
+++ b/x-pack/plugins/data_usage/common/test_utils/time_ago.ts
@@ -0,0 +1,9 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+export const timeXMinutesAgo = (x: number) =>
+ new Date(new Date().getTime() - x * 60 * 1000).toISOString();
diff --git a/x-pack/plugins/data_usage/common/utils.ts b/x-pack/plugins/data_usage/common/utils.ts
new file mode 100644
index 0000000000000..ddd707b1134fd
--- /dev/null
+++ b/x-pack/plugins/data_usage/common/utils.ts
@@ -0,0 +1,10 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import dateMath from '@kbn/datemath';
+export const dateParser = (date: string) => dateMath.parse(date)?.toISOString();
+export const momentDateParser = (date: string) => dateMath.parse(date);
diff --git a/x-pack/plugins/data_usage/public/app/components/assets/illustration_product_no_results_magnifying_glass.svg b/x-pack/plugins/data_usage/public/app/components/assets/illustration_product_no_results_magnifying_glass.svg
new file mode 100644
index 0000000000000..4329041f84a9f
--- /dev/null
+++ b/x-pack/plugins/data_usage/public/app/components/assets/illustration_product_no_results_magnifying_glass.svg
@@ -0,0 +1,32 @@
+
diff --git a/x-pack/plugins/data_usage/public/app/components/chart_panel.tsx b/x-pack/plugins/data_usage/public/app/components/chart_panel.tsx
index bb0df29e22fff..208b1e576c0d7 100644
--- a/x-pack/plugins/data_usage/public/app/components/chart_panel.tsx
+++ b/x-pack/plugins/data_usage/public/app/components/chart_panel.tsx
@@ -20,7 +20,7 @@ import {
} from '@elastic/charts';
import { i18n } from '@kbn/i18n';
import { LegendAction } from './legend_action';
-import { MetricTypes, MetricSeries } from '../../../common/rest_types';
+import { type MetricTypes, type MetricSeries } from '../../../common/rest_types';
import { formatBytes } from '../../utils/format_bytes';
// TODO: Remove this when we have a title for each metric type
diff --git a/x-pack/plugins/data_usage/public/app/components/charts.tsx b/x-pack/plugins/data_usage/public/app/components/charts.tsx
index 4a2b9b4fbc875..271cfe432402d 100644
--- a/x-pack/plugins/data_usage/public/app/components/charts.tsx
+++ b/x-pack/plugins/data_usage/public/app/components/charts.tsx
@@ -6,9 +6,8 @@
*/
import React, { useCallback, useState } from 'react';
import { EuiFlexGroup } from '@elastic/eui';
-import { MetricTypes } from '../../../common/rest_types';
import { ChartPanel } from './chart_panel';
-import { UsageMetricsResponseSchemaBody } from '../../../common/rest_types';
+import type { UsageMetricsResponseSchemaBody, MetricTypes } from '../../../common/rest_types';
import { useTestIdGenerator } from '../../hooks/use_test_id_generator';
interface ChartsProps {
data: UsageMetricsResponseSchemaBody;
diff --git a/x-pack/plugins/data_usage/public/app/components/charts_loading.tsx b/x-pack/plugins/data_usage/public/app/components/charts_loading.tsx
new file mode 100644
index 0000000000000..08c37934c451e
--- /dev/null
+++ b/x-pack/plugins/data_usage/public/app/components/charts_loading.tsx
@@ -0,0 +1,35 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+import React from 'react';
+import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiLoadingChart } from '@elastic/eui';
+import { useTestIdGenerator } from '../../hooks/use_test_id_generator';
+
+export const ChartsLoading = ({
+ 'data-test-subj': dataTestSubj,
+}: {
+ 'data-test-subj'?: string;
+}) => {
+ const getTestId = useTestIdGenerator(dataTestSubj);
+ // returns 2 loading icons for the two charts
+ return (
+
+ {[...Array(2)].map((i) => (
+
+
+
+
+
+ ))}
+
+ );
+};
+
+ChartsLoading.displayName = 'ChartsLoading';
diff --git a/x-pack/plugins/data_usage/public/app/components/data_usage_metrics.test.tsx b/x-pack/plugins/data_usage/public/app/components/data_usage_metrics.test.tsx
index 8ece65b7a57a4..91e2fd5ddafa9 100644
--- a/x-pack/plugins/data_usage/public/app/components/data_usage_metrics.test.tsx
+++ b/x-pack/plugins/data_usage/public/app/components/data_usage_metrics.test.tsx
@@ -5,7 +5,8 @@
* 2.0.
*/
import React from 'react';
-import { render, waitFor } from '@testing-library/react';
+import { TestProvider } from '../../../common/test_utils';
+import { render, waitFor, within, type RenderResult } from '@testing-library/react';
import userEvent, { type UserEvent } from '@testing-library/user-event';
import { DataUsageMetrics } from './data_usage_metrics';
import { useGetDataUsageMetrics } from '../../hooks/use_get_usage_metrics';
@@ -102,21 +103,6 @@ jest.mock('@kbn/kibana-react-plugin/public', () => {
to: 'now',
display: 'Last 7 days',
},
- {
- from: 'now-30d',
- to: 'now',
- display: 'Last 30 days',
- },
- {
- from: 'now-90d',
- to: 'now',
- display: 'Last 90 days',
- },
- {
- from: 'now-1y',
- to: 'now',
- display: 'Last 1 year',
- },
],
};
return x[k];
@@ -156,6 +142,7 @@ describe('DataUsageMetrics', () => {
let user: UserEvent;
const testId = 'test';
const testIdFilter = `${testId}-filter`;
+ let renderComponent: () => RenderResult;
beforeAll(() => {
jest.useFakeTimers();
@@ -167,18 +154,24 @@ describe('DataUsageMetrics', () => {
beforeEach(() => {
jest.clearAllMocks();
+ renderComponent = () =>
+ render(
+
+
+
+ );
user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime, pointerEventsCheck: 0 });
mockUseGetDataUsageMetrics.mockReturnValue(getBaseMockedDataUsageMetrics);
mockUseGetDataUsageDataStreams.mockReturnValue(getBaseMockedDataStreams);
});
it('renders', () => {
- const { getByTestId } = render();
+ const { getByTestId } = renderComponent();
expect(getByTestId(`${testId}`)).toBeTruthy();
});
it('should show date filter', () => {
- const { getByTestId } = render();
+ const { getByTestId } = renderComponent();
const dateFilter = getByTestId(`${testIdFilter}-date-range`);
expect(dateFilter).toBeTruthy();
expect(dateFilter.textContent).toContain('to');
@@ -190,12 +183,12 @@ describe('DataUsageMetrics', () => {
...getBaseMockedDataStreams,
isFetching: true,
});
- const { queryByTestId } = render();
+ const { queryByTestId } = renderComponent();
expect(queryByTestId(`${testIdFilter}-dataStreams-popoverButton`)).not.toBeTruthy();
});
it('should show data streams filter', () => {
- const { getByTestId } = render();
+ const { getByTestId } = renderComponent();
expect(getByTestId(`${testIdFilter}-dataStreams-popoverButton`)).toBeTruthy();
});
@@ -205,7 +198,7 @@ describe('DataUsageMetrics', () => {
data: generateDataStreams(5),
isFetching: false,
});
- const { getByTestId } = render();
+ const { getByTestId } = renderComponent();
expect(getByTestId(`${testIdFilter}-dataStreams-popoverButton`)).toHaveTextContent(
'Data streams5'
);
@@ -217,29 +210,76 @@ describe('DataUsageMetrics', () => {
data: generateDataStreams(100),
isFetching: false,
});
- const { getByTestId } = render();
+ const { getByTestId } = renderComponent();
const toggleFilterButton = getByTestId(`${testIdFilter}-dataStreams-popoverButton`);
expect(toggleFilterButton).toHaveTextContent('Data streams50');
});
- it('should allow de-selecting all but one data stream option', async () => {
+ it('should allow de-selecting data stream options', async () => {
mockUseGetDataUsageDataStreams.mockReturnValue({
error: undefined,
- data: generateDataStreams(5),
+ data: generateDataStreams(10),
isFetching: false,
});
- const { getByTestId, getAllByTestId } = render();
+ const { getByTestId, getAllByTestId } = renderComponent();
const toggleFilterButton = getByTestId(`${testIdFilter}-dataStreams-popoverButton`);
- expect(toggleFilterButton).toHaveTextContent('Data streams5');
+ expect(toggleFilterButton).toHaveTextContent('Data streams10');
await user.click(toggleFilterButton);
const allFilterOptions = getAllByTestId('dataStreams-filter-option');
- for (let i = 0; i < allFilterOptions.length - 1; i++) {
+ // deselect 9 options
+ for (let i = 0; i < allFilterOptions.length; i++) {
await user.click(allFilterOptions[i]);
}
expect(toggleFilterButton).toHaveTextContent('Data streams1');
+ expect(within(toggleFilterButton).getByRole('marquee').getAttribute('aria-label')).toEqual(
+ '1 active filters'
+ );
+ });
+
+ it('should allow selecting/deselecting all data stream options using `select all` and `clear all`', async () => {
+ mockUseGetDataUsageDataStreams.mockReturnValue({
+ error: undefined,
+ data: generateDataStreams(10),
+ isFetching: false,
+ });
+ const { getByTestId } = renderComponent();
+ const toggleFilterButton = getByTestId(`${testIdFilter}-dataStreams-popoverButton`);
+
+ expect(toggleFilterButton).toHaveTextContent('Data streams10');
+ await user.click(toggleFilterButton);
+
+ // all options are selected on load
+ expect(within(toggleFilterButton).getByRole('marquee').getAttribute('aria-label')).toEqual(
+ '10 active filters'
+ );
+
+ const selectAllButton = getByTestId(`${testIdFilter}-dataStreams-selectAllButton`);
+ const clearAllButton = getByTestId(`${testIdFilter}-dataStreams-clearAllButton`);
+
+ // select all is disabled
+ expect(selectAllButton).toBeTruthy();
+ expect(selectAllButton.getAttribute('disabled')).not.toBeNull();
+
+ // clear all is enabled
+ expect(clearAllButton).toBeTruthy();
+ expect(clearAllButton.getAttribute('disabled')).toBeNull();
+ // click clear all and expect all options to be deselected
+ await user.click(clearAllButton);
+ expect(within(toggleFilterButton).getByRole('marquee').getAttribute('aria-label')).toEqual(
+ '10 available filters'
+ );
+ // select all is enabled again
+ expect(await selectAllButton.getAttribute('disabled')).toBeNull();
+ // click select all
+ await user.click(selectAllButton);
+
+ // all options are selected and clear all is disabled
+ expect(within(toggleFilterButton).getByRole('marquee').getAttribute('aria-label')).toEqual(
+ '10 active filters'
+ );
});
it('should not call usage metrics API if no data streams', async () => {
@@ -247,7 +287,7 @@ describe('DataUsageMetrics', () => {
...getBaseMockedDataStreams,
data: [],
});
- render();
+ renderComponent();
expect(mockUseGetDataUsageMetrics).toHaveBeenCalledWith(
expect.any(Object),
expect.objectContaining({ enabled: false })
@@ -259,7 +299,7 @@ describe('DataUsageMetrics', () => {
...getBaseMockedDataUsageMetrics,
isFetching: true,
});
- const { getByTestId } = render();
+ const { getByTestId } = renderComponent();
expect(getByTestId(`${testId}-charts-loading`)).toBeTruthy();
});
@@ -290,10 +330,19 @@ describe('DataUsageMetrics', () => {
],
},
});
- const { getByTestId } = render();
+ const { getByTestId } = renderComponent();
expect(getByTestId(`${testId}-charts`)).toBeTruthy();
});
+ it('should show no charts callout', () => {
+ mockUseGetDataUsageMetrics.mockReturnValue({
+ ...getBaseMockedDataUsageMetrics,
+ isFetched: false,
+ });
+ const { getByTestId } = renderComponent();
+ expect(getByTestId(`${testId}-no-charts-callout`)).toBeTruthy();
+ });
+
it('should refetch usage metrics with `Refresh` button click', async () => {
const refetch = jest.fn();
mockUseGetDataUsageMetrics.mockReturnValue({
@@ -306,7 +355,7 @@ describe('DataUsageMetrics', () => {
isFetched: true,
refetch,
});
- const { getByTestId } = render();
+ const { getByTestId } = renderComponent();
const refreshButton = getByTestId(`${testIdFilter}-super-refresh-button`);
// click refresh 5 times
for (let i = 0; i < 5; i++) {
@@ -326,7 +375,7 @@ describe('DataUsageMetrics', () => {
isFetched: true,
error: new Error('Uh oh!'),
});
- render();
+ renderComponent();
await waitFor(() => {
expect(mockServices.notifications.toasts.addDanger).toHaveBeenCalledWith({
title: 'Error getting usage metrics',
@@ -341,7 +390,7 @@ describe('DataUsageMetrics', () => {
isFetched: true,
error: new Error('Uh oh!'),
});
- render();
+ renderComponent();
await waitFor(() => {
expect(mockServices.notifications.toasts.addDanger).toHaveBeenCalledWith({
title: 'Error getting data streams',
diff --git a/x-pack/plugins/data_usage/public/app/components/data_usage_metrics.tsx b/x-pack/plugins/data_usage/public/app/components/data_usage_metrics.tsx
index 5460c7ada0389..d7d6417cf1444 100644
--- a/x-pack/plugins/data_usage/public/app/components/data_usage_metrics.tsx
+++ b/x-pack/plugins/data_usage/public/app/components/data_usage_metrics.tsx
@@ -7,18 +7,20 @@
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
import { css } from '@emotion/react';
-import { EuiFlexGroup, EuiFlexItem, EuiLoadingElastic } from '@elastic/eui';
+import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { Charts } from './charts';
import { useBreadcrumbs } from '../../utils/use_breadcrumbs';
import { useKibanaContextForPlugin } from '../../utils/use_kibana';
-import { PLUGIN_NAME } from '../../../common';
+import { DEFAULT_METRIC_TYPES, type UsageMetricsRequestBody } from '../../../common/rest_types';
+import { PLUGIN_NAME } from '../../translations';
import { useGetDataUsageMetrics } from '../../hooks/use_get_usage_metrics';
import { useGetDataUsageDataStreams } from '../../hooks/use_get_data_streams';
import { useDataUsageMetricsUrlParams } from '../hooks/use_charts_url_params';
import { DEFAULT_DATE_RANGE_OPTIONS, useDateRangePicker } from '../hooks/use_date_picker';
-import { DEFAULT_METRIC_TYPES, UsageMetricsRequestBody } from '../../../common/rest_types';
import { ChartFilters, ChartFiltersProps } from './filters/charts_filters';
+import { ChartsLoading } from './charts_loading';
+import { NoDataCallout } from './no_data_callout';
import { useTestIdGenerator } from '../../hooks/use_test_id_generator';
const EuiItemCss = css`
@@ -33,6 +35,8 @@ export const DataUsageMetrics = memo(
({ 'data-test-subj': dataTestSubj = 'data-usage-metrics' }: { 'data-test-subj'?: string }) => {
const getTestId = useTestIdGenerator(dataTestSubj);
+ const [isFirstPageLoad, setIsFirstPageLoad] = useState(true);
+
const {
services: { chrome, appParams, notifications },
} = useKibanaContextForPlugin();
@@ -68,10 +72,10 @@ export const DataUsageMetrics = memo(
});
useEffect(() => {
- if (!metricTypesFromUrl) {
+ if (!metricTypesFromUrl && isFirstPageLoad) {
setUrlMetricTypesFilter(metricsFilters.metricTypes.join(','));
}
- if (!dataStreamsFromUrl && dataStreams) {
+ if (!dataStreamsFromUrl && dataStreams && isFirstPageLoad) {
const hasMoreThan50 = dataStreams.length > 50;
const _dataStreams = hasMoreThan50 ? dataStreams.slice(0, 50) : dataStreams;
setUrlDataStreamsFilter(_dataStreams.map((ds) => ds.name).join(','));
@@ -83,6 +87,7 @@ export const DataUsageMetrics = memo(
dataStreams,
dataStreamsFromUrl,
endDateFromUrl,
+ isFirstPageLoad,
metricTypesFromUrl,
metricsFilters.dataStreams,
metricsFilters.from,
@@ -106,9 +111,9 @@ export const DataUsageMetrics = memo(
const {
error: errorFetchingDataUsageMetrics,
- data,
+ data: usageMetricsData,
isFetching,
- isFetched,
+ isFetched: hasFetchedDataUsageMetricsData,
refetch: refetchDataUsageMetrics,
} = useGetDataUsageMetrics(
{
@@ -118,10 +123,16 @@ export const DataUsageMetrics = memo(
},
{
retry: false,
- enabled: !!metricsFilters.dataStreams.length,
+ enabled: !!(metricsFilters.dataStreams.length && metricsFilters.metricTypes.length),
}
);
+ useEffect(() => {
+ if (!isFetching && hasFetchedDataUsageMetricsData) {
+ setIsFirstPageLoad(false);
+ }
+ }, [isFetching, hasFetchedDataUsageMetricsData]);
+
const onRefresh = useCallback(() => {
refetchDataUsageMetrics();
}, [refetchDataUsageMetrics]);
@@ -204,13 +215,14 @@ export const DataUsageMetrics = memo(
data-test-subj={getTestId('filter')}
/>
-
- {isFetched && data ? (
-
+ {hasFetchedDataUsageMetricsData && usageMetricsData ? (
+
) : isFetching ? (
-
- ) : null}
+
+ ) : (
+
+ )}
);
diff --git a/x-pack/plugins/data_usage/public/app/components/dataset_quality_link.tsx b/x-pack/plugins/data_usage/public/app/components/dataset_quality_link.tsx
index d6627f3d8dca2..8e81e6091156b 100644
--- a/x-pack/plugins/data_usage/public/app/components/dataset_quality_link.tsx
+++ b/x-pack/plugins/data_usage/public/app/components/dataset_quality_link.tsx
@@ -6,13 +6,14 @@
*/
import React from 'react';
-import { EuiListGroupItem } from '@elastic/eui';
import {
DataQualityDetailsLocatorParams,
DATA_QUALITY_DETAILS_LOCATOR_ID,
} from '@kbn/deeplinks-observability';
import { useKibanaContextForPlugin } from '../../utils/use_kibana';
import { useDateRangePicker } from '../hooks/use_date_picker';
+import { LegendActionItem } from './legend_action_item';
+import { UX_LABELS } from '../../translations';
interface DatasetQualityLinkProps {
dataStreamName: string;
@@ -39,6 +40,8 @@ export const DatasetQualityLink: React.FC = React.memo(
await locator.navigate(locatorParams);
}
};
- return ;
+ return (
+
+ );
}
);
diff --git a/x-pack/plugins/data_usage/public/app/components/filters/charts_filter.tsx b/x-pack/plugins/data_usage/public/app/components/filters/charts_filter.tsx
index 6b4806537e74b..fcff6fc13f260 100644
--- a/x-pack/plugins/data_usage/public/app/components/filters/charts_filter.tsx
+++ b/x-pack/plugins/data_usage/public/app/components/filters/charts_filter.tsx
@@ -5,18 +5,15 @@
* 2.0.
*/
-import { orderBy } from 'lodash/fp';
+import { orderBy, findKey } from 'lodash/fp';
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
-import { EuiPopoverTitle, EuiSelectable } from '@elastic/eui';
+import { EuiPopoverTitle, EuiSelectable, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { useTestIdGenerator } from '../../../hooks/use_test_id_generator';
-import {
- METRIC_TYPE_API_VALUES_TO_UI_OPTIONS_MAP,
- type MetricTypes,
-} from '../../../../common/rest_types';
-
-import { UX_LABELS } from '../../translations';
+import { METRIC_TYPE_API_VALUES_TO_UI_OPTIONS_MAP } from '../../../../common/rest_types';
+import { UX_LABELS } from '../../../translations';
import { ChartsFilterPopover } from './charts_filter_popover';
+import { ToggleAllButton } from './toggle_all_button';
import { FilterItems, FilterName, useChartsFilter } from '../../hooks';
const getSearchPlaceholder = (filterName: FilterName) => {
@@ -84,6 +81,11 @@ export const ChartsFilter = memo(
},
});
+ const addHeightToPopover = useMemo(
+ () => isDataStreamsFilter && numFilters + numActiveFilters > 15,
+ [isDataStreamsFilter, numFilters, numActiveFilters]
+ );
+
// track popover state to pin selected options
const wasPopoverOpen = useRef(isPopoverOpen);
@@ -102,7 +104,7 @@ export const ChartsFilter = memo(
);
// augmented options based on the dataStreams filter
- const sortedHostsFilterOptions = useMemo(() => {
+ const sortedDataStreamsFilterOptions = useMemo(() => {
if (shouldPinSelectedDataStreams() || areDataStreamsSelectedOnMount) {
// pin checked items to the top
return orderBy('checked', 'asc', items);
@@ -116,12 +118,6 @@ export const ChartsFilter = memo(
const onOptionsChange = useCallback(
(newOptions: FilterItems) => {
const optionItemsToSet = newOptions.map((option) => option);
- const currChecks = optionItemsToSet.filter((option) => option.checked === 'on');
-
- // don't update filter state if trying to uncheck all options
- if (currChecks.length < 1) {
- return;
- }
// update filter UI options state
setItems(optionItemsToSet);
@@ -136,13 +132,9 @@ export const ChartsFilter = memo(
// update URL params
if (isMetricsFilter) {
- setUrlMetricTypesFilter(
- selectedItems
- .map((item) => METRIC_TYPE_API_VALUES_TO_UI_OPTIONS_MAP[item as MetricTypes])
- .join()
- );
+ setUrlMetricTypesFilter(selectedItems.join(','));
} else if (isDataStreamsFilter) {
- setUrlDataStreamsFilter(selectedItems.join());
+ setUrlDataStreamsFilter(selectedItems.join(','));
}
// reset shouldPinSelectedDataStreams, setAreDataStreamsSelectedOnMount
shouldPinSelectedDataStreams(false);
@@ -162,6 +154,63 @@ export const ChartsFilter = memo(
]
);
+ const onSelectAll = useCallback(() => {
+ const allItems: FilterItems = items.map((item) => {
+ return {
+ ...item,
+ checked: 'on',
+ };
+ });
+ setItems(allItems);
+ const optionsToSelect = allItems.map((i) => i.label);
+ onChangeFilterOptions(optionsToSelect);
+
+ if (isDataStreamsFilter) {
+ setUrlDataStreamsFilter(optionsToSelect.join(','));
+ }
+ if (isMetricsFilter) {
+ setUrlMetricTypesFilter(
+ optionsToSelect
+ .map((option) => findKey(METRIC_TYPE_API_VALUES_TO_UI_OPTIONS_MAP, option))
+ .join(',')
+ );
+ }
+ }, [
+ items,
+ isDataStreamsFilter,
+ isMetricsFilter,
+ setItems,
+ onChangeFilterOptions,
+ setUrlDataStreamsFilter,
+ setUrlMetricTypesFilter,
+ ]);
+
+ const onClearAll = useCallback(() => {
+ setItems(
+ items.map((item) => {
+ return {
+ ...item,
+ checked: undefined,
+ };
+ })
+ );
+ onChangeFilterOptions([]);
+ if (isDataStreamsFilter) {
+ setUrlDataStreamsFilter('');
+ }
+ if (isMetricsFilter) {
+ setUrlMetricTypesFilter('');
+ }
+ }, [
+ items,
+ isDataStreamsFilter,
+ isMetricsFilter,
+ setItems,
+ onChangeFilterOptions,
+ setUrlDataStreamsFilter,
+ setUrlMetricTypesFilter,
+ ]);
+
useEffect(() => {
return () => {
wasPopoverOpen.current = isPopoverOpen;
@@ -182,9 +231,10 @@ export const ChartsFilter = memo(
(
)}
{list}
+
+
+
+
+
+
+
+
);
}}
diff --git a/x-pack/plugins/data_usage/public/app/components/filters/charts_filter_popover.tsx b/x-pack/plugins/data_usage/public/app/components/filters/charts_filter_popover.tsx
index 3c0237c84a0c9..a2f4585e592ce 100644
--- a/x-pack/plugins/data_usage/public/app/components/filters/charts_filter_popover.tsx
+++ b/x-pack/plugins/data_usage/public/app/components/filters/charts_filter_popover.tsx
@@ -9,7 +9,7 @@ import React, { memo, useMemo } from 'react';
import { EuiFilterButton, EuiPopover, useGeneratedHtmlId } from '@elastic/eui';
import { useTestIdGenerator } from '../../../hooks/use_test_id_generator';
import { type FilterName } from '../../hooks/use_charts_filter';
-import { FILTER_NAMES } from '../../translations';
+import { FILTER_NAMES } from '../../../translations';
export const ChartsFilterPopover = memo(
({
diff --git a/x-pack/plugins/data_usage/public/app/components/filters/date_picker.tsx b/x-pack/plugins/data_usage/public/app/components/filters/date_picker.tsx
index 62c6cc542a523..81ab435670f89 100644
--- a/x-pack/plugins/data_usage/public/app/components/filters/date_picker.tsx
+++ b/x-pack/plugins/data_usage/public/app/components/filters/date_picker.tsx
@@ -15,8 +15,9 @@ import type {
OnRefreshChangeProps,
} from '@elastic/eui/src/components/date_picker/types';
import { UI_SETTINGS } from '@kbn/data-plugin/common';
-import moment from 'moment';
+import { momentDateParser } from '../../../../common/utils';
import { useTestIdGenerator } from '../../../hooks/use_test_id_generator';
+import { DEFAULT_DATE_RANGE_OPTIONS } from '../../hooks/use_date_picker';
export interface DateRangePickerValues {
autoRefreshOptions: {
@@ -50,16 +51,23 @@ export const UsageMetricsDateRangePicker = memo
();
const { uiSettings } = kibana.services;
const [commonlyUsedRanges] = useState(() => {
- return (
- uiSettings
- ?.get(UI_SETTINGS.TIMEPICKER_QUICK_RANGES)
- ?.map(({ from, to, display }: { from: string; to: string; display: string }) => {
- return {
+ const _commonlyUsedRanges: Array<{ from: string; to: string; display: string }> =
+ uiSettings.get(UI_SETTINGS.TIMEPICKER_QUICK_RANGES);
+ if (!_commonlyUsedRanges) {
+ return [];
+ }
+ return _commonlyUsedRanges.reduce(
+ (acc, { from, to, display }: { from: string; to: string; display: string }) => {
+ if (!['now-30d/d', 'now-90d/d', 'now-1y/d'].includes(from)) {
+ acc.push({
start: from,
end: to,
label: display,
- };
- }) ?? []
+ });
+ }
+ return acc;
+ },
+ []
);
});
@@ -80,9 +88,9 @@ export const UsageMetricsDateRangePicker = memo
);
diff --git a/x-pack/plugins/data_usage/public/app/components/filters/toggle_all_button.tsx b/x-pack/plugins/data_usage/public/app/components/filters/toggle_all_button.tsx
new file mode 100644
index 0000000000000..3d1c4080fcc9c
--- /dev/null
+++ b/x-pack/plugins/data_usage/public/app/components/filters/toggle_all_button.tsx
@@ -0,0 +1,45 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { css } from '@emotion/react';
+import { euiThemeVars } from '@kbn/ui-theme';
+import React, { memo } from 'react';
+import { EuiButtonEmpty, EuiButtonEmptyProps } from '@elastic/eui';
+
+const EuiButtonEmptyCss = css`
+ border-top: ${euiThemeVars.euiBorderThin};
+ border-radius: 0;
+`;
+
+interface ToggleAllButtonProps {
+ 'data-test-subj'?: string;
+ color: EuiButtonEmptyProps['color'];
+ icon: EuiButtonEmptyProps['iconType'];
+ isDisabled: boolean;
+ onClick: () => void;
+ label: string;
+}
+
+export const ToggleAllButton = memo(
+ ({ color, 'data-test-subj': dataTestSubj, icon, isDisabled, label, onClick }) => {
+ // const getTestId = useTestIdGenerator(dataTestSubj);
+ return (
+
+ {label}
+
+ );
+ }
+);
+
+ToggleAllButton.displayName = 'ToggleAllButton';
diff --git a/x-pack/plugins/data_usage/public/app/components/legend_action.tsx b/x-pack/plugins/data_usage/public/app/components/legend_action.tsx
index c9059037c4445..b748b77163245 100644
--- a/x-pack/plugins/data_usage/public/app/components/legend_action.tsx
+++ b/x-pack/plugins/data_usage/public/app/components/legend_action.tsx
@@ -5,18 +5,12 @@
* 2.0.
*/
import React, { useCallback } from 'react';
-import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiButtonIcon,
- EuiPopover,
- EuiListGroup,
- EuiListGroupItem,
- EuiSpacer,
-} from '@elastic/eui';
+import { EuiFlexGroup, EuiFlexItem, EuiButtonIcon, EuiPopover, EuiListGroup } from '@elastic/eui';
import { IndexManagementLocatorParams } from '@kbn/index-management-shared-types';
import { DatasetQualityLink } from './dataset_quality_link';
import { useKibanaContextForPlugin } from '../../utils/use_kibana';
+import { LegendActionItem } from './legend_action_item';
+import { UX_LABELS } from '../../translations';
interface LegendActionProps {
idx: number;
@@ -63,7 +57,7 @@ export const LegendAction: React.FC = React.memo(
togglePopover(uniqueStreamName)}
/>
@@ -74,11 +68,15 @@ export const LegendAction: React.FC = React.memo(
anchorPosition="downRight"
>
-
-
-
+
{hasIndexManagementFeature && (
-
+
)}
{hasDataSetQualityFeature && }
diff --git a/x-pack/plugins/data_usage/public/app/components/legend_action_item.tsx b/x-pack/plugins/data_usage/public/app/components/legend_action_item.tsx
new file mode 100644
index 0000000000000..3b4f0d9f698f7
--- /dev/null
+++ b/x-pack/plugins/data_usage/public/app/components/legend_action_item.tsx
@@ -0,0 +1,17 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { memo } from 'react';
+import { EuiListGroupItem } from '@elastic/eui';
+
+export const LegendActionItem = memo(
+ ({ label, onClick }: { label: string; onClick: () => Promise | void }) => (
+
+ )
+);
+
+LegendActionItem.displayName = 'LegendActionItem';
diff --git a/x-pack/plugins/data_usage/public/app/components/no_data_callout.tsx b/x-pack/plugins/data_usage/public/app/components/no_data_callout.tsx
new file mode 100644
index 0000000000000..c8c06db351060
--- /dev/null
+++ b/x-pack/plugins/data_usage/public/app/components/no_data_callout.tsx
@@ -0,0 +1,59 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { EuiPanel, EuiFlexGroup, EuiFlexItem, EuiImage, EuiText, EuiTitle } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n-react';
+import icon from './assets/illustration_product_no_results_magnifying_glass.svg';
+import { useTestIdGenerator } from '../../hooks/use_test_id_generator';
+
+export const NoDataCallout = ({
+ 'data-test-subj': dateTestSubj,
+}: {
+ 'data-test-subj'?: string;
+}) => {
+ const getTestId = useTestIdGenerator(dateTestSubj);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+NoDataCallout.displayName = 'NoDataCallout';
diff --git a/x-pack/plugins/data_usage/public/app/data_usage_metrics_page.tsx b/x-pack/plugins/data_usage/public/app/data_usage_metrics_page.tsx
index 69edb7a7f01ce..adc53e12b5749 100644
--- a/x-pack/plugins/data_usage/public/app/data_usage_metrics_page.tsx
+++ b/x-pack/plugins/data_usage/public/app/data_usage_metrics_page.tsx
@@ -7,7 +7,7 @@
import React from 'react';
import { DataUsagePage } from './components/page';
-import { DATA_USAGE_PAGE } from './translations';
+import { DATA_USAGE_PAGE } from '../translations';
import { DataUsageMetrics } from './components/data_usage_metrics';
export const DataUsageMetricsPage = () => {
diff --git a/x-pack/plugins/data_usage/public/app/hooks/use_charts_filter.tsx b/x-pack/plugins/data_usage/public/app/hooks/use_charts_filter.tsx
index d2c5dc554ff2d..012a6027aadb2 100644
--- a/x-pack/plugins/data_usage/public/app/hooks/use_charts_filter.tsx
+++ b/x-pack/plugins/data_usage/public/app/hooks/use_charts_filter.tsx
@@ -6,13 +6,13 @@
*/
import { useState, useEffect, useMemo } from 'react';
+import { DEFAULT_SELECTED_OPTIONS } from '../../../common';
import {
- isDefaultMetricType,
- METRIC_TYPE_API_VALUES_TO_UI_OPTIONS_MAP,
METRIC_TYPE_VALUES,
+ METRIC_TYPE_API_VALUES_TO_UI_OPTIONS_MAP,
+ isDefaultMetricType,
} from '../../../common/rest_types';
-import { DEFAULT_SELECTED_OPTIONS } from '../../../common';
-import { FILTER_NAMES } from '../translations';
+import { FILTER_NAMES } from '../../translations';
import { useDataUsageMetricsUrlParams } from './use_charts_url_params';
import { formatBytes } from '../../utils/format_bytes';
import { ChartsFilterProps } from '../components/filters/charts_filter';
@@ -48,6 +48,7 @@ export const useChartsFilter = ({
} => {
const {
dataStreams: selectedDataStreamsFromUrl,
+ metricTypes: selectedMetricTypesFromUrl,
setUrlMetricTypesFilter,
setUrlDataStreamsFilter,
} = useDataUsageMetricsUrlParams();
@@ -73,8 +74,13 @@ export const useChartsFilter = ({
? METRIC_TYPE_VALUES.map((metricType) => ({
key: metricType,
label: METRIC_TYPE_API_VALUES_TO_UI_OPTIONS_MAP[metricType],
- checked: isDefaultMetricType(metricType) ? 'on' : undefined, // default metrics are selected by default
- disabled: isDefaultMetricType(metricType),
+ checked: selectedMetricTypesFromUrl
+ ? selectedMetricTypesFromUrl.includes(metricType)
+ ? 'on'
+ : undefined
+ : isDefaultMetricType(metricType) // default metrics are selected by default
+ ? 'on'
+ : undefined,
'data-test-subj': `${filterOptions.filterName}-filter-option`,
}))
: isDataStreamsFilter && !!filterOptions.options.length
diff --git a/x-pack/plugins/data_usage/public/app/hooks/use_charts_url_params.test.tsx b/x-pack/plugins/data_usage/public/app/hooks/use_charts_url_params.test.tsx
index c73e35fe1397d..20f091029f5b8 100644
--- a/x-pack/plugins/data_usage/public/app/hooks/use_charts_url_params.test.tsx
+++ b/x-pack/plugins/data_usage/public/app/hooks/use_charts_url_params.test.tsx
@@ -5,12 +5,10 @@
* 2.0.
*/
-import moment from 'moment';
-import { METRIC_TYPE_VALUES, MetricTypes } from '../../../common/rest_types';
+import { METRIC_TYPE_VALUES, type MetricTypes } from '../../../common/rest_types';
import { getDataUsageMetricsFiltersFromUrlParams } from './use_charts_url_params';
-// FLAKY: https://github.com/elastic/kibana/issues/200888
-describe.skip('#getDataUsageMetricsFiltersFromUrlParams', () => {
+describe('#getDataUsageMetricsFiltersFromUrlParams', () => {
const getMetricTypesAsArray = (): MetricTypes[] => {
return [...METRIC_TYPE_VALUES];
};
@@ -58,12 +56,12 @@ describe.skip('#getDataUsageMetricsFiltersFromUrlParams', () => {
it('should use given relative startDate and endDate values URL params', () => {
expect(
getDataUsageMetricsFiltersFromUrlParams({
- startDate: moment().subtract(24, 'hours').toISOString(),
- endDate: moment().toISOString(),
+ startDate: 'now-9d',
+ endDate: 'now-24h/h',
})
).toEqual({
- endDate: moment().toISOString(),
- startDate: moment().subtract(24, 'hours').toISOString(),
+ endDate: 'now-24h/h',
+ startDate: 'now-9d',
});
});
diff --git a/x-pack/plugins/data_usage/public/app/hooks/use_charts_url_params.tsx b/x-pack/plugins/data_usage/public/app/hooks/use_charts_url_params.tsx
index ed833393ad7eb..3a1ba7dc1de62 100644
--- a/x-pack/plugins/data_usage/public/app/hooks/use_charts_url_params.tsx
+++ b/x-pack/plugins/data_usage/public/app/hooks/use_charts_url_params.tsx
@@ -6,7 +6,7 @@
*/
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useHistory, useLocation } from 'react-router-dom';
-import { MetricTypes, isMetricType } from '../../../common/rest_types';
+import { type MetricTypes, isMetricType } from '../../../common/rest_types';
import { useUrlParams } from '../../hooks/use_url_params';
import { DEFAULT_DATE_RANGE_OPTIONS } from './use_date_picker';
diff --git a/x-pack/plugins/data_usage/public/app/hooks/use_date_picker.tsx b/x-pack/plugins/data_usage/public/app/hooks/use_date_picker.tsx
index 1b4b7e38e3554..f4d198461f733 100644
--- a/x-pack/plugins/data_usage/public/app/hooks/use_date_picker.tsx
+++ b/x-pack/plugins/data_usage/public/app/hooks/use_date_picker.tsx
@@ -5,7 +5,6 @@
* 2.0.
*/
-import moment from 'moment';
import { useCallback, useState } from 'react';
import type {
DurationRange,
@@ -19,8 +18,10 @@ export const DEFAULT_DATE_RANGE_OPTIONS = Object.freeze({
enabled: false,
duration: 10000,
},
- startDate: moment().subtract(24, 'hours').startOf('day').toISOString(),
- endDate: moment().toISOString(),
+ startDate: 'now-24h/h',
+ endDate: 'now',
+ maxDate: 'now+1s',
+ minDate: 'now-9d',
recentlyUsedDateRanges: [],
});
diff --git a/x-pack/plugins/data_usage/public/application.tsx b/x-pack/plugins/data_usage/public/application.tsx
index 0e6cdc6192c7c..7bd2c794d5b3c 100644
--- a/x-pack/plugins/data_usage/public/application.tsx
+++ b/x-pack/plugins/data_usage/public/application.tsx
@@ -16,8 +16,8 @@ import { PerformanceContextProvider } from '@kbn/ebt-tools';
import { useKibanaContextForPluginProvider } from './utils/use_kibana';
import { DataUsageStartDependencies, DataUsagePublicStart } from './types';
import { PLUGIN_ID } from '../common';
-import { DataUsageMetricsPage } from './app/data_usage_metrics_page';
import { DataUsageReactQueryClientProvider } from '../common/query_client';
+import { DataUsageMetricsPage } from './app/data_usage_metrics_page';
export const renderApp = (
core: CoreStart,
diff --git a/x-pack/plugins/data_usage/public/hooks/use_get_data_streams.test.tsx b/x-pack/plugins/data_usage/public/hooks/use_get_data_streams.test.tsx
index 04cee589a523d..5e224e635dca4 100644
--- a/x-pack/plugins/data_usage/public/hooks/use_get_data_streams.test.tsx
+++ b/x-pack/plugins/data_usage/public/hooks/use_get_data_streams.test.tsx
@@ -11,7 +11,7 @@ import { renderHook } from '@testing-library/react-hooks';
import { useGetDataUsageDataStreams } from './use_get_data_streams';
import { DATA_USAGE_DATA_STREAMS_API_ROUTE } from '../../common';
import { coreMock as mockCore } from '@kbn/core/public/mocks';
-import { dataUsageTestQueryClientOptions } from '../../common/test_utils/test_query_client_options';
+import { dataUsageTestQueryClientOptions } from '../../common/test_utils';
const useQueryMock = _useQuery as jest.Mock;
diff --git a/x-pack/plugins/data_usage/public/hooks/use_get_usage_metrics.test.tsx b/x-pack/plugins/data_usage/public/hooks/use_get_usage_metrics.test.tsx
index 677bd4bdfcef1..1ddb84d89ffc9 100644
--- a/x-pack/plugins/data_usage/public/hooks/use_get_usage_metrics.test.tsx
+++ b/x-pack/plugins/data_usage/public/hooks/use_get_usage_metrics.test.tsx
@@ -5,14 +5,13 @@
* 2.0.
*/
-import moment from 'moment';
import React, { ReactNode } from 'react';
import { QueryClient, QueryClientProvider, useQuery as _useQuery } from '@tanstack/react-query';
import { renderHook } from '@testing-library/react-hooks';
import { useGetDataUsageMetrics } from './use_get_usage_metrics';
import { DATA_USAGE_METRICS_API_ROUTE } from '../../common';
import { coreMock as mockCore } from '@kbn/core/public/mocks';
-import { dataUsageTestQueryClientOptions } from '../../common/test_utils/test_query_client_options';
+import { dataUsageTestQueryClientOptions, timeXMinutesAgo } from '../../common/test_utils';
const useQueryMock = _useQuery as jest.Mock;
@@ -42,8 +41,8 @@ jest.mock('../utils/use_kibana', () => {
});
const defaultUsageMetricsRequestBody = {
- from: moment().subtract(15, 'minutes').toISOString(),
- to: moment().toISOString(),
+ from: timeXMinutesAgo(15),
+ to: timeXMinutesAgo(0),
metricTypes: ['ingest_rate'],
dataStreams: ['ds-1'],
};
diff --git a/x-pack/plugins/data_usage/public/hooks/use_get_usage_metrics.ts b/x-pack/plugins/data_usage/public/hooks/use_get_usage_metrics.ts
index 6b2ef5316b0f6..da5f3004d0024 100644
--- a/x-pack/plugins/data_usage/public/hooks/use_get_usage_metrics.ts
+++ b/x-pack/plugins/data_usage/public/hooks/use_get_usage_metrics.ts
@@ -8,8 +8,12 @@
import type { UseQueryOptions, UseQueryResult } from '@tanstack/react-query';
import { useQuery } from '@tanstack/react-query';
import type { IHttpFetchError } from '@kbn/core-http-browser';
-import { UsageMetricsRequestBody, UsageMetricsResponseSchemaBody } from '../../common/rest_types';
+import { dateParser } from '../../common/utils';
import { DATA_USAGE_METRICS_API_ROUTE } from '../../common';
+import type {
+ UsageMetricsRequestBody,
+ UsageMetricsResponseSchemaBody,
+} from '../../common/rest_types';
import { useKibanaContextForPlugin } from '../utils/use_kibana';
interface ErrorType {
@@ -33,8 +37,8 @@ export const useGetDataUsageMetrics = (
signal,
version: '1',
body: JSON.stringify({
- from: body.from,
- to: body.to,
+ from: dateParser(body.from),
+ to: dateParser(body.to),
metricTypes: body.metricTypes,
dataStreams: body.dataStreams,
}),
diff --git a/x-pack/plugins/data_usage/public/plugin.ts b/x-pack/plugins/data_usage/public/plugin.ts
index aa3b02c2b671b..b43dcebe25c18 100644
--- a/x-pack/plugins/data_usage/public/plugin.ts
+++ b/x-pack/plugins/data_usage/public/plugin.ts
@@ -13,7 +13,8 @@ import {
DataUsageStartDependencies,
DataUsageSetupDependencies,
} from './types';
-import { PLUGIN_ID, PLUGIN_NAME } from '../common';
+import { PLUGIN_ID } from '../common';
+import { PLUGIN_NAME } from './translations';
export class DataUsagePlugin
implements
diff --git a/x-pack/plugins/data_usage/public/app/translations.tsx b/x-pack/plugins/data_usage/public/translations.tsx
similarity index 68%
rename from x-pack/plugins/data_usage/public/app/translations.tsx
rename to x-pack/plugins/data_usage/public/translations.tsx
index ee42d3b58906b..0996ec2bb6d50 100644
--- a/x-pack/plugins/data_usage/public/app/translations.tsx
+++ b/x-pack/plugins/data_usage/public/translations.tsx
@@ -7,6 +7,10 @@
import { i18n } from '@kbn/i18n';
+export const PLUGIN_NAME = i18n.translate('xpack.dataUsage.name', {
+ defaultMessage: 'Data Usage',
+});
+
export const FILTER_NAMES = Object.freeze({
metricTypes: i18n.translate('xpack.dataUsage.metrics.filter.metricTypes', {
defaultMessage: 'Metric types',
@@ -35,6 +39,9 @@ export const DATA_USAGE_PAGE = Object.freeze({
});
export const UX_LABELS = Object.freeze({
+ filterSelectAll: i18n.translate('xpack.dataUsage.metrics.filter.selectAll', {
+ defaultMessage: 'Select all',
+ }),
filterClearAll: i18n.translate('xpack.dataUsage.metrics.filter.clearAll', {
defaultMessage: 'Clear all',
}),
@@ -48,4 +55,18 @@ export const UX_LABELS = Object.freeze({
defaultMessage: 'No {filterName} available',
values: { filterName },
}),
+ dataQualityPopup: {
+ open: i18n.translate('xpack.dataUsage.metrics.dataQuality.open.actions', {
+ defaultMessage: 'Open data stream actions',
+ }),
+ copy: i18n.translate('xpack.dataUsage.metrics.dataQuality.copy.dataStream', {
+ defaultMessage: 'Copy data stream name',
+ }),
+ manage: i18n.translate('xpack.dataUsage.metrics.dataQuality.manage.dataStream', {
+ defaultMessage: 'Manage data stream',
+ }),
+ view: i18n.translate('xpack.dataUsage.metrics.dataQuality.view', {
+ defaultMessage: 'View data quality',
+ }),
+ },
});
diff --git a/x-pack/plugins/data_usage/server/routes/internal/data_streams.test.ts b/x-pack/plugins/data_usage/server/routes/internal/data_streams.test.ts
index 2330e465d9b12..374c4b9c82e7e 100644
--- a/x-pack/plugins/data_usage/server/routes/internal/data_streams.test.ts
+++ b/x-pack/plugins/data_usage/server/routes/internal/data_streams.test.ts
@@ -84,6 +84,48 @@ describe('registerDataStreamsRoute', () => {
});
});
+ it('should not include data streams with 0 size', async () => {
+ mockGetMeteringStats.mockResolvedValue({
+ datastreams: [
+ {
+ name: 'datastream1',
+ size_in_bytes: 100,
+ },
+ {
+ name: 'datastream2',
+ size_in_bytes: 200,
+ },
+ {
+ name: 'datastream3',
+ size_in_bytes: 0,
+ },
+ {
+ name: 'datastream4',
+ size_in_bytes: 0,
+ },
+ ],
+ });
+ const mockRequest = httpServerMock.createKibanaRequest({ body: {} });
+ const mockResponse = httpServerMock.createResponseFactory();
+ const mockRouter = mockCore.http.createRouter.mock.results[0].value;
+ const [[, handler]] = mockRouter.versioned.get.mock.results[0].value.addVersion.mock.calls;
+ await handler(context, mockRequest, mockResponse);
+
+ expect(mockResponse.ok).toHaveBeenCalledTimes(1);
+ expect(mockResponse.ok.mock.calls[0][0]).toEqual({
+ body: [
+ {
+ name: 'datastream2',
+ storageSizeBytes: 200,
+ },
+ {
+ name: 'datastream1',
+ storageSizeBytes: 100,
+ },
+ ],
+ });
+ });
+
it('should return correct error if metering stats request fails', async () => {
// using custom error for test here to avoid having to import the actual error class
mockGetMeteringStats.mockRejectedValue(
@@ -105,7 +147,7 @@ describe('registerDataStreamsRoute', () => {
it.each([
['no datastreams', {}, []],
['empty array', { datastreams: [] }, []],
- ['an empty element', { datastreams: [{}] }, [{ name: undefined, storageSizeBytes: 0 }]],
+ ['an empty element', { datastreams: [{}] }, []],
])('should return empty array when no stats data with %s', async (_, stats, res) => {
mockGetMeteringStats.mockResolvedValue(stats);
const mockRequest = httpServerMock.createKibanaRequest({ body: {} });
diff --git a/x-pack/plugins/data_usage/server/routes/internal/data_streams_handler.ts b/x-pack/plugins/data_usage/server/routes/internal/data_streams_handler.ts
index 9abd898358e9e..99b4e982c5a40 100644
--- a/x-pack/plugins/data_usage/server/routes/internal/data_streams_handler.ts
+++ b/x-pack/plugins/data_usage/server/routes/internal/data_streams_handler.ts
@@ -27,10 +27,15 @@ export const getDataStreamsHandler = (
meteringStats && !!meteringStats.length
? meteringStats
.sort((a, b) => b.size_in_bytes - a.size_in_bytes)
- .map((stat) => ({
- name: stat.name,
- storageSizeBytes: stat.size_in_bytes ?? 0,
- }))
+ .reduce>((acc, stat) => {
+ if (stat.size_in_bytes > 0) {
+ acc.push({
+ name: stat.name,
+ storageSizeBytes: stat.size_in_bytes ?? 0,
+ });
+ }
+ return acc;
+ }, [])
: [];
return response.ok({
diff --git a/x-pack/plugins/data_usage/server/routes/internal/usage_metrics.test.ts b/x-pack/plugins/data_usage/server/routes/internal/usage_metrics.test.ts
index d6337bbcc8dcd..c0eb0e5e8ef2d 100644
--- a/x-pack/plugins/data_usage/server/routes/internal/usage_metrics.test.ts
+++ b/x-pack/plugins/data_usage/server/routes/internal/usage_metrics.test.ts
@@ -4,7 +4,6 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import moment from 'moment';
import type { MockedKeys } from '@kbn/utility-types-jest';
import type { CoreSetup } from '@kbn/core/server';
import { registerUsageMetricsRoute } from './usage_metrics';
@@ -20,6 +19,7 @@ import { DATA_USAGE_METRICS_API_ROUTE } from '../../../common';
import { createMockedDataUsageContext } from '../../mocks';
import { CustomHttpRequestError } from '../../utils';
import { AutoOpsError } from '../../services/errors';
+import { timeXMinutesAgo } from '../../../common/test_utils';
describe('registerUsageMetricsRoute', () => {
let mockCore: MockedKeys>;
@@ -56,8 +56,8 @@ describe('registerUsageMetricsRoute', () => {
const mockRequest = httpServerMock.createKibanaRequest({
body: {
- from: moment().subtract(15, 'minutes').toISOString(),
- to: moment().toISOString(),
+ from: timeXMinutesAgo(15),
+ to: timeXMinutesAgo(0),
metricTypes: ['ingest_rate'],
dataStreams: [],
},
@@ -123,8 +123,8 @@ describe('registerUsageMetricsRoute', () => {
const mockRequest = httpServerMock.createKibanaRequest({
body: {
- from: moment().subtract(15, 'minutes').toISOString(),
- to: moment().toISOString(),
+ from: timeXMinutesAgo(15),
+ to: timeXMinutesAgo(0),
metricTypes: ['ingest_rate', 'storage_retained'],
dataStreams: ['.ds-1', '.ds-2'],
},
@@ -191,8 +191,8 @@ describe('registerUsageMetricsRoute', () => {
const mockRequest = httpServerMock.createKibanaRequest({
body: {
- from: moment().subtract(15, 'minutes').toISOString(),
- to: moment().toISOString(),
+ from: timeXMinutesAgo(15),
+ to: timeXMinutesAgo(0),
metricTypes: ['ingest_rate'],
dataStreams: ['.ds-1', '.ds-2'],
},
diff --git a/x-pack/plugins/data_usage/server/routes/internal/usage_metrics_handler.ts b/x-pack/plugins/data_usage/server/routes/internal/usage_metrics_handler.ts
index 6907a683696a7..c2dee4ca2ce52 100644
--- a/x-pack/plugins/data_usage/server/routes/internal/usage_metrics_handler.ts
+++ b/x-pack/plugins/data_usage/server/routes/internal/usage_metrics_handler.ts
@@ -5,8 +5,9 @@
* 2.0.
*/
+import { chunk } from 'lodash/fp';
import { RequestHandler } from '@kbn/core/server';
-import {
+import type {
MetricTypes,
UsageMetricsAutoOpsResponseSchemaBody,
UsageMetricsRequestBody,
@@ -30,6 +31,8 @@ export const getUsageMetricsHandler = (
const core = await context.core;
const esClient = core.elasticsearch.client.asCurrentUser;
+ const getDataStreams = (name: string[]) =>
+ esClient.indices.getDataStream({ name, expand_wildcards: 'all' });
logger.debug(`Retrieving usage metrics`);
const { from, to, metricTypes, dataStreams: requestDsNames } = request.body;
@@ -43,15 +46,24 @@ export const getUsageMetricsHandler = (
new CustomHttpRequestError('[request body.dataStreams]: no data streams selected', 400)
);
}
- let dataStreamsResponse;
+
+ let dataStreamsResponse: Array<{ name: string }>;
try {
- // Attempt to fetch data streams
- const { data_streams: dataStreams } = await esClient.indices.getDataStream({
- name: requestDsNames,
- expand_wildcards: 'all',
- });
- dataStreamsResponse = dataStreams;
+ if (requestDsNames.length <= 50) {
+ logger.debug(`Retrieving usage metrics`);
+ const { data_streams: dataStreams } = await getDataStreams(requestDsNames);
+ dataStreamsResponse = dataStreams;
+ } else {
+ logger.debug(`Retrieving usage metrics in chunks of 50`);
+ // Attempt to fetch data streams in chunks of 50
+ const dataStreamsChunks = Math.ceil(requestDsNames.length / 50);
+ const chunkedDsLists = chunk(dataStreamsChunks, requestDsNames);
+ const chunkedDataStreams = await Promise.all(
+ chunkedDsLists.map((dsList) => getDataStreams(dsList))
+ );
+ dataStreamsResponse = chunkedDataStreams.flatMap((ds) => ds.data_streams);
+ }
} catch (error) {
return errorHandler(
logger,
diff --git a/x-pack/plugins/data_usage/server/services/autoops_api.ts b/x-pack/plugins/data_usage/server/services/autoops_api.ts
index 9fd742a3e73fa..2ff824e04f6dd 100644
--- a/x-pack/plugins/data_usage/server/services/autoops_api.ts
+++ b/x-pack/plugins/data_usage/server/services/autoops_api.ts
@@ -6,7 +6,7 @@
*/
import https from 'https';
-import dateMath from '@kbn/datemath';
+
import { SslConfig, sslSchema } from '@kbn/server-http-tools';
import apm from 'elastic-apm-node';
@@ -16,9 +16,10 @@ import axios from 'axios';
import { LogMeta } from '@kbn/core/server';
import {
UsageMetricsAutoOpsResponseSchema,
- UsageMetricsAutoOpsResponseSchemaBody,
- UsageMetricsRequestBody,
+ type UsageMetricsAutoOpsResponseSchemaBody,
+ type UsageMetricsRequestBody,
} from '../../common/rest_types';
+import { dateParser } from '../../common/utils';
import { AutoOpsConfig } from '../types';
import { AutoOpsError } from './errors';
import { appContextService } from './app_context';
@@ -30,7 +31,6 @@ const AUTO_OPS_MISSING_CONFIG_ERROR = 'Missing autoops configuration';
const getAutoOpsAPIRequestUrl = (url?: string, projectId?: string): string =>
`${url}/monitoring/serverless/v1/projects/${projectId}/metrics`;
-const dateParser = (date: string) => dateMath.parse(date)?.toISOString();
export class AutoOpsAPIService {
private logger: Logger;
constructor(logger: Logger) {
diff --git a/x-pack/plugins/data_usage/server/services/index.ts b/x-pack/plugins/data_usage/server/services/index.ts
index 69db6b590c6f3..56e449c8a5679 100644
--- a/x-pack/plugins/data_usage/server/services/index.ts
+++ b/x-pack/plugins/data_usage/server/services/index.ts
@@ -6,7 +6,7 @@
*/
import { ValidationError } from '@kbn/config-schema';
import { Logger } from '@kbn/logging';
-import { MetricTypes } from '../../common/rest_types';
+import type { MetricTypes } from '../../common/rest_types';
import { AutoOpsError } from './errors';
import { AutoOpsAPIService } from './autoops_api';
diff --git a/x-pack/plugins/data_usage/tsconfig.json b/x-pack/plugins/data_usage/tsconfig.json
index 309bad3e1b63c..8647f7957451a 100644
--- a/x-pack/plugins/data_usage/tsconfig.json
+++ b/x-pack/plugins/data_usage/tsconfig.json
@@ -33,6 +33,8 @@
"@kbn/server-http-tools",
"@kbn/utility-types-jest",
"@kbn/datemath",
+ "@kbn/ui-theme",
+ "@kbn/i18n-react",
],
"exclude": ["target/**/*"]
}
diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json
index dc6ae26d7f798..06506ff9d1c93 100644
--- a/x-pack/plugins/translations/translations/fr-FR.json
+++ b/x-pack/plugins/translations/translations/fr-FR.json
@@ -11696,8 +11696,8 @@
"xpack.apm.serviceIcons.service": "Service",
"xpack.apm.serviceIcons.serviceDetails.cloud.architecture": "Architecture",
"xpack.apm.serviceIcons.serviceDetails.cloud.availabilityZoneLabel": "{zones, plural, =0 {Zone de disponibilité} one {Zone de disponibilité} other {Zones de disponibilité}}",
- "xpack.apm.serviceIcons.serviceDetails.cloud.faasTriggerTypeLabel": "{triggerTypes, plural, =0 {Type de déclencheur} one {Type de déclencheur} other {Types de déclencheurs}}",
"xpack.apm.serviceIcons.serviceDetails.cloud.functionNameLabel": "{functionNames, plural, =0 {Nom de fonction} one {Nom de fonction} other {Noms de fonction}}",
+ "xpack.apm.serviceIcons.serviceDetails.cloud.faasTriggerTypeLabel": "{triggerTypes, plural, =0 {Type de déclencheur} one {Type de déclencheur} other {Types de déclencheurs}}",
"xpack.apm.serviceIcons.serviceDetails.cloud.machineTypesLabel": "{machineTypes, plural, =0{Type de machine} one {Type de machine} other {Types de machines}}",
"xpack.apm.serviceIcons.serviceDetails.cloud.projectIdLabel": "ID de projet",
"xpack.apm.serviceIcons.serviceDetails.cloud.providerLabel": "Fournisseur cloud",
@@ -15425,7 +15425,6 @@
"xpack.datasetQuality.types.label": "Types",
"xpack.dataUsage.charts.ingestedMax": "Données ingérées",
"xpack.dataUsage.charts.retainedMax": "Données conservées dans le stockage",
- "xpack.dataUsage.metrics.filter.clearAll": "Tout effacer",
"xpack.dataUsage.metrics.filter.dataStreams": "Flux de données",
"xpack.dataUsage.metrics.filter.emptyMessage": "Aucun {filterName} disponible",
"xpack.dataUsage.metrics.filter.metricTypes": "Types d'indicateurs",
@@ -28261,8 +28260,8 @@
"xpack.maps.source.esSearch.descendingLabel": "décroissant",
"xpack.maps.source.esSearch.extentFilterLabel": "Filtre dynamique pour les données de la zone de carte visible",
"xpack.maps.source.esSearch.fieldNotFoundMsg": "Impossible de trouver \"{fieldName}\" dans le modèle d'indexation \"{indexPatternName}\".",
- "xpack.maps.source.esSearch.geofieldLabel": "Champ géospatial",
"xpack.maps.source.esSearch.geoFieldLabel": "Champ géospatial",
+ "xpack.maps.source.esSearch.geofieldLabel": "Champ géospatial",
"xpack.maps.source.esSearch.geoFieldTypeLabel": "Type de champ géospatial",
"xpack.maps.source.esSearch.indexOverOneLengthEditError": "Votre vue de données pointe vers plusieurs index. Un seul index est autorisé par vue de données.",
"xpack.maps.source.esSearch.indexZeroLengthEditError": "Votre vue de données ne pointe vers aucun index.",
@@ -38014,8 +38013,8 @@
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.maxAlertsFieldLessThanWarning": "Kibana ne permet qu'un maximum de {maxNumber} {maxNumber, plural, =1 {alerte} other {alertes}} par exécution de règle.",
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.nameFieldRequiredError": "Nom obligatoire.",
"xpack.securitySolution.detectionEngine.createRule.stepAboutrule.noteHelpText": "Ajouter un guide d'investigation sur les règles...",
- "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "Ajouter le guide de configuration de règle...",
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupHelpText": "Fournissez des instructions sur les conditions préalables à la règle, telles que les intégrations requises, les étapes de configuration et tout ce qui est nécessaire au bon fonctionnement de la règle.",
+ "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "Ajouter le guide de configuration de règle...",
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupLabel": "Guide de configuration",
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.tagFieldEmptyError": "Une balise ne doit pas être vide",
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.threatIndicatorPathFieldEmptyError": "Le remplacement du préfixe d'indicateur ne peut pas être vide.",
@@ -43803,8 +43802,8 @@
"xpack.slo.sloEmbeddable.config.sloSelector.placeholder": "Sélectionner un SLO",
"xpack.slo.sloEmbeddable.displayName": "Aperçu du SLO",
"xpack.slo.sloEmbeddable.overview.sloNotFoundText": "Le SLO a été supprimé. Vous pouvez supprimer sans risque le widget du tableau de bord.",
- "xpack.slo.sloGridItem.targetFlexItemLabel": "Cible {target}",
"xpack.slo.sLOGridItem.targetFlexItemLabel": "Cible {target}",
+ "xpack.slo.sloGridItem.targetFlexItemLabel": "Cible {target}",
"xpack.slo.sloGroupConfiguration.customFiltersLabel": "Personnaliser le filtre",
"xpack.slo.sloGroupConfiguration.customFiltersOptional": "Facultatif",
"xpack.slo.sloGroupConfiguration.customFilterText": "Personnaliser le filtre",
@@ -45329,8 +45328,8 @@
"xpack.stackConnectors.components.casesWebhookxpack.stackConnectors.components.casesWebhook.connectorTypeTitle": "Webhook - Données de gestion des cas",
"xpack.stackConnectors.components.d3security.bodyCodeEditorAriaLabel": "Éditeur de code",
"xpack.stackConnectors.components.d3security.bodyFieldLabel": "Corps",
- "xpack.stackConnectors.components.d3security.connectorTypeTitle": "Données D3",
"xpack.stackConnectors.components.d3Security.connectorTypeTitle": "D3 Security",
+ "xpack.stackConnectors.components.d3security.connectorTypeTitle": "Données D3",
"xpack.stackConnectors.components.d3security.eventTypeFieldLabel": "Type d'événement",
"xpack.stackConnectors.components.d3security.invalidActionText": "Nom d'action non valide.",
"xpack.stackConnectors.components.d3security.requiredActionText": "L'action est requise.",
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index b060c39d5f1b8..d4c397428a8e0 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -11679,8 +11679,8 @@
"xpack.apm.serviceIcons.service": "サービス",
"xpack.apm.serviceIcons.serviceDetails.cloud.architecture": "アーキテクチャー",
"xpack.apm.serviceIcons.serviceDetails.cloud.availabilityZoneLabel": "{zones, plural, other {可用性ゾーン}}",
- "xpack.apm.serviceIcons.serviceDetails.cloud.faasTriggerTypeLabel": "{triggerTypes, plural, other {トリガータイプ}}",
"xpack.apm.serviceIcons.serviceDetails.cloud.functionNameLabel": "{functionNames, plural, other {関数名}}",
+ "xpack.apm.serviceIcons.serviceDetails.cloud.faasTriggerTypeLabel": "{triggerTypes, plural, other {トリガータイプ}}",
"xpack.apm.serviceIcons.serviceDetails.cloud.machineTypesLabel": "{machineTypes, plural, other {コンピュータータイプ} }\n",
"xpack.apm.serviceIcons.serviceDetails.cloud.projectIdLabel": "プロジェクト ID",
"xpack.apm.serviceIcons.serviceDetails.cloud.providerLabel": "クラウドプロバイダー",
@@ -15404,7 +15404,6 @@
"xpack.datasetQuality.types.label": "タイプ",
"xpack.dataUsage.charts.ingestedMax": "インジェストされたデータ",
"xpack.dataUsage.charts.retainedMax": "ストレージに保持されたデータ",
- "xpack.dataUsage.metrics.filter.clearAll": "すべて消去",
"xpack.dataUsage.metrics.filter.dataStreams": "データストリーム",
"xpack.dataUsage.metrics.filter.emptyMessage": "{filterName}がありません",
"xpack.dataUsage.metrics.filter.metricTypes": "メトリックタイプ",
@@ -28233,8 +28232,8 @@
"xpack.maps.source.esSearch.descendingLabel": "降順",
"xpack.maps.source.esSearch.extentFilterLabel": "マップの表示範囲でデータを動的にフィルタリング",
"xpack.maps.source.esSearch.fieldNotFoundMsg": "インデックスパターン''{indexPatternName}''に''{fieldName}''が見つかりません。",
- "xpack.maps.source.esSearch.geofieldLabel": "地理空間フィールド",
"xpack.maps.source.esSearch.geoFieldLabel": "地理空間フィールド",
+ "xpack.maps.source.esSearch.geofieldLabel": "地理空間フィールド",
"xpack.maps.source.esSearch.geoFieldTypeLabel": "地理空間フィールドタイプ",
"xpack.maps.source.esSearch.indexOverOneLengthEditError": "データビューは複数のインデックスを参照しています。データビューごとに1つのインデックスのみが許可されています。",
"xpack.maps.source.esSearch.indexZeroLengthEditError": "データビューはどのインデックスも参照していません。",
@@ -37981,8 +37980,8 @@
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.maxAlertsFieldLessThanWarning": "Kibanaで許可される最大数は、1回の実行につき、{maxNumber} {maxNumber, plural, other {アラート}}です。",
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.nameFieldRequiredError": "名前が必要です。",
"xpack.securitySolution.detectionEngine.createRule.stepAboutrule.noteHelpText": "ルール調査ガイドを追加...",
- "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "ルールセットアップガイドを追加...",
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupHelpText": "必要な統合、構成ステップ、ルールが正常に動作するために必要な他のすべての項目といった、ルール前提条件に関する指示を入力します。",
+ "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "ルールセットアップガイドを追加...",
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupLabel": "セットアップガイド",
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.tagFieldEmptyError": "タグを空にすることはできません",
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.threatIndicatorPathFieldEmptyError": "インジケータープレフィックスの無効化を空にすることはできません",
@@ -43767,8 +43766,8 @@
"xpack.slo.sloEmbeddable.config.sloSelector.placeholder": "SLOを選択",
"xpack.slo.sloEmbeddable.displayName": "SLO概要",
"xpack.slo.sloEmbeddable.overview.sloNotFoundText": "SLOが削除されました。ウィジェットをダッシュボードから安全に削除できます。",
- "xpack.slo.sloGridItem.targetFlexItemLabel": "目標{target}",
"xpack.slo.sLOGridItem.targetFlexItemLabel": "目標{target}",
+ "xpack.slo.sloGridItem.targetFlexItemLabel": "目標{target}",
"xpack.slo.sloGroupConfiguration.customFiltersLabel": "カスタムフィルター",
"xpack.slo.sloGroupConfiguration.customFiltersOptional": "オプション",
"xpack.slo.sloGroupConfiguration.customFilterText": "カスタムフィルター",
@@ -45288,8 +45287,8 @@
"xpack.stackConnectors.components.casesWebhookxpack.stackConnectors.components.casesWebhook.connectorTypeTitle": "Webフック - ケース管理データ",
"xpack.stackConnectors.components.d3security.bodyCodeEditorAriaLabel": "コードエディター",
"xpack.stackConnectors.components.d3security.bodyFieldLabel": "本文",
- "xpack.stackConnectors.components.d3security.connectorTypeTitle": "D3データ",
"xpack.stackConnectors.components.d3Security.connectorTypeTitle": "D3セキュリティ",
+ "xpack.stackConnectors.components.d3security.connectorTypeTitle": "D3データ",
"xpack.stackConnectors.components.d3security.eventTypeFieldLabel": "イベントタイプ",
"xpack.stackConnectors.components.d3security.invalidActionText": "無効なアクション名です。",
"xpack.stackConnectors.components.d3security.requiredActionText": "アクションが必要です。",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 4b5f21d04c964..e5ee0c1ede629 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -11449,8 +11449,8 @@
"xpack.apm.serviceIcons.service": "服务",
"xpack.apm.serviceIcons.serviceDetails.cloud.architecture": "架构",
"xpack.apm.serviceIcons.serviceDetails.cloud.availabilityZoneLabel": "{zones, plural, other {可用性区域}}",
- "xpack.apm.serviceIcons.serviceDetails.cloud.faasTriggerTypeLabel": "{triggerTypes, plural, other {触发类型}}",
"xpack.apm.serviceIcons.serviceDetails.cloud.functionNameLabel": "{functionNames, plural, other {功能名称}}",
+ "xpack.apm.serviceIcons.serviceDetails.cloud.faasTriggerTypeLabel": "{triggerTypes, plural, other {触发类型}}",
"xpack.apm.serviceIcons.serviceDetails.cloud.machineTypesLabel": "{machineTypes, plural, other {机器类型}}",
"xpack.apm.serviceIcons.serviceDetails.cloud.projectIdLabel": "项目 ID",
"xpack.apm.serviceIcons.serviceDetails.cloud.providerLabel": "云服务提供商",
@@ -15098,7 +15098,6 @@
"xpack.datasetQuality.types.label": "类型",
"xpack.dataUsage.charts.ingestedMax": "已采集的数据",
"xpack.dataUsage.charts.retainedMax": "保留在存储中的数据",
- "xpack.dataUsage.metrics.filter.clearAll": "全部清除",
"xpack.dataUsage.metrics.filter.dataStreams": "数据流",
"xpack.dataUsage.metrics.filter.emptyMessage": "无 {filterName} 可用",
"xpack.dataUsage.metrics.filter.metricTypes": "指标类型",
@@ -27742,8 +27741,8 @@
"xpack.maps.source.esSearch.convertToGeoJsonErrorMsg": "无法将搜索响应转换成 geoJson 功能集合,错误:{errorMsg}",
"xpack.maps.source.esSearch.descendingLabel": "降序",
"xpack.maps.source.esSearch.extentFilterLabel": "在可见地图区域中动态筛留数据",
- "xpack.maps.source.esSearch.geofieldLabel": "地理空间字段",
"xpack.maps.source.esSearch.geoFieldLabel": "地理空间字段",
+ "xpack.maps.source.esSearch.geofieldLabel": "地理空间字段",
"xpack.maps.source.esSearch.geoFieldTypeLabel": "地理空间字段类型",
"xpack.maps.source.esSearch.indexOverOneLengthEditError": "您的数据视图指向多个索引。每个数据视图只允许一个索引。",
"xpack.maps.source.esSearch.indexZeroLengthEditError": "您的数据视图未指向任何索引。",
@@ -37378,8 +37377,8 @@
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.maxAlertsFieldLessThanWarning": "每次规则运行时,Kibana 最多只允许 {maxNumber} 个{maxNumber, plural, other {告警}}。",
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.nameFieldRequiredError": "名称必填。",
"xpack.securitySolution.detectionEngine.createRule.stepAboutrule.noteHelpText": "添加规则调查指南......",
- "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "添加规则设置指南......",
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupHelpText": "提供有关规则先决条件的说明,如所需集成、配置步骤,以及规则正常运行所需的任何其他内容。",
+ "xpack.securitySolution.detectionEngine.createRule.stepAboutrule.setupHelpText": "添加规则设置指南......",
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.setupLabel": "设置指南",
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.tagFieldEmptyError": "标签不得为空",
"xpack.securitySolution.detectionEngine.createRule.stepAboutRule.threatIndicatorPathFieldEmptyError": "指标前缀覆盖不得为空",
@@ -43116,8 +43115,8 @@
"xpack.slo.sloEmbeddable.config.sloSelector.placeholder": "选择 SLO",
"xpack.slo.sloEmbeddable.displayName": "SLO 概览",
"xpack.slo.sloEmbeddable.overview.sloNotFoundText": "SLO 已删除。您可以放心从仪表板中删除小组件。",
- "xpack.slo.sloGridItem.targetFlexItemLabel": "目标 {target}",
"xpack.slo.sLOGridItem.targetFlexItemLabel": "目标 {target}",
+ "xpack.slo.sloGridItem.targetFlexItemLabel": "目标 {target}",
"xpack.slo.sloGroupConfiguration.customFiltersLabel": "定制筛选",
"xpack.slo.sloGroupConfiguration.customFiltersOptional": "可选",
"xpack.slo.sloGroupConfiguration.customFilterText": "定制筛选",
@@ -44589,8 +44588,8 @@
"xpack.stackConnectors.components.casesWebhookxpack.stackConnectors.components.casesWebhook.connectorTypeTitle": "Webhook - 案例管理数据",
"xpack.stackConnectors.components.d3security.bodyCodeEditorAriaLabel": "代码编辑器",
"xpack.stackConnectors.components.d3security.bodyFieldLabel": "正文",
- "xpack.stackConnectors.components.d3security.connectorTypeTitle": "D3 数据",
"xpack.stackConnectors.components.d3Security.connectorTypeTitle": "D3 Security",
+ "xpack.stackConnectors.components.d3security.connectorTypeTitle": "D3 数据",
"xpack.stackConnectors.components.d3security.eventTypeFieldLabel": "事件类型",
"xpack.stackConnectors.components.d3security.invalidActionText": "操作名称无效。",
"xpack.stackConnectors.components.d3security.requiredActionText": "'操作'必填。",
diff --git a/x-pack/test_serverless/api_integration/test_suites/common/data_usage/tests/data_streams.ts b/x-pack/test_serverless/api_integration/test_suites/common/data_usage/tests/data_streams.ts
index b6559c3efc9b6..d26b73f8689c8 100644
--- a/x-pack/test_serverless/api_integration/test_suites/common/data_usage/tests/data_streams.ts
+++ b/x-pack/test_serverless/api_integration/test_suites/common/data_usage/tests/data_streams.ts
@@ -33,7 +33,10 @@ export default function ({ getService }: FtrProviderContext) {
await svlDatastreamsHelpers.deleteDataStream(testDataStreamName);
});
- it('returns created data streams', async () => {
+ // skipped because we filter out data streams with 0 storage size,
+ // and metering api does not pick up indexed data here
+ // TODO: route should potentially not depend solely on metering API
+ it.skip('returns created data streams', async () => {
const res = await supertestAdminWithCookieCredentials
.get(DATA_USAGE_DATA_STREAMS_API_ROUTE)
.set('elastic-api-version', '1');
From 09633698893318d4128237e3e454c24e0e301a83 Mon Sep 17 00:00:00 2001
From: "elastic-renovate-prod[bot]"
<174716857+elastic-renovate-prod[bot]@users.noreply.github.com>
Date: Fri, 22 Nov 2024 17:42:49 -0800
Subject: [PATCH 28/38] Update docker.elastic.co/wolfi/chainguard-base:latest
Docker digest to 55b297d (main) (#201075)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| docker.elastic.co/wolfi/chainguard-base | digest | `32099b9` ->
`55b297d` |
---
### Configuration
📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] If you want to rebase/retry this PR, check
this box
---
This PR has been generated by [Renovate
Bot](https://togithub.com/renovatebot/renovate).
Co-authored-by: elastic-renovate-prod[bot] <174716857+elastic-renovate-prod[bot]@users.noreply.github.com>
---
src/dev/build/tasks/os_packages/docker_generator/run.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/dev/build/tasks/os_packages/docker_generator/run.ts b/src/dev/build/tasks/os_packages/docker_generator/run.ts
index 186360c03e805..8ff44c13ff44f 100644
--- a/src/dev/build/tasks/os_packages/docker_generator/run.ts
+++ b/src/dev/build/tasks/os_packages/docker_generator/run.ts
@@ -51,7 +51,7 @@ export async function runDockerGenerator(
*/
if (flags.baseImage === 'wolfi')
baseImageName =
- 'docker.elastic.co/wolfi/chainguard-base:latest@sha256:32099b99697d9da842c1ccacdbef1beee05a68cddb817e858d7656df45ed4c93';
+ 'docker.elastic.co/wolfi/chainguard-base:latest@sha256:55b297da5151d2a2997e8ab9729fe1304e4869389d7090ab7031cc29530f69f8';
let imageFlavor = '';
if (flags.baseImage === 'ubi') imageFlavor += `-ubi`;
From 7dfda396c07899432c5ffa82419e933e2a44205d Mon Sep 17 00:00:00 2001
From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Date: Sat, 23 Nov 2024 18:45:10 +1100
Subject: [PATCH 29/38] [api-docs] 2024-11-23 Daily api_docs build (#201490)
Generated by
https://buildkite.com/elastic/kibana-api-docs-daily/builds/900
---
api_docs/actions.mdx | 2 +-
api_docs/advanced_settings.mdx | 2 +-
.../ai_assistant_management_selection.mdx | 2 +-
api_docs/aiops.mdx | 2 +-
api_docs/alerting.mdx | 2 +-
api_docs/apm.mdx | 2 +-
api_docs/apm_data_access.mdx | 2 +-
api_docs/banners.mdx | 2 +-
api_docs/bfetch.mdx | 2 +-
api_docs/canvas.mdx | 2 +-
api_docs/cases.mdx | 2 +-
api_docs/charts.mdx | 2 +-
api_docs/cloud.mdx | 2 +-
api_docs/cloud_data_migration.mdx | 2 +-
api_docs/cloud_defend.mdx | 2 +-
api_docs/cloud_security_posture.mdx | 2 +-
api_docs/console.mdx | 2 +-
api_docs/content_management.mdx | 2 +-
api_docs/controls.mdx | 2 +-
api_docs/custom_integrations.mdx | 2 +-
api_docs/dashboard.mdx | 2 +-
api_docs/dashboard_enhanced.mdx | 2 +-
api_docs/data.mdx | 2 +-
api_docs/data_quality.mdx | 2 +-
api_docs/data_query.mdx | 2 +-
api_docs/data_search.mdx | 2 +-
api_docs/data_usage.devdocs.json | 22 +-
api_docs/data_usage.mdx | 4 +-
api_docs/data_view_editor.mdx | 2 +-
api_docs/data_view_field_editor.mdx | 2 +-
api_docs/data_view_management.mdx | 2 +-
api_docs/data_views.devdocs.json | 4 -
api_docs/data_views.mdx | 2 +-
api_docs/data_visualizer.mdx | 2 +-
api_docs/dataset_quality.mdx | 2 +-
api_docs/deprecations_by_api.mdx | 2 +-
api_docs/deprecations_by_plugin.mdx | 4 +-
api_docs/deprecations_by_team.mdx | 2 +-
api_docs/dev_tools.mdx | 2 +-
api_docs/discover.mdx | 2 +-
api_docs/discover_enhanced.mdx | 2 +-
api_docs/discover_shared.mdx | 2 +-
api_docs/ecs_data_quality_dashboard.mdx | 2 +-
api_docs/elastic_assistant.mdx | 2 +-
api_docs/embeddable.mdx | 2 +-
api_docs/embeddable_enhanced.mdx | 2 +-
api_docs/encrypted_saved_objects.mdx | 2 +-
api_docs/enterprise_search.mdx | 2 +-
api_docs/entities_data_access.mdx | 2 +-
api_docs/entity_manager.devdocs.json | 1193 ++++++++++++++++-
api_docs/entity_manager.mdx | 4 +-
api_docs/es_ui_shared.mdx | 2 +-
api_docs/esql.mdx | 2 +-
api_docs/esql_data_grid.mdx | 2 +-
api_docs/event_annotation.mdx | 2 +-
api_docs/event_annotation_listing.mdx | 2 +-
api_docs/event_log.mdx | 2 +-
api_docs/exploratory_view.mdx | 2 +-
api_docs/expression_error.mdx | 2 +-
api_docs/expression_gauge.mdx | 2 +-
api_docs/expression_heatmap.mdx | 2 +-
api_docs/expression_image.mdx | 2 +-
api_docs/expression_legacy_metric_vis.mdx | 2 +-
api_docs/expression_metric.mdx | 2 +-
api_docs/expression_metric_vis.mdx | 2 +-
api_docs/expression_partition_vis.mdx | 2 +-
api_docs/expression_repeat_image.mdx | 2 +-
api_docs/expression_reveal_image.mdx | 2 +-
api_docs/expression_shape.mdx | 2 +-
api_docs/expression_tagcloud.mdx | 2 +-
api_docs/expression_x_y.mdx | 2 +-
api_docs/expressions.mdx | 2 +-
api_docs/features.mdx | 2 +-
api_docs/field_formats.mdx | 2 +-
api_docs/fields_metadata.mdx | 2 +-
api_docs/file_upload.mdx | 2 +-
api_docs/files.mdx | 2 +-
api_docs/files_management.mdx | 2 +-
api_docs/fleet.mdx | 2 +-
api_docs/global_search.mdx | 2 +-
api_docs/guided_onboarding.mdx | 2 +-
api_docs/home.mdx | 2 +-
api_docs/image_embeddable.mdx | 2 +-
api_docs/index_lifecycle_management.mdx | 2 +-
api_docs/index_management.mdx | 2 +-
api_docs/inference.mdx | 2 +-
api_docs/infra.mdx | 2 +-
api_docs/ingest_pipelines.mdx | 2 +-
api_docs/inspector.mdx | 2 +-
api_docs/integration_assistant.mdx | 2 +-
api_docs/interactive_setup.mdx | 2 +-
api_docs/inventory.mdx | 2 +-
api_docs/investigate.mdx | 2 +-
api_docs/investigate_app.mdx | 2 +-
api_docs/kbn_actions_types.mdx | 2 +-
api_docs/kbn_ai_assistant.mdx | 2 +-
api_docs/kbn_ai_assistant_common.mdx | 2 +-
api_docs/kbn_aiops_components.mdx | 2 +-
api_docs/kbn_aiops_log_pattern_analysis.mdx | 2 +-
api_docs/kbn_aiops_log_rate_analysis.mdx | 2 +-
.../kbn_alerting_api_integration_helpers.mdx | 2 +-
api_docs/kbn_alerting_comparators.mdx | 2 +-
api_docs/kbn_alerting_state_types.mdx | 2 +-
api_docs/kbn_alerting_types.mdx | 2 +-
api_docs/kbn_alerts_as_data_utils.mdx | 2 +-
api_docs/kbn_alerts_grouping.mdx | 2 +-
api_docs/kbn_alerts_ui_shared.mdx | 2 +-
api_docs/kbn_analytics.mdx | 2 +-
api_docs/kbn_analytics_collection_utils.mdx | 2 +-
api_docs/kbn_apm_config_loader.mdx | 2 +-
api_docs/kbn_apm_data_view.mdx | 2 +-
api_docs/kbn_apm_synthtrace.mdx | 2 +-
api_docs/kbn_apm_synthtrace_client.mdx | 2 +-
api_docs/kbn_apm_types.mdx | 2 +-
api_docs/kbn_apm_utils.mdx | 2 +-
api_docs/kbn_avc_banner.mdx | 2 +-
api_docs/kbn_axe_config.mdx | 2 +-
api_docs/kbn_bfetch_error.mdx | 2 +-
api_docs/kbn_calculate_auto.mdx | 2 +-
.../kbn_calculate_width_from_char_count.mdx | 2 +-
api_docs/kbn_cases_components.mdx | 2 +-
api_docs/kbn_cbor.mdx | 2 +-
api_docs/kbn_cell_actions.mdx | 2 +-
api_docs/kbn_chart_expressions_common.mdx | 2 +-
api_docs/kbn_chart_icons.mdx | 2 +-
api_docs/kbn_ci_stats_core.mdx | 2 +-
api_docs/kbn_ci_stats_performance_metrics.mdx | 2 +-
api_docs/kbn_ci_stats_reporter.mdx | 2 +-
api_docs/kbn_cli_dev_mode.mdx | 2 +-
api_docs/kbn_cloud_security_posture.mdx | 2 +-
.../kbn_cloud_security_posture_common.mdx | 2 +-
api_docs/kbn_cloud_security_posture_graph.mdx | 2 +-
api_docs/kbn_code_editor.mdx | 2 +-
api_docs/kbn_code_editor_mock.mdx | 2 +-
api_docs/kbn_code_owners.mdx | 2 +-
api_docs/kbn_coloring.mdx | 2 +-
api_docs/kbn_config.mdx | 2 +-
api_docs/kbn_config_mocks.mdx | 2 +-
api_docs/kbn_config_schema.mdx | 2 +-
.../kbn_content_management_content_editor.mdx | 2 +-
...ent_management_content_insights_public.mdx | 2 +-
...ent_management_content_insights_server.mdx | 2 +-
...bn_content_management_favorites_common.mdx | 2 +-
...bn_content_management_favorites_public.mdx | 2 +-
...bn_content_management_favorites_server.mdx | 2 +-
...tent_management_tabbed_table_list_view.mdx | 2 +-
...kbn_content_management_table_list_view.mdx | 2 +-
...tent_management_table_list_view_common.mdx | 2 +-
...ntent_management_table_list_view_table.mdx | 2 +-
.../kbn_content_management_user_profiles.mdx | 2 +-
api_docs/kbn_content_management_utils.mdx | 2 +-
api_docs/kbn_core_analytics_browser.mdx | 2 +-
.../kbn_core_analytics_browser_internal.mdx | 2 +-
api_docs/kbn_core_analytics_browser_mocks.mdx | 2 +-
api_docs/kbn_core_analytics_server.mdx | 2 +-
.../kbn_core_analytics_server_internal.mdx | 2 +-
api_docs/kbn_core_analytics_server_mocks.mdx | 2 +-
api_docs/kbn_core_application_browser.mdx | 2 +-
.../kbn_core_application_browser_internal.mdx | 2 +-
.../kbn_core_application_browser_mocks.mdx | 2 +-
api_docs/kbn_core_application_common.mdx | 2 +-
api_docs/kbn_core_apps_browser_internal.mdx | 2 +-
api_docs/kbn_core_apps_browser_mocks.mdx | 2 +-
api_docs/kbn_core_apps_server_internal.mdx | 2 +-
api_docs/kbn_core_base_browser_mocks.mdx | 2 +-
api_docs/kbn_core_base_common.mdx | 2 +-
api_docs/kbn_core_base_server_internal.mdx | 2 +-
api_docs/kbn_core_base_server_mocks.mdx | 2 +-
.../kbn_core_capabilities_browser_mocks.mdx | 2 +-
api_docs/kbn_core_capabilities_common.mdx | 2 +-
api_docs/kbn_core_capabilities_server.mdx | 2 +-
.../kbn_core_capabilities_server_mocks.mdx | 2 +-
api_docs/kbn_core_chrome_browser.devdocs.json | 2 +-
api_docs/kbn_core_chrome_browser.mdx | 2 +-
api_docs/kbn_core_chrome_browser_mocks.mdx | 2 +-
api_docs/kbn_core_config_server_internal.mdx | 2 +-
api_docs/kbn_core_custom_branding_browser.mdx | 2 +-
..._core_custom_branding_browser_internal.mdx | 2 +-
...kbn_core_custom_branding_browser_mocks.mdx | 2 +-
api_docs/kbn_core_custom_branding_common.mdx | 2 +-
api_docs/kbn_core_custom_branding_server.mdx | 2 +-
...n_core_custom_branding_server_internal.mdx | 2 +-
.../kbn_core_custom_branding_server_mocks.mdx | 2 +-
api_docs/kbn_core_deprecations_browser.mdx | 2 +-
...kbn_core_deprecations_browser_internal.mdx | 2 +-
.../kbn_core_deprecations_browser_mocks.mdx | 2 +-
api_docs/kbn_core_deprecations_common.mdx | 2 +-
api_docs/kbn_core_deprecations_server.mdx | 2 +-
.../kbn_core_deprecations_server_internal.mdx | 2 +-
.../kbn_core_deprecations_server_mocks.mdx | 2 +-
api_docs/kbn_core_doc_links_browser.mdx | 2 +-
api_docs/kbn_core_doc_links_browser_mocks.mdx | 2 +-
api_docs/kbn_core_doc_links_server.mdx | 2 +-
api_docs/kbn_core_doc_links_server_mocks.mdx | 2 +-
...e_elasticsearch_client_server_internal.mdx | 2 +-
...core_elasticsearch_client_server_mocks.mdx | 2 +-
api_docs/kbn_core_elasticsearch_server.mdx | 2 +-
...kbn_core_elasticsearch_server_internal.mdx | 2 +-
.../kbn_core_elasticsearch_server_mocks.mdx | 2 +-
.../kbn_core_environment_server_internal.mdx | 2 +-
.../kbn_core_environment_server_mocks.mdx | 2 +-
.../kbn_core_execution_context_browser.mdx | 2 +-
...ore_execution_context_browser_internal.mdx | 2 +-
...n_core_execution_context_browser_mocks.mdx | 2 +-
.../kbn_core_execution_context_common.mdx | 2 +-
.../kbn_core_execution_context_server.mdx | 2 +-
...core_execution_context_server_internal.mdx | 2 +-
...bn_core_execution_context_server_mocks.mdx | 2 +-
api_docs/kbn_core_fatal_errors_browser.mdx | 2 +-
.../kbn_core_fatal_errors_browser_mocks.mdx | 2 +-
api_docs/kbn_core_feature_flags_browser.mdx | 2 +-
...bn_core_feature_flags_browser_internal.mdx | 2 +-
.../kbn_core_feature_flags_browser_mocks.mdx | 2 +-
api_docs/kbn_core_feature_flags_server.mdx | 2 +-
...kbn_core_feature_flags_server_internal.mdx | 2 +-
.../kbn_core_feature_flags_server_mocks.mdx | 2 +-
api_docs/kbn_core_http_browser.mdx | 2 +-
api_docs/kbn_core_http_browser_internal.mdx | 2 +-
api_docs/kbn_core_http_browser_mocks.mdx | 2 +-
api_docs/kbn_core_http_common.mdx | 2 +-
.../kbn_core_http_context_server_mocks.mdx | 2 +-
...re_http_request_handler_context_server.mdx | 2 +-
api_docs/kbn_core_http_resources_server.mdx | 2 +-
...bn_core_http_resources_server_internal.mdx | 2 +-
.../kbn_core_http_resources_server_mocks.mdx | 2 +-
...e_http_router_server_internal.devdocs.json | 10 +-
.../kbn_core_http_router_server_internal.mdx | 2 +-
...core_http_router_server_mocks.devdocs.json | 2 +-
.../kbn_core_http_router_server_mocks.mdx | 2 +-
api_docs/kbn_core_http_server.devdocs.json | 69 +-
api_docs/kbn_core_http_server.mdx | 4 +-
api_docs/kbn_core_http_server_internal.mdx | 2 +-
api_docs/kbn_core_http_server_mocks.mdx | 2 +-
.../kbn_core_http_server_utils.devdocs.json | 186 +++
api_docs/kbn_core_http_server_utils.mdx | 30 +
api_docs/kbn_core_i18n_browser.mdx | 2 +-
api_docs/kbn_core_i18n_browser_mocks.mdx | 2 +-
api_docs/kbn_core_i18n_server.mdx | 2 +-
api_docs/kbn_core_i18n_server_internal.mdx | 2 +-
api_docs/kbn_core_i18n_server_mocks.mdx | 2 +-
...n_core_injected_metadata_browser_mocks.mdx | 2 +-
...kbn_core_integrations_browser_internal.mdx | 2 +-
.../kbn_core_integrations_browser_mocks.mdx | 2 +-
api_docs/kbn_core_lifecycle_browser.mdx | 2 +-
api_docs/kbn_core_lifecycle_browser_mocks.mdx | 2 +-
api_docs/kbn_core_lifecycle_server.mdx | 2 +-
api_docs/kbn_core_lifecycle_server_mocks.mdx | 2 +-
api_docs/kbn_core_logging_browser_mocks.mdx | 2 +-
api_docs/kbn_core_logging_common_internal.mdx | 2 +-
api_docs/kbn_core_logging_server.mdx | 2 +-
api_docs/kbn_core_logging_server_internal.mdx | 2 +-
api_docs/kbn_core_logging_server_mocks.mdx | 2 +-
...ore_metrics_collectors_server_internal.mdx | 2 +-
...n_core_metrics_collectors_server_mocks.mdx | 2 +-
api_docs/kbn_core_metrics_server.mdx | 2 +-
api_docs/kbn_core_metrics_server_internal.mdx | 2 +-
api_docs/kbn_core_metrics_server_mocks.mdx | 2 +-
api_docs/kbn_core_mount_utils_browser.mdx | 2 +-
api_docs/kbn_core_node_server.mdx | 2 +-
api_docs/kbn_core_node_server_internal.mdx | 2 +-
api_docs/kbn_core_node_server_mocks.mdx | 2 +-
api_docs/kbn_core_notifications_browser.mdx | 2 +-
...bn_core_notifications_browser_internal.mdx | 2 +-
.../kbn_core_notifications_browser_mocks.mdx | 2 +-
api_docs/kbn_core_overlays_browser.mdx | 2 +-
.../kbn_core_overlays_browser_internal.mdx | 2 +-
api_docs/kbn_core_overlays_browser_mocks.mdx | 2 +-
api_docs/kbn_core_plugins_browser.mdx | 2 +-
api_docs/kbn_core_plugins_browser_mocks.mdx | 2 +-
.../kbn_core_plugins_contracts_browser.mdx | 2 +-
.../kbn_core_plugins_contracts_server.mdx | 2 +-
api_docs/kbn_core_plugins_server.mdx | 2 +-
api_docs/kbn_core_plugins_server_mocks.mdx | 2 +-
api_docs/kbn_core_preboot_server.mdx | 2 +-
api_docs/kbn_core_preboot_server_mocks.mdx | 2 +-
api_docs/kbn_core_rendering_browser.mdx | 2 +-
api_docs/kbn_core_rendering_browser_mocks.mdx | 2 +-
.../kbn_core_rendering_server_internal.mdx | 2 +-
api_docs/kbn_core_rendering_server_mocks.mdx | 2 +-
api_docs/kbn_core_root_server_internal.mdx | 2 +-
.../kbn_core_saved_objects_api_browser.mdx | 2 +-
.../kbn_core_saved_objects_api_server.mdx | 2 +-
...bn_core_saved_objects_api_server_mocks.mdx | 2 +-
...ore_saved_objects_base_server_internal.mdx | 2 +-
...n_core_saved_objects_base_server_mocks.mdx | 2 +-
api_docs/kbn_core_saved_objects_browser.mdx | 2 +-
...bn_core_saved_objects_browser_internal.mdx | 2 +-
.../kbn_core_saved_objects_browser_mocks.mdx | 2 +-
api_docs/kbn_core_saved_objects_common.mdx | 2 +-
..._objects_import_export_server_internal.mdx | 2 +-
...ved_objects_import_export_server_mocks.mdx | 2 +-
...aved_objects_migration_server_internal.mdx | 2 +-
...e_saved_objects_migration_server_mocks.mdx | 2 +-
api_docs/kbn_core_saved_objects_server.mdx | 2 +-
...kbn_core_saved_objects_server_internal.mdx | 2 +-
.../kbn_core_saved_objects_server_mocks.mdx | 2 +-
.../kbn_core_saved_objects_utils_server.mdx | 2 +-
api_docs/kbn_core_security_browser.mdx | 2 +-
.../kbn_core_security_browser_internal.mdx | 2 +-
api_docs/kbn_core_security_browser_mocks.mdx | 2 +-
api_docs/kbn_core_security_common.mdx | 2 +-
api_docs/kbn_core_security_server.mdx | 2 +-
.../kbn_core_security_server_internal.mdx | 2 +-
api_docs/kbn_core_security_server_mocks.mdx | 2 +-
api_docs/kbn_core_status_common.mdx | 2 +-
api_docs/kbn_core_status_server.mdx | 2 +-
api_docs/kbn_core_status_server_internal.mdx | 2 +-
api_docs/kbn_core_status_server_mocks.mdx | 2 +-
...core_test_helpers_deprecations_getters.mdx | 2 +-
...n_core_test_helpers_http_setup_browser.mdx | 2 +-
api_docs/kbn_core_test_helpers_kbn_server.mdx | 2 +-
.../kbn_core_test_helpers_model_versions.mdx | 2 +-
...n_core_test_helpers_so_type_serializer.mdx | 2 +-
api_docs/kbn_core_test_helpers_test_utils.mdx | 2 +-
api_docs/kbn_core_theme_browser.mdx | 2 +-
api_docs/kbn_core_theme_browser_mocks.mdx | 2 +-
api_docs/kbn_core_ui_settings_browser.mdx | 2 +-
.../kbn_core_ui_settings_browser_internal.mdx | 2 +-
.../kbn_core_ui_settings_browser_mocks.mdx | 2 +-
api_docs/kbn_core_ui_settings_common.mdx | 2 +-
api_docs/kbn_core_ui_settings_server.mdx | 2 +-
.../kbn_core_ui_settings_server_internal.mdx | 2 +-
.../kbn_core_ui_settings_server_mocks.mdx | 2 +-
api_docs/kbn_core_usage_data_server.mdx | 2 +-
.../kbn_core_usage_data_server_internal.mdx | 2 +-
api_docs/kbn_core_usage_data_server_mocks.mdx | 2 +-
api_docs/kbn_core_user_profile_browser.mdx | 2 +-
...kbn_core_user_profile_browser_internal.mdx | 2 +-
.../kbn_core_user_profile_browser_mocks.mdx | 2 +-
api_docs/kbn_core_user_profile_common.mdx | 2 +-
api_docs/kbn_core_user_profile_server.mdx | 2 +-
.../kbn_core_user_profile_server_internal.mdx | 2 +-
.../kbn_core_user_profile_server_mocks.mdx | 2 +-
api_docs/kbn_core_user_settings_server.mdx | 2 +-
.../kbn_core_user_settings_server_mocks.mdx | 2 +-
api_docs/kbn_crypto.mdx | 2 +-
api_docs/kbn_crypto_browser.mdx | 2 +-
api_docs/kbn_custom_icons.mdx | 2 +-
api_docs/kbn_custom_integrations.mdx | 2 +-
api_docs/kbn_cypress_config.mdx | 2 +-
api_docs/kbn_data_forge.mdx | 2 +-
api_docs/kbn_data_service.mdx | 2 +-
api_docs/kbn_data_stream_adapter.mdx | 2 +-
api_docs/kbn_data_view_utils.mdx | 2 +-
api_docs/kbn_datemath.mdx | 2 +-
api_docs/kbn_deeplinks_analytics.mdx | 2 +-
api_docs/kbn_deeplinks_devtools.mdx | 2 +-
api_docs/kbn_deeplinks_fleet.mdx | 2 +-
api_docs/kbn_deeplinks_management.mdx | 2 +-
api_docs/kbn_deeplinks_ml.mdx | 2 +-
api_docs/kbn_deeplinks_observability.mdx | 2 +-
api_docs/kbn_deeplinks_search.mdx | 2 +-
api_docs/kbn_deeplinks_security.devdocs.json | 4 +-
api_docs/kbn_deeplinks_security.mdx | 2 +-
api_docs/kbn_deeplinks_shared.mdx | 2 +-
api_docs/kbn_default_nav_analytics.mdx | 2 +-
api_docs/kbn_default_nav_devtools.mdx | 2 +-
api_docs/kbn_default_nav_management.mdx | 2 +-
api_docs/kbn_default_nav_ml.mdx | 2 +-
api_docs/kbn_dev_cli_errors.mdx | 2 +-
api_docs/kbn_dev_cli_runner.mdx | 2 +-
api_docs/kbn_dev_proc_runner.mdx | 2 +-
api_docs/kbn_dev_utils.mdx | 2 +-
.../kbn_discover_contextual_components.mdx | 2 +-
api_docs/kbn_discover_utils.mdx | 2 +-
api_docs/kbn_doc_links.devdocs.json | 14 +
api_docs/kbn_doc_links.mdx | 4 +-
api_docs/kbn_docs_utils.mdx | 2 +-
api_docs/kbn_dom_drag_drop.mdx | 2 +-
api_docs/kbn_ebt_tools.mdx | 2 +-
api_docs/kbn_ecs_data_quality_dashboard.mdx | 2 +-
api_docs/kbn_elastic_agent_utils.mdx | 2 +-
api_docs/kbn_elastic_assistant.mdx | 2 +-
api_docs/kbn_elastic_assistant_common.mdx | 2 +-
api_docs/kbn_entities_schema.devdocs.json | 61 +
api_docs/kbn_entities_schema.mdx | 4 +-
api_docs/kbn_es.mdx | 2 +-
api_docs/kbn_es_archiver.mdx | 2 +-
api_docs/kbn_es_errors.mdx | 2 +-
api_docs/kbn_es_query.mdx | 2 +-
api_docs/kbn_es_types.mdx | 2 +-
api_docs/kbn_eslint_plugin_imports.mdx | 2 +-
api_docs/kbn_esql_ast.mdx | 2 +-
api_docs/kbn_esql_editor.mdx | 2 +-
api_docs/kbn_esql_utils.mdx | 2 +-
api_docs/kbn_esql_validation_autocomplete.mdx | 2 +-
api_docs/kbn_event_annotation_common.mdx | 2 +-
api_docs/kbn_event_annotation_components.mdx | 2 +-
api_docs/kbn_expandable_flyout.mdx | 2 +-
api_docs/kbn_field_types.mdx | 2 +-
api_docs/kbn_field_utils.mdx | 2 +-
api_docs/kbn_find_used_node_modules.mdx | 2 +-
api_docs/kbn_formatters.mdx | 2 +-
.../kbn_ftr_common_functional_services.mdx | 2 +-
.../kbn_ftr_common_functional_ui_services.mdx | 2 +-
api_docs/kbn_generate.mdx | 2 +-
api_docs/kbn_generate_console_definitions.mdx | 2 +-
api_docs/kbn_generate_csv.devdocs.json | 4 +-
api_docs/kbn_generate_csv.mdx | 2 +-
api_docs/kbn_grid_layout.mdx | 2 +-
api_docs/kbn_grouping.mdx | 2 +-
api_docs/kbn_guided_onboarding.mdx | 2 +-
api_docs/kbn_handlebars.mdx | 2 +-
api_docs/kbn_hapi_mocks.mdx | 2 +-
api_docs/kbn_health_gateway_server.mdx | 2 +-
api_docs/kbn_home_sample_data_card.mdx | 2 +-
api_docs/kbn_home_sample_data_tab.mdx | 2 +-
api_docs/kbn_i18n.mdx | 2 +-
api_docs/kbn_i18n_react.mdx | 2 +-
api_docs/kbn_import_resolver.mdx | 2 +-
api_docs/kbn_index_adapter.mdx | 2 +-
...dex_lifecycle_management_common_shared.mdx | 2 +-
.../kbn_index_management_shared_types.mdx | 2 +-
api_docs/kbn_inference_common.mdx | 2 +-
api_docs/kbn_inference_integration_flyout.mdx | 2 +-
api_docs/kbn_infra_forge.mdx | 2 +-
api_docs/kbn_interpreter.mdx | 2 +-
api_docs/kbn_investigation_shared.mdx | 2 +-
api_docs/kbn_io_ts_utils.mdx | 2 +-
api_docs/kbn_ipynb.mdx | 2 +-
api_docs/kbn_item_buffer.mdx | 2 +-
api_docs/kbn_jest_serializers.mdx | 2 +-
api_docs/kbn_journeys.mdx | 2 +-
api_docs/kbn_json_ast.mdx | 2 +-
api_docs/kbn_json_schemas.mdx | 2 +-
api_docs/kbn_kibana_manifest_schema.mdx | 2 +-
api_docs/kbn_language_documentation.mdx | 2 +-
api_docs/kbn_lens_embeddable_utils.mdx | 2 +-
api_docs/kbn_lens_formula_docs.mdx | 2 +-
api_docs/kbn_logging.mdx | 2 +-
api_docs/kbn_logging_mocks.mdx | 2 +-
api_docs/kbn_managed_content_badge.mdx | 2 +-
api_docs/kbn_managed_vscode_config.mdx | 2 +-
api_docs/kbn_management_cards_navigation.mdx | 2 +-
.../kbn_management_settings_application.mdx | 2 +-
...ent_settings_components_field_category.mdx | 2 +-
...gement_settings_components_field_input.mdx | 2 +-
...nagement_settings_components_field_row.mdx | 2 +-
...bn_management_settings_components_form.mdx | 2 +-
...n_management_settings_field_definition.mdx | 2 +-
api_docs/kbn_management_settings_ids.mdx | 4 +-
...n_management_settings_section_registry.mdx | 4 +-
api_docs/kbn_management_settings_types.mdx | 2 +-
.../kbn_management_settings_utilities.mdx | 2 +-
api_docs/kbn_management_storybook_config.mdx | 2 +-
api_docs/kbn_manifest.mdx | 2 +-
api_docs/kbn_mapbox_gl.mdx | 2 +-
api_docs/kbn_maps_vector_tile_utils.mdx | 2 +-
api_docs/kbn_ml_agg_utils.mdx | 2 +-
api_docs/kbn_ml_anomaly_utils.mdx | 2 +-
api_docs/kbn_ml_cancellable_search.mdx | 2 +-
api_docs/kbn_ml_category_validator.mdx | 2 +-
api_docs/kbn_ml_chi2test.mdx | 2 +-
.../kbn_ml_data_frame_analytics_utils.mdx | 2 +-
api_docs/kbn_ml_data_grid.mdx | 2 +-
api_docs/kbn_ml_date_picker.mdx | 2 +-
api_docs/kbn_ml_date_utils.mdx | 2 +-
api_docs/kbn_ml_error_utils.mdx | 2 +-
api_docs/kbn_ml_field_stats_flyout.mdx | 2 +-
api_docs/kbn_ml_in_memory_table.mdx | 2 +-
api_docs/kbn_ml_is_defined.mdx | 2 +-
api_docs/kbn_ml_is_populated_object.mdx | 2 +-
api_docs/kbn_ml_kibana_theme.mdx | 2 +-
api_docs/kbn_ml_local_storage.mdx | 2 +-
api_docs/kbn_ml_nested_property.mdx | 2 +-
api_docs/kbn_ml_number_utils.mdx | 2 +-
api_docs/kbn_ml_parse_interval.mdx | 2 +-
api_docs/kbn_ml_query_utils.mdx | 2 +-
api_docs/kbn_ml_random_sampler_utils.mdx | 2 +-
api_docs/kbn_ml_route_utils.mdx | 2 +-
api_docs/kbn_ml_runtime_field_utils.mdx | 2 +-
api_docs/kbn_ml_string_hash.mdx | 2 +-
api_docs/kbn_ml_time_buckets.mdx | 2 +-
api_docs/kbn_ml_trained_models_utils.mdx | 2 +-
api_docs/kbn_ml_ui_actions.mdx | 2 +-
api_docs/kbn_ml_url_state.mdx | 2 +-
api_docs/kbn_ml_validators.mdx | 2 +-
api_docs/kbn_mock_idp_utils.mdx | 2 +-
api_docs/kbn_monaco.mdx | 2 +-
api_docs/kbn_object_versioning.mdx | 2 +-
api_docs/kbn_object_versioning_utils.mdx | 2 +-
api_docs/kbn_observability_alert_details.mdx | 2 +-
.../kbn_observability_alerting_rule_utils.mdx | 2 +-
.../kbn_observability_alerting_test_data.mdx | 2 +-
...ility_get_padded_alert_time_range_util.mdx | 2 +-
api_docs/kbn_observability_logs_overview.mdx | 2 +-
...kbn_observability_synthetics_test_data.mdx | 2 +-
api_docs/kbn_openapi_bundler.mdx | 2 +-
api_docs/kbn_openapi_generator.mdx | 2 +-
api_docs/kbn_optimizer.mdx | 2 +-
api_docs/kbn_optimizer_webpack_helpers.mdx | 2 +-
api_docs/kbn_osquery_io_ts_types.mdx | 2 +-
api_docs/kbn_panel_loader.mdx | 2 +-
..._performance_testing_dataset_extractor.mdx | 2 +-
api_docs/kbn_plugin_check.mdx | 2 +-
api_docs/kbn_plugin_generator.mdx | 2 +-
api_docs/kbn_plugin_helpers.mdx | 2 +-
api_docs/kbn_presentation_containers.mdx | 2 +-
api_docs/kbn_presentation_publishing.mdx | 2 +-
api_docs/kbn_product_doc_artifact_builder.mdx | 2 +-
api_docs/kbn_product_doc_common.mdx | 2 +-
api_docs/kbn_profiling_utils.mdx | 2 +-
api_docs/kbn_random_sampling.mdx | 2 +-
api_docs/kbn_react_field.mdx | 2 +-
api_docs/kbn_react_hooks.mdx | 2 +-
api_docs/kbn_react_kibana_context_common.mdx | 2 +-
api_docs/kbn_react_kibana_context_render.mdx | 2 +-
api_docs/kbn_react_kibana_context_root.mdx | 2 +-
api_docs/kbn_react_kibana_context_styled.mdx | 2 +-
api_docs/kbn_react_kibana_context_theme.mdx | 2 +-
api_docs/kbn_react_kibana_mount.mdx | 2 +-
api_docs/kbn_recently_accessed.mdx | 2 +-
api_docs/kbn_repo_file_maps.mdx | 2 +-
api_docs/kbn_repo_linter.mdx | 2 +-
api_docs/kbn_repo_path.mdx | 2 +-
.../kbn_repo_source_classifier.devdocs.json | 136 +-
api_docs/kbn_repo_source_classifier.mdx | 7 +-
api_docs/kbn_reporting_common.mdx | 2 +-
api_docs/kbn_reporting_csv_share_panel.mdx | 2 +-
...bn_reporting_export_types_csv.devdocs.json | 8 +-
api_docs/kbn_reporting_export_types_csv.mdx | 2 +-
.../kbn_reporting_export_types_csv_common.mdx | 2 +-
...bn_reporting_export_types_pdf.devdocs.json | 8 +-
api_docs/kbn_reporting_export_types_pdf.mdx | 2 +-
.../kbn_reporting_export_types_pdf_common.mdx | 2 +-
...bn_reporting_export_types_png.devdocs.json | 4 +-
api_docs/kbn_reporting_export_types_png.mdx | 2 +-
.../kbn_reporting_export_types_png_common.mdx | 2 +-
.../kbn_reporting_mocks_server.devdocs.json | 6 +-
api_docs/kbn_reporting_mocks_server.mdx | 2 +-
api_docs/kbn_reporting_public.mdx | 2 +-
api_docs/kbn_reporting_server.devdocs.json | 12 +-
api_docs/kbn_reporting_server.mdx | 2 +-
api_docs/kbn_resizable_layout.mdx | 2 +-
.../kbn_response_ops_feature_flag_service.mdx | 2 +-
api_docs/kbn_response_ops_rule_params.mdx | 2 +-
api_docs/kbn_rison.mdx | 2 +-
api_docs/kbn_rollup.mdx | 2 +-
api_docs/kbn_router_to_openapispec.mdx | 2 +-
api_docs/kbn_router_utils.mdx | 2 +-
api_docs/kbn_rrule.mdx | 2 +-
api_docs/kbn_rule_data_utils.mdx | 2 +-
api_docs/kbn_saved_objects_settings.mdx | 2 +-
api_docs/kbn_screenshotting_server.mdx | 2 +-
api_docs/kbn_search_api_keys_components.mdx | 2 +-
api_docs/kbn_search_api_keys_server.mdx | 2 +-
api_docs/kbn_search_api_panels.mdx | 2 +-
api_docs/kbn_search_connectors.mdx | 2 +-
api_docs/kbn_search_errors.mdx | 2 +-
api_docs/kbn_search_index_documents.mdx | 2 +-
api_docs/kbn_search_response_warnings.mdx | 2 +-
api_docs/kbn_search_shared_ui.mdx | 2 +-
api_docs/kbn_search_types.mdx | 2 +-
api_docs/kbn_security_api_key_management.mdx | 2 +-
api_docs/kbn_security_authorization_core.mdx | 2 +-
...kbn_security_authorization_core_common.mdx | 2 +-
api_docs/kbn_security_form_components.mdx | 2 +-
api_docs/kbn_security_hardening.mdx | 2 +-
api_docs/kbn_security_plugin_types_common.mdx | 2 +-
api_docs/kbn_security_plugin_types_public.mdx | 2 +-
api_docs/kbn_security_plugin_types_server.mdx | 2 +-
.../kbn_security_role_management_model.mdx | 2 +-
...kbn_security_solution_distribution_bar.mdx | 2 +-
api_docs/kbn_security_solution_features.mdx | 2 +-
api_docs/kbn_security_solution_navigation.mdx | 2 +-
api_docs/kbn_security_solution_side_nav.mdx | 2 +-
...kbn_security_solution_storybook_config.mdx | 2 +-
api_docs/kbn_security_ui_components.mdx | 2 +-
.../kbn_securitysolution_autocomplete.mdx | 2 +-
api_docs/kbn_securitysolution_data_table.mdx | 2 +-
api_docs/kbn_securitysolution_ecs.mdx | 2 +-
api_docs/kbn_securitysolution_es_utils.mdx | 2 +-
...ritysolution_exception_list_components.mdx | 2 +-
api_docs/kbn_securitysolution_hook_utils.mdx | 2 +-
..._securitysolution_io_ts_alerting_types.mdx | 2 +-
.../kbn_securitysolution_io_ts_list_types.mdx | 2 +-
api_docs/kbn_securitysolution_io_ts_types.mdx | 2 +-
api_docs/kbn_securitysolution_io_ts_utils.mdx | 2 +-
api_docs/kbn_securitysolution_list_api.mdx | 2 +-
.../kbn_securitysolution_list_constants.mdx | 2 +-
api_docs/kbn_securitysolution_list_hooks.mdx | 2 +-
api_docs/kbn_securitysolution_list_utils.mdx | 2 +-
api_docs/kbn_securitysolution_rules.mdx | 2 +-
api_docs/kbn_securitysolution_t_grid.mdx | 2 +-
.../kbn_securitysolution_utils.devdocs.json | 54 +
api_docs/kbn_securitysolution_utils.mdx | 4 +-
api_docs/kbn_server_http_tools.mdx | 2 +-
.../kbn_server_route_repository.devdocs.json | 13 +-
api_docs/kbn_server_route_repository.mdx | 2 +-
.../kbn_server_route_repository_client.mdx | 2 +-
...server_route_repository_utils.devdocs.json | 13 +-
.../kbn_server_route_repository_utils.mdx | 2 +-
api_docs/kbn_serverless_common_settings.mdx | 4 +-
.../kbn_serverless_observability_settings.mdx | 4 +-
api_docs/kbn_serverless_project_switcher.mdx | 2 +-
api_docs/kbn_serverless_search_settings.mdx | 4 +-
api_docs/kbn_serverless_security_settings.mdx | 4 +-
api_docs/kbn_serverless_storybook_config.mdx | 2 +-
api_docs/kbn_shared_svg.mdx | 2 +-
api_docs/kbn_shared_ux_avatar_solution.mdx | 2 +-
.../kbn_shared_ux_button_exit_full_screen.mdx | 2 +-
api_docs/kbn_shared_ux_button_toolbar.mdx | 2 +-
api_docs/kbn_shared_ux_card_no_data.mdx | 2 +-
api_docs/kbn_shared_ux_card_no_data_mocks.mdx | 2 +-
api_docs/kbn_shared_ux_chrome_navigation.mdx | 2 +-
api_docs/kbn_shared_ux_error_boundary.mdx | 2 +-
api_docs/kbn_shared_ux_file_context.mdx | 2 +-
api_docs/kbn_shared_ux_file_image.mdx | 2 +-
api_docs/kbn_shared_ux_file_image_mocks.mdx | 2 +-
api_docs/kbn_shared_ux_file_mocks.mdx | 2 +-
api_docs/kbn_shared_ux_file_picker.mdx | 2 +-
api_docs/kbn_shared_ux_file_types.mdx | 2 +-
api_docs/kbn_shared_ux_file_upload.mdx | 2 +-
api_docs/kbn_shared_ux_file_util.mdx | 2 +-
api_docs/kbn_shared_ux_link_redirect_app.mdx | 2 +-
.../kbn_shared_ux_link_redirect_app_mocks.mdx | 2 +-
api_docs/kbn_shared_ux_markdown.mdx | 2 +-
api_docs/kbn_shared_ux_markdown_mocks.mdx | 2 +-
.../kbn_shared_ux_page_analytics_no_data.mdx | 2 +-
...shared_ux_page_analytics_no_data_mocks.mdx | 2 +-
.../kbn_shared_ux_page_kibana_no_data.mdx | 2 +-
...bn_shared_ux_page_kibana_no_data_mocks.mdx | 2 +-
.../kbn_shared_ux_page_kibana_template.mdx | 2 +-
...n_shared_ux_page_kibana_template_mocks.mdx | 2 +-
api_docs/kbn_shared_ux_page_no_data.mdx | 2 +-
.../kbn_shared_ux_page_no_data_config.mdx | 2 +-
...bn_shared_ux_page_no_data_config_mocks.mdx | 2 +-
api_docs/kbn_shared_ux_page_no_data_mocks.mdx | 2 +-
api_docs/kbn_shared_ux_page_solution_nav.mdx | 2 +-
.../kbn_shared_ux_prompt_no_data_views.mdx | 2 +-
...n_shared_ux_prompt_no_data_views_mocks.mdx | 2 +-
api_docs/kbn_shared_ux_prompt_not_found.mdx | 2 +-
api_docs/kbn_shared_ux_router.mdx | 2 +-
api_docs/kbn_shared_ux_router_mocks.mdx | 2 +-
api_docs/kbn_shared_ux_storybook_config.mdx | 2 +-
api_docs/kbn_shared_ux_storybook_mock.mdx | 2 +-
api_docs/kbn_shared_ux_tabbed_modal.mdx | 2 +-
api_docs/kbn_shared_ux_table_persist.mdx | 2 +-
api_docs/kbn_shared_ux_utility.mdx | 2 +-
api_docs/kbn_slo_schema.mdx | 2 +-
api_docs/kbn_some_dev_log.mdx | 2 +-
api_docs/kbn_sort_predicates.mdx | 2 +-
api_docs/kbn_sse_utils.mdx | 2 +-
api_docs/kbn_sse_utils_client.mdx | 2 +-
api_docs/kbn_sse_utils_server.mdx | 2 +-
api_docs/kbn_std.mdx | 2 +-
api_docs/kbn_stdio_dev_helpers.mdx | 2 +-
api_docs/kbn_storybook.mdx | 2 +-
api_docs/kbn_synthetics_e2e.mdx | 2 +-
api_docs/kbn_synthetics_private_location.mdx | 2 +-
api_docs/kbn_telemetry_tools.mdx | 2 +-
api_docs/kbn_test.mdx | 2 +-
api_docs/kbn_test_eui_helpers.mdx | 2 +-
api_docs/kbn_test_jest_helpers.mdx | 2 +-
api_docs/kbn_test_subj_selector.mdx | 2 +-
api_docs/kbn_timerange.mdx | 2 +-
api_docs/kbn_tooling_log.mdx | 2 +-
api_docs/kbn_transpose_utils.mdx | 2 +-
api_docs/kbn_triggers_actions_ui_types.mdx | 2 +-
api_docs/kbn_try_in_console.mdx | 2 +-
api_docs/kbn_ts_projects.mdx | 2 +-
api_docs/kbn_typed_react_router_config.mdx | 2 +-
api_docs/kbn_ui_actions_browser.mdx | 2 +-
api_docs/kbn_ui_shared_deps_src.mdx | 2 +-
api_docs/kbn_ui_theme.mdx | 2 +-
api_docs/kbn_unified_data_table.mdx | 2 +-
api_docs/kbn_unified_doc_viewer.mdx | 2 +-
api_docs/kbn_unified_field_list.mdx | 2 +-
api_docs/kbn_unsaved_changes_badge.mdx | 2 +-
api_docs/kbn_unsaved_changes_prompt.mdx | 2 +-
api_docs/kbn_use_tracked_promise.mdx | 2 +-
api_docs/kbn_user_profile_components.mdx | 2 +-
api_docs/kbn_utility_types.mdx | 2 +-
api_docs/kbn_utility_types_jest.mdx | 2 +-
api_docs/kbn_utils.mdx | 2 +-
api_docs/kbn_visualization_ui_components.mdx | 2 +-
api_docs/kbn_visualization_utils.mdx | 2 +-
api_docs/kbn_xstate_utils.mdx | 2 +-
api_docs/kbn_yarn_lock_validator.mdx | 2 +-
api_docs/kbn_zod.devdocs.json | 2 +-
api_docs/kbn_zod.mdx | 2 +-
api_docs/kbn_zod_helpers.mdx | 2 +-
api_docs/kibana_overview.mdx | 2 +-
api_docs/kibana_react.mdx | 2 +-
api_docs/kibana_utils.mdx | 2 +-
api_docs/kubernetes_security.mdx | 2 +-
api_docs/lens.mdx | 2 +-
api_docs/license_api_guard.mdx | 2 +-
api_docs/license_management.mdx | 2 +-
api_docs/licensing.mdx | 2 +-
api_docs/links.mdx | 2 +-
api_docs/lists.mdx | 2 +-
api_docs/llm_tasks.mdx | 2 +-
api_docs/logs_data_access.mdx | 2 +-
api_docs/logs_explorer.mdx | 2 +-
api_docs/logs_shared.mdx | 2 +-
api_docs/management.mdx | 2 +-
api_docs/maps.mdx | 2 +-
api_docs/maps_ems.mdx | 2 +-
api_docs/metrics_data_access.mdx | 2 +-
api_docs/ml.mdx | 2 +-
api_docs/mock_idp_plugin.mdx | 2 +-
api_docs/monitoring.mdx | 2 +-
api_docs/monitoring_collection.mdx | 2 +-
api_docs/navigation.mdx | 2 +-
api_docs/newsfeed.mdx | 2 +-
api_docs/no_data_page.mdx | 2 +-
api_docs/notifications.mdx | 2 +-
api_docs/observability.mdx | 2 +-
api_docs/observability_a_i_assistant.mdx | 2 +-
api_docs/observability_a_i_assistant_app.mdx | 2 +-
.../observability_ai_assistant_management.mdx | 2 +-
api_docs/observability_logs_explorer.mdx | 2 +-
api_docs/observability_onboarding.mdx | 2 +-
api_docs/observability_shared.mdx | 2 +-
api_docs/osquery.mdx | 2 +-
api_docs/painless_lab.mdx | 2 +-
api_docs/plugin_directory.mdx | 37 +-
api_docs/presentation_panel.mdx | 2 +-
api_docs/presentation_util.mdx | 2 +-
api_docs/product_doc_base.mdx | 2 +-
api_docs/profiling.mdx | 2 +-
api_docs/profiling_data_access.mdx | 2 +-
api_docs/remote_clusters.mdx | 2 +-
api_docs/reporting.mdx | 2 +-
api_docs/rollup.mdx | 2 +-
api_docs/rule_registry.mdx | 2 +-
api_docs/runtime_fields.mdx | 2 +-
api_docs/saved_objects.mdx | 2 +-
api_docs/saved_objects_finder.mdx | 2 +-
api_docs/saved_objects_management.mdx | 2 +-
api_docs/saved_objects_tagging.mdx | 2 +-
api_docs/saved_objects_tagging_oss.mdx | 2 +-
api_docs/saved_search.mdx | 2 +-
api_docs/screenshot_mode.mdx | 2 +-
api_docs/screenshotting.mdx | 2 +-
api_docs/search_assistant.mdx | 2 +-
api_docs/search_connectors.mdx | 2 +-
api_docs/search_homepage.mdx | 2 +-
api_docs/search_indices.devdocs.json | 2 +-
api_docs/search_indices.mdx | 2 +-
api_docs/search_inference_endpoints.mdx | 2 +-
api_docs/search_navigation.devdocs.json | 390 ++++++
api_docs/search_navigation.mdx | 41 +
api_docs/search_notebooks.mdx | 2 +-
api_docs/search_playground.mdx | 2 +-
api_docs/security.mdx | 2 +-
api_docs/security_solution.devdocs.json | 4 +-
api_docs/security_solution.mdx | 2 +-
api_docs/security_solution_ess.mdx | 2 +-
api_docs/security_solution_serverless.mdx | 2 +-
api_docs/serverless.mdx | 2 +-
api_docs/serverless_observability.mdx | 2 +-
api_docs/serverless_search.mdx | 2 +-
api_docs/session_view.mdx | 2 +-
api_docs/share.mdx | 2 +-
api_docs/slo.mdx | 2 +-
api_docs/snapshot_restore.mdx | 2 +-
api_docs/spaces.mdx | 2 +-
api_docs/stack_alerts.mdx | 2 +-
api_docs/stack_connectors.mdx | 2 +-
api_docs/streams.mdx | 2 +-
api_docs/task_manager.mdx | 2 +-
api_docs/telemetry.mdx | 2 +-
api_docs/telemetry_collection_manager.mdx | 2 +-
api_docs/telemetry_management_section.mdx | 2 +-
api_docs/threat_intelligence.mdx | 2 +-
api_docs/timelines.devdocs.json | 204 ++-
api_docs/timelines.mdx | 7 +-
api_docs/transform.mdx | 2 +-
api_docs/triggers_actions_ui.mdx | 2 +-
api_docs/ui_actions.mdx | 2 +-
api_docs/ui_actions_enhanced.mdx | 2 +-
api_docs/unified_doc_viewer.mdx | 2 +-
api_docs/unified_histogram.mdx | 2 +-
api_docs/unified_search.mdx | 2 +-
api_docs/unified_search_autocomplete.mdx | 2 +-
api_docs/uptime.mdx | 2 +-
api_docs/url_forwarding.mdx | 2 +-
api_docs/usage_collection.mdx | 2 +-
api_docs/ux.mdx | 2 +-
api_docs/vis_default_editor.mdx | 2 +-
api_docs/vis_type_gauge.mdx | 2 +-
api_docs/vis_type_heatmap.mdx | 2 +-
api_docs/vis_type_pie.mdx | 2 +-
api_docs/vis_type_table.mdx | 2 +-
api_docs/vis_type_timelion.mdx | 2 +-
api_docs/vis_type_timeseries.mdx | 2 +-
api_docs/vis_type_vega.mdx | 2 +-
api_docs/vis_type_vislib.mdx | 2 +-
api_docs/vis_type_xy.mdx | 2 +-
api_docs/visualizations.mdx | 2 +-
792 files changed, 3187 insertions(+), 910 deletions(-)
create mode 100644 api_docs/kbn_core_http_server_utils.devdocs.json
create mode 100644 api_docs/kbn_core_http_server_utils.mdx
create mode 100644 api_docs/search_navigation.devdocs.json
create mode 100644 api_docs/search_navigation.mdx
diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx
index c46307e899555..2de9842a90caf 100644
--- a/api_docs/actions.mdx
+++ b/api_docs/actions.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions
title: "actions"
image: https://source.unsplash.com/400x175/?github
description: API docs for the actions plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions']
---
import actionsObj from './actions.devdocs.json';
diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx
index 3c758b28e1621..2fe16bd9dc064 100644
--- a/api_docs/advanced_settings.mdx
+++ b/api_docs/advanced_settings.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings
title: "advancedSettings"
image: https://source.unsplash.com/400x175/?github
description: API docs for the advancedSettings plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings']
---
import advancedSettingsObj from './advanced_settings.devdocs.json';
diff --git a/api_docs/ai_assistant_management_selection.mdx b/api_docs/ai_assistant_management_selection.mdx
index 1f9bbdc82eafe..d72c4bbe777b0 100644
--- a/api_docs/ai_assistant_management_selection.mdx
+++ b/api_docs/ai_assistant_management_selection.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiAssistantManagementSelection
title: "aiAssistantManagementSelection"
image: https://source.unsplash.com/400x175/?github
description: API docs for the aiAssistantManagementSelection plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiAssistantManagementSelection']
---
import aiAssistantManagementSelectionObj from './ai_assistant_management_selection.devdocs.json';
diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx
index 1b86116b3a61c..1f8423a67f0ec 100644
--- a/api_docs/aiops.mdx
+++ b/api_docs/aiops.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops
title: "aiops"
image: https://source.unsplash.com/400x175/?github
description: API docs for the aiops plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops']
---
import aiopsObj from './aiops.devdocs.json';
diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx
index 824a897b7edbb..ef1bb1bbff2d3 100644
--- a/api_docs/alerting.mdx
+++ b/api_docs/alerting.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting
title: "alerting"
image: https://source.unsplash.com/400x175/?github
description: API docs for the alerting plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting']
---
import alertingObj from './alerting.devdocs.json';
diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx
index 3fd196f6a3ea1..77c1e8b9c4221 100644
--- a/api_docs/apm.mdx
+++ b/api_docs/apm.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm
title: "apm"
image: https://source.unsplash.com/400x175/?github
description: API docs for the apm plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm']
---
import apmObj from './apm.devdocs.json';
diff --git a/api_docs/apm_data_access.mdx b/api_docs/apm_data_access.mdx
index 70d67751d9f52..bc70c83c44a45 100644
--- a/api_docs/apm_data_access.mdx
+++ b/api_docs/apm_data_access.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apmDataAccess
title: "apmDataAccess"
image: https://source.unsplash.com/400x175/?github
description: API docs for the apmDataAccess plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apmDataAccess']
---
import apmDataAccessObj from './apm_data_access.devdocs.json';
diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx
index c4f3b9492fcd2..c6b70c174c5e9 100644
--- a/api_docs/banners.mdx
+++ b/api_docs/banners.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners
title: "banners"
image: https://source.unsplash.com/400x175/?github
description: API docs for the banners plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners']
---
import bannersObj from './banners.devdocs.json';
diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx
index 5354ef0b591ba..84077417dde6e 100644
--- a/api_docs/bfetch.mdx
+++ b/api_docs/bfetch.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch
title: "bfetch"
image: https://source.unsplash.com/400x175/?github
description: API docs for the bfetch plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch']
---
import bfetchObj from './bfetch.devdocs.json';
diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx
index a012f754c98f6..4c86b2865f8f2 100644
--- a/api_docs/canvas.mdx
+++ b/api_docs/canvas.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas
title: "canvas"
image: https://source.unsplash.com/400x175/?github
description: API docs for the canvas plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas']
---
import canvasObj from './canvas.devdocs.json';
diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx
index 279f5f92bc770..cd5073777d5e8 100644
--- a/api_docs/cases.mdx
+++ b/api_docs/cases.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases
title: "cases"
image: https://source.unsplash.com/400x175/?github
description: API docs for the cases plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases']
---
import casesObj from './cases.devdocs.json';
diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx
index c45e0a8dead2c..59573c9c46534 100644
--- a/api_docs/charts.mdx
+++ b/api_docs/charts.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts
title: "charts"
image: https://source.unsplash.com/400x175/?github
description: API docs for the charts plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts']
---
import chartsObj from './charts.devdocs.json';
diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx
index 32379e22a8fbd..ce22abe82430a 100644
--- a/api_docs/cloud.mdx
+++ b/api_docs/cloud.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud
title: "cloud"
image: https://source.unsplash.com/400x175/?github
description: API docs for the cloud plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud']
---
import cloudObj from './cloud.devdocs.json';
diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx
index 000e9143be76f..6a1a92aaa53cd 100644
--- a/api_docs/cloud_data_migration.mdx
+++ b/api_docs/cloud_data_migration.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDataMigration
title: "cloudDataMigration"
image: https://source.unsplash.com/400x175/?github
description: API docs for the cloudDataMigration plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDataMigration']
---
import cloudDataMigrationObj from './cloud_data_migration.devdocs.json';
diff --git a/api_docs/cloud_defend.mdx b/api_docs/cloud_defend.mdx
index 54adbbaddee54..f23adca3af9ad 100644
--- a/api_docs/cloud_defend.mdx
+++ b/api_docs/cloud_defend.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDefend
title: "cloudDefend"
image: https://source.unsplash.com/400x175/?github
description: API docs for the cloudDefend plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDefend']
---
import cloudDefendObj from './cloud_defend.devdocs.json';
diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx
index 82a7ab678f338..6dfde72b5109c 100644
--- a/api_docs/cloud_security_posture.mdx
+++ b/api_docs/cloud_security_posture.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture
title: "cloudSecurityPosture"
image: https://source.unsplash.com/400x175/?github
description: API docs for the cloudSecurityPosture plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudSecurityPosture']
---
import cloudSecurityPostureObj from './cloud_security_posture.devdocs.json';
diff --git a/api_docs/console.mdx b/api_docs/console.mdx
index ca5595652c622..3e4cf813bc43c 100644
--- a/api_docs/console.mdx
+++ b/api_docs/console.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console
title: "console"
image: https://source.unsplash.com/400x175/?github
description: API docs for the console plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console']
---
import consoleObj from './console.devdocs.json';
diff --git a/api_docs/content_management.mdx b/api_docs/content_management.mdx
index baec4a847cbee..05c6205a528e4 100644
--- a/api_docs/content_management.mdx
+++ b/api_docs/content_management.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/contentManagement
title: "contentManagement"
image: https://source.unsplash.com/400x175/?github
description: API docs for the contentManagement plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'contentManagement']
---
import contentManagementObj from './content_management.devdocs.json';
diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx
index ed65a57c45b84..636fcb8435914 100644
--- a/api_docs/controls.mdx
+++ b/api_docs/controls.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls
title: "controls"
image: https://source.unsplash.com/400x175/?github
description: API docs for the controls plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls']
---
import controlsObj from './controls.devdocs.json';
diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx
index 168097f888727..4f7f01042031d 100644
--- a/api_docs/custom_integrations.mdx
+++ b/api_docs/custom_integrations.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations
title: "customIntegrations"
image: https://source.unsplash.com/400x175/?github
description: API docs for the customIntegrations plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations']
---
import customIntegrationsObj from './custom_integrations.devdocs.json';
diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx
index 896f30264a98d..0660af730b1c3 100644
--- a/api_docs/dashboard.mdx
+++ b/api_docs/dashboard.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard
title: "dashboard"
image: https://source.unsplash.com/400x175/?github
description: API docs for the dashboard plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard']
---
import dashboardObj from './dashboard.devdocs.json';
diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx
index 39ff8a3aed26d..c7141fd4cc0d0 100644
--- a/api_docs/dashboard_enhanced.mdx
+++ b/api_docs/dashboard_enhanced.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced
title: "dashboardEnhanced"
image: https://source.unsplash.com/400x175/?github
description: API docs for the dashboardEnhanced plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced']
---
import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json';
diff --git a/api_docs/data.mdx b/api_docs/data.mdx
index 06c3e8522b3bd..94c336fce9e58 100644
--- a/api_docs/data.mdx
+++ b/api_docs/data.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data
title: "data"
image: https://source.unsplash.com/400x175/?github
description: API docs for the data plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data']
---
import dataObj from './data.devdocs.json';
diff --git a/api_docs/data_quality.mdx b/api_docs/data_quality.mdx
index 041afddaca06d..6a8e27093d896 100644
--- a/api_docs/data_quality.mdx
+++ b/api_docs/data_quality.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataQuality
title: "dataQuality"
image: https://source.unsplash.com/400x175/?github
description: API docs for the dataQuality plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataQuality']
---
import dataQualityObj from './data_quality.devdocs.json';
diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx
index ba24c3db6c879..8d9f86d84d380 100644
--- a/api_docs/data_query.mdx
+++ b/api_docs/data_query.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query
title: "data.query"
image: https://source.unsplash.com/400x175/?github
description: API docs for the data.query plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query']
---
import dataQueryObj from './data_query.devdocs.json';
diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx
index 52bf12c0a388b..f58dbf1de8ee3 100644
--- a/api_docs/data_search.mdx
+++ b/api_docs/data_search.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search
title: "data.search"
image: https://source.unsplash.com/400x175/?github
description: API docs for the data.search plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search']
---
import dataSearchObj from './data_search.devdocs.json';
diff --git a/api_docs/data_usage.devdocs.json b/api_docs/data_usage.devdocs.json
index 09fcffd5c58eb..fa0dd73eb8c27 100644
--- a/api_docs/data_usage.devdocs.json
+++ b/api_docs/data_usage.devdocs.json
@@ -88,7 +88,7 @@
"signature": [
"\"/api/data_usage/\""
],
- "path": "x-pack/plugins/data_usage/common/index.ts",
+ "path": "x-pack/plugins/data_usage/common/constants.ts",
"deprecated": false,
"trackAdoption": false,
"initialIsOpen": false
@@ -100,7 +100,7 @@
"tags": [],
"label": "DATA_USAGE_DATA_STREAMS_API_ROUTE",
"description": [],
- "path": "x-pack/plugins/data_usage/common/index.ts",
+ "path": "x-pack/plugins/data_usage/common/constants.ts",
"deprecated": false,
"trackAdoption": false,
"initialIsOpen": false
@@ -112,7 +112,7 @@
"tags": [],
"label": "DATA_USAGE_METRICS_API_ROUTE",
"description": [],
- "path": "x-pack/plugins/data_usage/common/index.ts",
+ "path": "x-pack/plugins/data_usage/common/constants.ts",
"deprecated": false,
"trackAdoption": false,
"initialIsOpen": false
@@ -127,7 +127,7 @@
"signature": [
"50"
],
- "path": "x-pack/plugins/data_usage/common/index.ts",
+ "path": "x-pack/plugins/data_usage/common/constants.ts",
"deprecated": false,
"trackAdoption": false,
"initialIsOpen": false
@@ -142,19 +142,7 @@
"signature": [
"\"data_usage\""
],
- "path": "x-pack/plugins/data_usage/common/index.ts",
- "deprecated": false,
- "trackAdoption": false,
- "initialIsOpen": false
- },
- {
- "parentPluginId": "dataUsage",
- "id": "def-common.PLUGIN_NAME",
- "type": "string",
- "tags": [],
- "label": "PLUGIN_NAME",
- "description": [],
- "path": "x-pack/plugins/data_usage/common/index.ts",
+ "path": "x-pack/plugins/data_usage/common/constants.ts",
"deprecated": false,
"trackAdoption": false,
"initialIsOpen": false
diff --git a/api_docs/data_usage.mdx b/api_docs/data_usage.mdx
index 3e2caf4ea20f7..1eac24bd281e3 100644
--- a/api_docs/data_usage.mdx
+++ b/api_docs/data_usage.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataUsage
title: "dataUsage"
image: https://source.unsplash.com/400x175/?github
description: API docs for the dataUsage plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataUsage']
---
import dataUsageObj from './data_usage.devdocs.json';
@@ -21,7 +21,7 @@ Contact [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai
| Public API count | Any count | Items lacking comments | Missing exports |
|-------------------|-----------|------------------------|-----------------|
-| 10 | 0 | 10 | 0 |
+| 9 | 0 | 9 | 0 |
## Client
diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx
index eda90bd90b1ae..cd48e8825e5f9 100644
--- a/api_docs/data_view_editor.mdx
+++ b/api_docs/data_view_editor.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor
title: "dataViewEditor"
image: https://source.unsplash.com/400x175/?github
description: API docs for the dataViewEditor plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor']
---
import dataViewEditorObj from './data_view_editor.devdocs.json';
diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx
index a40a06de84f75..b6179080b4b31 100644
--- a/api_docs/data_view_field_editor.mdx
+++ b/api_docs/data_view_field_editor.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor
title: "dataViewFieldEditor"
image: https://source.unsplash.com/400x175/?github
description: API docs for the dataViewFieldEditor plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor']
---
import dataViewFieldEditorObj from './data_view_field_editor.devdocs.json';
diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx
index d611d8e1d6c48..7710e040d2c9c 100644
--- a/api_docs/data_view_management.mdx
+++ b/api_docs/data_view_management.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement
title: "dataViewManagement"
image: https://source.unsplash.com/400x175/?github
description: API docs for the dataViewManagement plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement']
---
import dataViewManagementObj from './data_view_management.devdocs.json';
diff --git a/api_docs/data_views.devdocs.json b/api_docs/data_views.devdocs.json
index 17af467c336c4..2db8e5ec94763 100644
--- a/api_docs/data_views.devdocs.json
+++ b/api_docs/data_views.devdocs.json
@@ -14202,10 +14202,6 @@
"plugin": "securitySolution",
"path": "x-pack/plugins/security_solution/public/sourcerer/containers/create_sourcerer_data_view.ts"
},
- {
- "plugin": "securitySolution",
- "path": "x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/eql_query_bar/validators.ts"
- },
{
"plugin": "timelines",
"path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts"
diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx
index e3b18891387da..c20498315eb04 100644
--- a/api_docs/data_views.mdx
+++ b/api_docs/data_views.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews
title: "dataViews"
image: https://source.unsplash.com/400x175/?github
description: API docs for the dataViews plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews']
---
import dataViewsObj from './data_views.devdocs.json';
diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx
index 10b17f6cb009b..3ce8fb25b84ca 100644
--- a/api_docs/data_visualizer.mdx
+++ b/api_docs/data_visualizer.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer
title: "dataVisualizer"
image: https://source.unsplash.com/400x175/?github
description: API docs for the dataVisualizer plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer']
---
import dataVisualizerObj from './data_visualizer.devdocs.json';
diff --git a/api_docs/dataset_quality.mdx b/api_docs/dataset_quality.mdx
index 8b5a77fa9f8ba..ccf37a02643db 100644
--- a/api_docs/dataset_quality.mdx
+++ b/api_docs/dataset_quality.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/datasetQuality
title: "datasetQuality"
image: https://source.unsplash.com/400x175/?github
description: API docs for the datasetQuality plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'datasetQuality']
---
import datasetQualityObj from './dataset_quality.devdocs.json';
diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx
index 93404d07f9595..d57e382a484fb 100644
--- a/api_docs/deprecations_by_api.mdx
+++ b/api_docs/deprecations_by_api.mdx
@@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi
slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api
title: Deprecated API usage by API
description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by.
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana']
---
diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx
index 0afb9d9eeaefa..2f67cddd362ea 100644
--- a/api_docs/deprecations_by_plugin.mdx
+++ b/api_docs/deprecations_by_plugin.mdx
@@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin
slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin
title: Deprecated API usage by plugin
description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by.
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana']
---
@@ -1328,7 +1328,7 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/
| | [wrap_search_source_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.ts#:~:text=create) | - |
| | [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch) | - |
| | [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/hooks/eql/api.ts#:~:text=options) | - |
-| | [create_sourcerer_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/sourcerer/containers/create_sourcerer_data_view.ts#:~:text=title), [create_sourcerer_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/sourcerer/containers/create_sourcerer_data_view.ts#:~:text=title), [create_sourcerer_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/sourcerer/containers/create_sourcerer_data_view.ts#:~:text=title), [validators.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/eql_query_bar/validators.ts#:~:text=title) | - |
+| | [create_sourcerer_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/sourcerer/containers/create_sourcerer_data_view.ts#:~:text=title), [create_sourcerer_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/sourcerer/containers/create_sourcerer_data_view.ts#:~:text=title), [create_sourcerer_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/sourcerer/containers/create_sourcerer_data_view.ts#:~:text=title) | - |
| | [fleet_services.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts#:~:text=policy_id), [fleet_services.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts#:~:text=policy_id), [endpoint_metadata_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.test.ts#:~:text=policy_id), [endpoint_package_policies.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/endpoint_package_policies.test.ts#:~:text=policy_id), [index.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts#:~:text=policy_id) | - |
| | [fleet_services.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts#:~:text=policy_id), [fleet_services.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts#:~:text=policy_id), [endpoint_metadata_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.test.ts#:~:text=policy_id), [endpoint_package_policies.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/endpoint_package_policies.test.ts#:~:text=policy_id), [index.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts#:~:text=policy_id) | - |
| | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode)+ 7 more | 8.8.0 |
diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx
index f6fb16069c438..829ba875d1e72 100644
--- a/api_docs/deprecations_by_team.mdx
+++ b/api_docs/deprecations_by_team.mdx
@@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam
slug: /kibana-dev-docs/api-meta/deprecations-due-by-team
title: Deprecated APIs due to be removed, by team
description: Lists the teams that are referencing deprecated APIs with a remove by date.
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana']
---
diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx
index 014e3b9577291..4ab3d0217e269 100644
--- a/api_docs/dev_tools.mdx
+++ b/api_docs/dev_tools.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools
title: "devTools"
image: https://source.unsplash.com/400x175/?github
description: API docs for the devTools plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools']
---
import devToolsObj from './dev_tools.devdocs.json';
diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx
index e51f0efbca904..f08f73d3ac893 100644
--- a/api_docs/discover.mdx
+++ b/api_docs/discover.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover
title: "discover"
image: https://source.unsplash.com/400x175/?github
description: API docs for the discover plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover']
---
import discoverObj from './discover.devdocs.json';
diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx
index 8f33990a5cb6a..8a93c5fa93283 100644
--- a/api_docs/discover_enhanced.mdx
+++ b/api_docs/discover_enhanced.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced
title: "discoverEnhanced"
image: https://source.unsplash.com/400x175/?github
description: API docs for the discoverEnhanced plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced']
---
import discoverEnhancedObj from './discover_enhanced.devdocs.json';
diff --git a/api_docs/discover_shared.mdx b/api_docs/discover_shared.mdx
index 5625ea4ce73a1..d26c5d48892e2 100644
--- a/api_docs/discover_shared.mdx
+++ b/api_docs/discover_shared.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverShared
title: "discoverShared"
image: https://source.unsplash.com/400x175/?github
description: API docs for the discoverShared plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverShared']
---
import discoverSharedObj from './discover_shared.devdocs.json';
diff --git a/api_docs/ecs_data_quality_dashboard.mdx b/api_docs/ecs_data_quality_dashboard.mdx
index a89da9995ee88..81848ddabefa0 100644
--- a/api_docs/ecs_data_quality_dashboard.mdx
+++ b/api_docs/ecs_data_quality_dashboard.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ecsDataQualityDashboard
title: "ecsDataQualityDashboard"
image: https://source.unsplash.com/400x175/?github
description: API docs for the ecsDataQualityDashboard plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard']
---
import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json';
diff --git a/api_docs/elastic_assistant.mdx b/api_docs/elastic_assistant.mdx
index 67ebc7fedb139..bc47f563f880d 100644
--- a/api_docs/elastic_assistant.mdx
+++ b/api_docs/elastic_assistant.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/elasticAssistant
title: "elasticAssistant"
image: https://source.unsplash.com/400x175/?github
description: API docs for the elasticAssistant plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'elasticAssistant']
---
import elasticAssistantObj from './elastic_assistant.devdocs.json';
diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx
index cb4b3c4bad40d..87b8021dab999 100644
--- a/api_docs/embeddable.mdx
+++ b/api_docs/embeddable.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable
title: "embeddable"
image: https://source.unsplash.com/400x175/?github
description: API docs for the embeddable plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable']
---
import embeddableObj from './embeddable.devdocs.json';
diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx
index e7c8c82ff0292..7e2be87068249 100644
--- a/api_docs/embeddable_enhanced.mdx
+++ b/api_docs/embeddable_enhanced.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced
title: "embeddableEnhanced"
image: https://source.unsplash.com/400x175/?github
description: API docs for the embeddableEnhanced plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced']
---
import embeddableEnhancedObj from './embeddable_enhanced.devdocs.json';
diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx
index acb4cefaddec0..13224e8a9af43 100644
--- a/api_docs/encrypted_saved_objects.mdx
+++ b/api_docs/encrypted_saved_objects.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects
title: "encryptedSavedObjects"
image: https://source.unsplash.com/400x175/?github
description: API docs for the encryptedSavedObjects plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects']
---
import encryptedSavedObjectsObj from './encrypted_saved_objects.devdocs.json';
diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx
index e7a15f22d30a5..93eeb38d8d9bf 100644
--- a/api_docs/enterprise_search.mdx
+++ b/api_docs/enterprise_search.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch
title: "enterpriseSearch"
image: https://source.unsplash.com/400x175/?github
description: API docs for the enterpriseSearch plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch']
---
import enterpriseSearchObj from './enterprise_search.devdocs.json';
diff --git a/api_docs/entities_data_access.mdx b/api_docs/entities_data_access.mdx
index d3dc9b4f8bf3f..4cbcc5e683b9b 100644
--- a/api_docs/entities_data_access.mdx
+++ b/api_docs/entities_data_access.mdx
@@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/entitiesDataAccess
title: "entitiesDataAccess"
image: https://source.unsplash.com/400x175/?github
description: API docs for the entitiesDataAccess plugin
-date: 2024-11-22
+date: 2024-11-23
tags: ['contributor', 'dev', 'apidocs', 'kibana', 'entitiesDataAccess']
---
import entitiesDataAccessObj from './entities_data_access.devdocs.json';
diff --git a/api_docs/entity_manager.devdocs.json b/api_docs/entity_manager.devdocs.json
index a3f5fff48eb99..7f11685ebce83 100644
--- a/api_docs/entity_manager.devdocs.json
+++ b/api_docs/entity_manager.devdocs.json
@@ -2,6 +2,1121 @@
"id": "entityManager",
"client": {
"classes": [
+ {
+ "parentPluginId": "entityManager",
+ "id": "def-public.EntityClient",
+ "type": "Class",
+ "tags": [],
+ "label": "EntityClient",
+ "description": [],
+ "path": "x-pack/plugins/entity_manager/public/lib/entity_client.ts",
+ "deprecated": false,
+ "trackAdoption": false,
+ "children": [
+ {
+ "parentPluginId": "entityManager",
+ "id": "def-public.EntityClient.repositoryClient",
+ "type": "Function",
+ "tags": [],
+ "label": "repositoryClient",
+ "description": [],
+ "signature": [
+ "(endpoint: TEndpoint, ...args: MaybeOptionalArgs<",
+ {
+ "pluginId": "@kbn/server-route-repository-utils",
+ "scope": "common",
+ "docId": "kibKbnServerRouteRepositoryUtilsPluginApi",
+ "section": "def-common.ClientRequestParamsOf",
+ "text": "ClientRequestParamsOf"
+ },
+ "<{ \"POST /internal/entities/v2/_search/preview\": ",
+ {
+ "pluginId": "@kbn/server-route-repository-utils",
+ "scope": "common",
+ "docId": "kibKbnServerRouteRepositoryUtilsPluginApi",
+ "section": "def-common.ServerRoute",
+ "text": "ServerRoute"
+ },
+ "<\"POST /internal/entities/v2/_search/preview\", Zod.ZodObject<{ body: Zod.ZodObject<{ sources: Zod.ZodArray>; index_patterns: Zod.ZodArray; identity_fields: Zod.ZodArray; metadata_fields: Zod.ZodArray; filters: Zod.ZodArray; }, \"strip\", Zod.ZodTypeAny, { type: string; filters: string[]; timestamp_field: string; metadata_fields: string[]; index_patterns: string[]; identity_fields: string[]; }, { type: string; filters: string[]; metadata_fields: string[]; index_patterns: string[]; identity_fields: string[]; timestamp_field?: string | undefined; }>, \"many\">; start: Zod.ZodEffects>, string, string | undefined>; end: Zod.ZodEffects>, string, string | undefined>; limit: Zod.ZodDefault>; }, \"strip\", Zod.ZodTypeAny, { start: string; end: string; sources: { type: string; filters: string[]; timestamp_field: string; metadata_fields: string[]; index_patterns: string[]; identity_fields: string[]; }[]; limit: number; }, { sources: { type: string; filters: string[]; metadata_fields: string[]; index_patterns: string[]; identity_fields: string[]; timestamp_field?: string | undefined; }[]; start?: string | undefined; end?: string | undefined; limit?: number | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { body: { start: string; end: string; sources: { type: string; filters: string[]; timestamp_field: string; metadata_fields: string[]; index_patterns: string[]; identity_fields: string[]; }[]; limit: number; }; }, { body: { sources: { type: string; filters: string[]; metadata_fields: string[]; index_patterns: string[]; identity_fields: string[]; timestamp_field?: string | undefined; }[]; start?: string | undefined; end?: string | undefined; limit?: number | undefined; }; }>, ",
+ "EntityManagerRouteHandlerResources",
+ ", ",
+ {
+ "pluginId": "@kbn/core-http-server",
+ "scope": "server",
+ "docId": "kibKbnCoreHttpServerPluginApi",
+ "section": "def-server.IKibanaResponse",
+ "text": "IKibanaResponse"
+ },
+ "<{ entities: ",
+ {
+ "pluginId": "@kbn/entities-schema",
+ "scope": "common",
+ "docId": "kibKbnEntitiesSchemaPluginApi",
+ "section": "def-common.EntityV2",
+ "text": "EntityV2"
+ },
+ "[]; }>, ",
+ {
+ "pluginId": "@kbn/server-route-repository-utils",
+ "scope": "common",
+ "docId": "kibKbnServerRouteRepositoryUtilsPluginApi",
+ "section": "def-common.DefaultRouteCreateOptions",
+ "text": "DefaultRouteCreateOptions"
+ },
+ ">; \"POST /internal/entities/v2/_search\": ",
+ {
+ "pluginId": "@kbn/server-route-repository-utils",
+ "scope": "common",
+ "docId": "kibKbnServerRouteRepositoryUtilsPluginApi",
+ "section": "def-common.ServerRoute",
+ "text": "ServerRoute"
+ },
+ "<\"POST /internal/entities/v2/_search\", Zod.ZodObject<{ body: Zod.ZodObject<{ type: Zod.ZodString; metadata_fields: Zod.ZodDefault>>; filters: Zod.ZodDefault>>; start: Zod.ZodEffects>, string, string | undefined>; end: Zod.ZodEffects>, string, string | undefined>; limit: Zod.ZodDefault>; }, \"strip\", Zod.ZodTypeAny, { type: string; start: string; end: string; filters: string[]; limit: number; metadata_fields: string[]; }, { type: string; start?: string | undefined; end?: string | undefined; filters?: string[] | undefined; limit?: number | undefined; metadata_fields?: string[] | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { body: { type: string; start: string; end: string; filters: string[]; limit: number; metadata_fields: string[]; }; }, { body: { type: string; start?: string | undefined; end?: string | undefined; filters?: string[] | undefined; limit?: number | undefined; metadata_fields?: string[] | undefined; }; }>, ",
+ "EntityManagerRouteHandlerResources",
+ ", ",
+ {
+ "pluginId": "@kbn/core-http-server",
+ "scope": "server",
+ "docId": "kibKbnCoreHttpServerPluginApi",
+ "section": "def-server.IKibanaResponse",
+ "text": "IKibanaResponse"
+ },
+ ", ",
+ {
+ "pluginId": "@kbn/server-route-repository-utils",
+ "scope": "common",
+ "docId": "kibKbnServerRouteRepositoryUtilsPluginApi",
+ "section": "def-common.DefaultRouteCreateOptions",
+ "text": "DefaultRouteCreateOptions"
+ },
+ ">; \"PATCH /internal/entities/definition/{id}\": ",
+ {
+ "pluginId": "@kbn/server-route-repository-utils",
+ "scope": "common",
+ "docId": "kibKbnServerRouteRepositoryUtilsPluginApi",
+ "section": "def-common.ServerRoute",
+ "text": "ServerRoute"
+ },
+ "<\"PATCH /internal/entities/definition/{id}\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; body: Zod.ZodObject; filter: Zod.ZodOptional>; version: Zod.ZodOptional>; name: Zod.ZodOptional; description: Zod.ZodOptional>; metrics: Zod.ZodOptional; field: Zod.ZodString; filter: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { name: string; field: string; aggregation: ",
+ {
+ "pluginId": "@kbn/entities-schema",
+ "scope": "common",
+ "docId": "kibKbnEntitiesSchemaPluginApi",
+ "section": "def-common.BasicAggregations",
+ "text": "BasicAggregations"
+ },
+ "; filter?: string | undefined; }, { name: string; field: string; aggregation: ",
+ {
+ "pluginId": "@kbn/entities-schema",
+ "scope": "common",
+ "docId": "kibKbnEntitiesSchemaPluginApi",
+ "section": "def-common.BasicAggregations",
+ "text": "BasicAggregations"
+ },
+ "; filter?: string | undefined; }>, Zod.ZodObject<{ name: Zod.ZodString; aggregation: Zod.ZodLiteral<\"doc_count\">; filter: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { name: string; aggregation: \"doc_count\"; filter?: string | undefined; }, { name: string; aggregation: \"doc_count\"; filter?: string | undefined; }>, Zod.ZodObject<{ name: Zod.ZodString; aggregation: Zod.ZodLiteral<\"percentile\">; field: Zod.ZodString; percentile: Zod.ZodNumber; filter: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { name: string; field: string; percentile: number; aggregation: \"percentile\"; filter?: string | undefined; }, { name: string; field: string; percentile: number; aggregation: \"percentile\"; filter?: string | undefined; }>]>, \"many\">; equation: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { name: string; metrics: ({ name: string; field: string; aggregation: ",
+ {
+ "pluginId": "@kbn/entities-schema",
+ "scope": "common",
+ "docId": "kibKbnEntitiesSchemaPluginApi",
+ "section": "def-common.BasicAggregations",
+ "text": "BasicAggregations"
+ },
+ "; filter?: string | undefined; } | { name: string; aggregation: \"doc_count\"; filter?: string | undefined; } | { name: string; field: string; percentile: number; aggregation: \"percentile\"; filter?: string | undefined; })[]; equation: string; }, { name: string; metrics: ({ name: string; field: string; aggregation: ",
+ {
+ "pluginId": "@kbn/entities-schema",
+ "scope": "common",
+ "docId": "kibKbnEntitiesSchemaPluginApi",
+ "section": "def-common.BasicAggregations",
+ "text": "BasicAggregations"
+ },
+ "; filter?: string | undefined; } | { name: string; aggregation: \"doc_count\"; filter?: string | undefined; } | { name: string; field: string; percentile: number; aggregation: \"percentile\"; filter?: string | undefined; })[]; equation: string; }>, \"many\">>>; indexPatterns: Zod.ZodOptional>; metadata: Zod.ZodOptional; aggregation: Zod.ZodDefault; limit: Zod.ZodDefault; lookbackPeriod: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { type: \"terms\"; limit: number; lookbackPeriod?: string | undefined; }, { type: \"terms\"; limit?: number | undefined; lookbackPeriod?: string | undefined; }>, Zod.ZodObject<{ type: Zod.ZodLiteral<\"top_value\">; sort: Zod.ZodRecord, Zod.ZodLiteral<\"desc\">]>>; lookbackPeriod: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; }, { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; }>]>>>; }, \"strip\", Zod.ZodTypeAny, { source: string; aggregation: { type: \"terms\"; limit: number; lookbackPeriod?: string | undefined; } | { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; }; destination?: string | undefined; }, { source: string; destination?: string | undefined; aggregation?: { type: \"terms\"; limit?: number | undefined; lookbackPeriod?: string | undefined; } | { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; } | undefined; }>, Zod.ZodEffects]>, { destination: string; source: string; aggregation: { type: \"terms\"; limit: number; lookbackPeriod?: string | undefined; } | { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; }; } | { destination: string; source: string; aggregation: { type: \"terms\"; limit: number; lookbackPeriod: undefined; }; }, string | { source: string; destination?: string | undefined; aggregation?: { type: \"terms\"; limit?: number | undefined; lookbackPeriod?: string | undefined; } | { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; } | undefined; }>, { destination: string; source: string; aggregation: { type: \"terms\"; limit: number; lookbackPeriod?: string | undefined; } | { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; }; } | { destination: string; source: string; aggregation: { type: \"terms\"; limit: number; lookbackPeriod: undefined; }; }, string | { source: string; destination?: string | undefined; aggregation?: { type: \"terms\"; limit?: number | undefined; lookbackPeriod?: string | undefined; } | { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; } | undefined; }>, \"many\">>>; identityFields: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { field: string; optional: false; }, { field: string; optional: false; }>, Zod.ZodEffects]>, \"many\">>; displayNameTemplate: Zod.ZodOptional; staticFields: Zod.ZodOptional>>; latest: Zod.ZodOptional>; settings: Zod.ZodOptional; syncDelay: Zod.ZodOptional; frequency: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { frequency?: string | undefined; syncField?: string | undefined; syncDelay?: string | undefined; }, { frequency?: string | undefined; syncField?: string | undefined; syncDelay?: string | undefined; }>>; }, \"strip\", Zod.ZodTypeAny, { lookbackPeriod: string; timestampField: string; settings?: { frequency?: string | undefined; syncField?: string | undefined; syncDelay?: string | undefined; } | undefined; }, { timestampField: string; settings?: { frequency?: string | undefined; syncField?: string | undefined; syncDelay?: string | undefined; } | undefined; lookbackPeriod?: string | undefined; }>>; installedComponents: Zod.ZodOptional, Zod.ZodLiteral<\"ingest_pipeline\">, Zod.ZodLiteral<\"template\">]>; id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; type: \"transform\" | \"template\" | \"ingest_pipeline\"; }, { id: string; type: \"transform\" | \"template\" | \"ingest_pipeline\"; }>, \"many\">>>; }, { latest: Zod.ZodOptional; lookbackPeriod: Zod.ZodOptional>>; settings: Zod.ZodOptional; syncDelay: Zod.ZodOptional; frequency: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { frequency?: string | undefined; syncField?: string | undefined; syncDelay?: string | undefined; }, { frequency?: string | undefined; syncField?: string | undefined; syncDelay?: string | undefined; }>>>; }, \"strip\", Zod.ZodTypeAny, { settings?: { frequency?: string | undefined; syncField?: string | undefined; syncDelay?: string | undefined; } | undefined; lookbackPeriod?: string | undefined; timestampField?: string | undefined; }, { settings?: { frequency?: string | undefined; syncField?: string | undefined; syncDelay?: string | undefined; } | undefined; lookbackPeriod?: string | undefined; timestampField?: string | undefined; }>>; version: Zod.ZodEffects; }>, \"strip\", Zod.ZodTypeAny, { version: string; type?: string | undefined; filter?: string | undefined; name?: string | undefined; description?: string | undefined; metrics?: { name: string; metrics: ({ name: string; field: string; aggregation: ",
+ {
+ "pluginId": "@kbn/entities-schema",
+ "scope": "common",
+ "docId": "kibKbnEntitiesSchemaPluginApi",
+ "section": "def-common.BasicAggregations",
+ "text": "BasicAggregations"
+ },
+ "; filter?: string | undefined; } | { name: string; aggregation: \"doc_count\"; filter?: string | undefined; } | { name: string; field: string; percentile: number; aggregation: \"percentile\"; filter?: string | undefined; })[]; equation: string; }[] | undefined; indexPatterns?: string[] | undefined; metadata?: ({ destination: string; source: string; aggregation: { type: \"terms\"; limit: number; lookbackPeriod?: string | undefined; } | { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; }; } | { destination: string; source: string; aggregation: { type: \"terms\"; limit: number; lookbackPeriod: undefined; }; })[] | undefined; identityFields?: ({ field: string; optional: false; } | { field: string; optional: boolean; })[] | undefined; displayNameTemplate?: string | undefined; staticFields?: Record | undefined; latest?: { settings?: { frequency?: string | undefined; syncField?: string | undefined; syncDelay?: string | undefined; } | undefined; lookbackPeriod?: string | undefined; timestampField?: string | undefined; } | undefined; installedComponents?: { id: string; type: \"transform\" | \"template\" | \"ingest_pipeline\"; }[] | undefined; }, { version: string; type?: string | undefined; filter?: string | undefined; name?: string | undefined; description?: string | undefined; metrics?: { name: string; metrics: ({ name: string; field: string; aggregation: ",
+ {
+ "pluginId": "@kbn/entities-schema",
+ "scope": "common",
+ "docId": "kibKbnEntitiesSchemaPluginApi",
+ "section": "def-common.BasicAggregations",
+ "text": "BasicAggregations"
+ },
+ "; filter?: string | undefined; } | { name: string; aggregation: \"doc_count\"; filter?: string | undefined; } | { name: string; field: string; percentile: number; aggregation: \"percentile\"; filter?: string | undefined; })[]; equation: string; }[] | undefined; indexPatterns?: string[] | undefined; metadata?: (string | { source: string; destination?: string | undefined; aggregation?: { type: \"terms\"; limit?: number | undefined; lookbackPeriod?: string | undefined; } | { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; } | undefined; })[] | undefined; identityFields?: (string | { field: string; optional: false; })[] | undefined; displayNameTemplate?: string | undefined; staticFields?: Record | undefined; latest?: { settings?: { frequency?: string | undefined; syncField?: string | undefined; syncDelay?: string | undefined; } | undefined; lookbackPeriod?: string | undefined; timestampField?: string | undefined; } | undefined; installedComponents?: { id: string; type: \"transform\" | \"template\" | \"ingest_pipeline\"; }[] | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; body: { version: string; type?: string | undefined; filter?: string | undefined; name?: string | undefined; description?: string | undefined; metrics?: { name: string; metrics: ({ name: string; field: string; aggregation: ",
+ {
+ "pluginId": "@kbn/entities-schema",
+ "scope": "common",
+ "docId": "kibKbnEntitiesSchemaPluginApi",
+ "section": "def-common.BasicAggregations",
+ "text": "BasicAggregations"
+ },
+ "; filter?: string | undefined; } | { name: string; aggregation: \"doc_count\"; filter?: string | undefined; } | { name: string; field: string; percentile: number; aggregation: \"percentile\"; filter?: string | undefined; })[]; equation: string; }[] | undefined; indexPatterns?: string[] | undefined; metadata?: ({ destination: string; source: string; aggregation: { type: \"terms\"; limit: number; lookbackPeriod?: string | undefined; } | { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; }; } | { destination: string; source: string; aggregation: { type: \"terms\"; limit: number; lookbackPeriod: undefined; }; })[] | undefined; identityFields?: ({ field: string; optional: false; } | { field: string; optional: boolean; })[] | undefined; displayNameTemplate?: string | undefined; staticFields?: Record | undefined; latest?: { settings?: { frequency?: string | undefined; syncField?: string | undefined; syncDelay?: string | undefined; } | undefined; lookbackPeriod?: string | undefined; timestampField?: string | undefined; } | undefined; installedComponents?: { id: string; type: \"transform\" | \"template\" | \"ingest_pipeline\"; }[] | undefined; }; }, { path: { id: string; }; body: { version: string; type?: string | undefined; filter?: string | undefined; name?: string | undefined; description?: string | undefined; metrics?: { name: string; metrics: ({ name: string; field: string; aggregation: ",
+ {
+ "pluginId": "@kbn/entities-schema",
+ "scope": "common",
+ "docId": "kibKbnEntitiesSchemaPluginApi",
+ "section": "def-common.BasicAggregations",
+ "text": "BasicAggregations"
+ },
+ "; filter?: string | undefined; } | { name: string; aggregation: \"doc_count\"; filter?: string | undefined; } | { name: string; field: string; percentile: number; aggregation: \"percentile\"; filter?: string | undefined; })[]; equation: string; }[] | undefined; indexPatterns?: string[] | undefined; metadata?: (string | { source: string; destination?: string | undefined; aggregation?: { type: \"terms\"; limit?: number | undefined; lookbackPeriod?: string | undefined; } | { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; } | undefined; })[] | undefined; identityFields?: (string | { field: string; optional: false; })[] | undefined; displayNameTemplate?: string | undefined; staticFields?: Record | undefined; latest?: { settings?: { frequency?: string | undefined; syncField?: string | undefined; syncDelay?: string | undefined; } | undefined; lookbackPeriod?: string | undefined; timestampField?: string | undefined; } | undefined; installedComponents?: { id: string; type: \"transform\" | \"template\" | \"ingest_pipeline\"; }[] | undefined; }; }>, ",
+ "EntityManagerRouteHandlerResources",
+ ", ",
+ {
+ "pluginId": "@kbn/core-http-server",
+ "scope": "server",
+ "docId": "kibKbnCoreHttpServerPluginApi",
+ "section": "def-server.IKibanaResponse",
+ "text": "IKibanaResponse"
+ },
+ ", ",
+ {
+ "pluginId": "@kbn/server-route-repository-utils",
+ "scope": "common",
+ "docId": "kibKbnServerRouteRepositoryUtilsPluginApi",
+ "section": "def-common.DefaultRouteCreateOptions",
+ "text": "DefaultRouteCreateOptions"
+ },
+ ">; \"POST /internal/entities/definition/{id}/_reset\": ",
+ {
+ "pluginId": "@kbn/server-route-repository-utils",
+ "scope": "common",
+ "docId": "kibKbnServerRouteRepositoryUtilsPluginApi",
+ "section": "def-common.ServerRoute",
+ "text": "ServerRoute"
+ },
+ "<\"POST /internal/entities/definition/{id}/_reset\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; }, \"strip\", Zod.ZodTypeAny, { path: { id: string; }; }, { path: { id: string; }; }>, ",
+ "EntityManagerRouteHandlerResources",
+ ", ",
+ {
+ "pluginId": "@kbn/core-http-server",
+ "scope": "server",
+ "docId": "kibKbnCoreHttpServerPluginApi",
+ "section": "def-server.IKibanaResponse",
+ "text": "IKibanaResponse"
+ },
+ ", ",
+ {
+ "pluginId": "@kbn/server-route-repository-utils",
+ "scope": "common",
+ "docId": "kibKbnServerRouteRepositoryUtilsPluginApi",
+ "section": "def-common.DefaultRouteCreateOptions",
+ "text": "DefaultRouteCreateOptions"
+ },
+ ">; \"GET /internal/entities/definition/{id?}\": ",
+ {
+ "pluginId": "@kbn/server-route-repository-utils",
+ "scope": "common",
+ "docId": "kibKbnServerRouteRepositoryUtilsPluginApi",
+ "section": "def-common.ServerRoute",
+ "text": "ServerRoute"
+ },
+ "<\"GET /internal/entities/definition/{id?}\", Zod.ZodObject<{ query: Zod.ZodObject<{ page: Zod.ZodOptional; perPage: Zod.ZodOptional; includeState: Zod.ZodDefault, Zod.ZodBoolean]>, boolean, boolean | \"true\" | \"false\">>>; }, \"strip\", Zod.ZodTypeAny, { includeState: boolean; page?: number | undefined; perPage?: number | undefined; }, { page?: number | undefined; perPage?: number | undefined; includeState?: boolean | \"true\" | \"false\" | undefined; }>; path: Zod.ZodObject<{ id: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { id?: string | undefined; }, { id?: string | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { query: { includeState: boolean; page?: number | undefined; perPage?: number | undefined; }; path: { id?: string | undefined; }; }, { query: { page?: number | undefined; perPage?: number | undefined; includeState?: boolean | \"true\" | \"false\" | undefined; }; path: { id?: string | undefined; }; }>, ",
+ "EntityManagerRouteHandlerResources",
+ ", ",
+ {
+ "pluginId": "@kbn/core-http-server",
+ "scope": "server",
+ "docId": "kibKbnCoreHttpServerPluginApi",
+ "section": "def-server.IKibanaResponse",
+ "text": "IKibanaResponse"
+ },
+ ", ",
+ {
+ "pluginId": "@kbn/server-route-repository-utils",
+ "scope": "common",
+ "docId": "kibKbnServerRouteRepositoryUtilsPluginApi",
+ "section": "def-common.DefaultRouteCreateOptions",
+ "text": "DefaultRouteCreateOptions"
+ },
+ ">; \"DELETE /internal/entities/definition/{id}\": ",
+ {
+ "pluginId": "@kbn/server-route-repository-utils",
+ "scope": "common",
+ "docId": "kibKbnServerRouteRepositoryUtilsPluginApi",
+ "section": "def-common.ServerRoute",
+ "text": "ServerRoute"
+ },
+ "<\"DELETE /internal/entities/definition/{id}\", Zod.ZodObject<{ path: Zod.ZodObject<{ id: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { id: string; }, { id: string; }>; query: Zod.ZodObject<{ deleteData: Zod.ZodDefault, Zod.ZodBoolean]>, boolean, boolean | \"true\" | \"false\">>>; }, \"strip\", Zod.ZodTypeAny, { deleteData: boolean; }, { deleteData?: boolean | \"true\" | \"false\" | undefined; }>; }, \"strip\", Zod.ZodTypeAny, { query: { deleteData: boolean; }; path: { id: string; }; }, { query: { deleteData?: boolean | \"true\" | \"false\" | undefined; }; path: { id: string; }; }>, ",
+ "EntityManagerRouteHandlerResources",
+ ", ",
+ {
+ "pluginId": "@kbn/core-http-server",
+ "scope": "server",
+ "docId": "kibKbnCoreHttpServerPluginApi",
+ "section": "def-server.IKibanaResponse",
+ "text": "IKibanaResponse"
+ },
+ ", ",
+ {
+ "pluginId": "@kbn/server-route-repository-utils",
+ "scope": "common",
+ "docId": "kibKbnServerRouteRepositoryUtilsPluginApi",
+ "section": "def-common.DefaultRouteCreateOptions",
+ "text": "DefaultRouteCreateOptions"
+ },
+ ">; \"POST /internal/entities/definition\": ",
+ {
+ "pluginId": "@kbn/server-route-repository-utils",
+ "scope": "common",
+ "docId": "kibKbnServerRouteRepositoryUtilsPluginApi",
+ "section": "def-common.ServerRoute",
+ "text": "ServerRoute"
+ },
+ "<\"POST /internal/entities/definition\", Zod.ZodObject<{ query: Zod.ZodObject<{ installOnly: Zod.ZodDefault, Zod.ZodBoolean]>, boolean, boolean | \"true\" | \"false\">>>; }, \"strip\", Zod.ZodTypeAny, { installOnly: boolean; }, { installOnly?: boolean | \"true\" | \"false\" | undefined; }>; body: Zod.ZodObject<{ id: Zod.ZodString; version: Zod.ZodEffects; name: Zod.ZodString; description: Zod.ZodOptional; type: Zod.ZodString; filter: Zod.ZodOptional; indexPatterns: Zod.ZodArray; identityFields: Zod.ZodArray; }, \"strip\", Zod.ZodTypeAny, { field: string; optional: false; }, { field: string; optional: false; }>, Zod.ZodEffects]>, \"many\">; displayNameTemplate: Zod.ZodString; metadata: Zod.ZodOptional; aggregation: Zod.ZodDefault; limit: Zod.ZodDefault; lookbackPeriod: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { type: \"terms\"; limit: number; lookbackPeriod?: string | undefined; }, { type: \"terms\"; limit?: number | undefined; lookbackPeriod?: string | undefined; }>, Zod.ZodObject<{ type: Zod.ZodLiteral<\"top_value\">; sort: Zod.ZodRecord, Zod.ZodLiteral<\"desc\">]>>; lookbackPeriod: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; }, { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; }>]>>>; }, \"strip\", Zod.ZodTypeAny, { source: string; aggregation: { type: \"terms\"; limit: number; lookbackPeriod?: string | undefined; } | { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; }; destination?: string | undefined; }, { source: string; destination?: string | undefined; aggregation?: { type: \"terms\"; limit?: number | undefined; lookbackPeriod?: string | undefined; } | { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; } | undefined; }>, Zod.ZodEffects]>, { destination: string; source: string; aggregation: { type: \"terms\"; limit: number; lookbackPeriod?: string | undefined; } | { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; }; } | { destination: string; source: string; aggregation: { type: \"terms\"; limit: number; lookbackPeriod: undefined; }; }, string | { source: string; destination?: string | undefined; aggregation?: { type: \"terms\"; limit?: number | undefined; lookbackPeriod?: string | undefined; } | { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; } | undefined; }>, { destination: string; source: string; aggregation: { type: \"terms\"; limit: number; lookbackPeriod?: string | undefined; } | { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; }; } | { destination: string; source: string; aggregation: { type: \"terms\"; limit: number; lookbackPeriod: undefined; }; }, string | { source: string; destination?: string | undefined; aggregation?: { type: \"terms\"; limit?: number | undefined; lookbackPeriod?: string | undefined; } | { type: \"top_value\"; sort: Record; lookbackPeriod?: string | undefined; } | undefined; }>, \"many\">>; metrics: Zod.ZodOptional; field: Zod.ZodString; filter: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { name: string; field: string; aggregation: ",
+ {
+ "pluginId": "@kbn/entities-schema",
+ "scope": "common",
+ "docId": "kibKbnEntitiesSchemaPluginApi",
+ "section": "def-common.BasicAggregations",
+ "text": "BasicAggregations"
+ },
+ "; filter?: string | undefined; }, { name: string; field: string; aggregation: ",
+ {
+ "pluginId": "@kbn/entities-schema",
+ "scope": "common",
+ "docId": "kibKbnEntitiesSchemaPluginApi",
+ "section": "def-common.BasicAggregations",
+ "text": "BasicAggregations"
+ },
+ "; filter?: string | undefined; }>, Zod.ZodObject<{ name: Zod.ZodString; aggregation: Zod.ZodLiteral<\"doc_count\">; filter: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { name: string; aggregation: \"doc_count\"; filter?: string | undefined; }, { name: string; aggregation: \"doc_count\"; filter?: string | undefined; }>, Zod.ZodObject<{ name: Zod.ZodString; aggregation: Zod.ZodLiteral<\"percentile\">; field: Zod.ZodString; percentile: Zod.ZodNumber; filter: Zod.ZodOptional; }, \"strip\", Zod.ZodTypeAny, { name: string; field: string; percentile: number; aggregation: \"percentile\"; filter?: string | undefined; }, { name: string; field: string; percentile: number; aggregation: \"percentile\"; filter?: string | undefined; }>]>, \"many\">; equation: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { name: string; metrics: ({ name: string; field: string; aggregation: ",
+ {
+ "pluginId": "@kbn/entities-schema",
+ "scope": "common",
+ "docId": "kibKbnEntitiesSchemaPluginApi",
+ "section": "def-common.BasicAggregations",
+ "text": "BasicAggregations"
+ },
+ "; filter?: string | undefined; } | { name: string; aggregation: \"doc_count\"; filter?: string | undefined; } | { name: string; field: string; percentile: number; aggregation: \"percentile\"; filter?: string | undefined; })[]; equation: string; }, { name: string; metrics: ({ name: string; field: string; aggregation: ",
+ {
+ "pluginId": "@kbn/entities-schema",
+ "scope": "common",
+ "docId": "kibKbnEntitiesSchemaPluginApi",
+ "section": "def-common.BasicAggregations",
+ "text": "BasicAggregations"
+ },
+ "; filter?: string | undefined; } | { name: string; aggregation: \"doc_count\"; filter?: string | undefined; } | { name: string; field: string; percentile: number; aggregation: \"percentile\"; filter?: string | undefined; })[]; equation: string; }>, \"many\">>; staticFields: Zod.ZodOptional>; managed: Zod.ZodDefault>; latest: Zod.ZodObject<{ timestampField: Zod.ZodString; lookbackPeriod: Zod.ZodDefault>; settings: Zod.ZodOptional; syncDelay: Zod.ZodOptional; frequency: Zod.ZodOptional