{
+ describe('dynamic suggestions for argument values', () => {
describe('.es()', () => {
it('should show index pattern suggestions for index argument', async () => {
await monacoEditor.setCodeEditorValue('');
diff --git a/test/functional/page_objects/timelion_page.ts b/test/functional/page_objects/timelion_page.ts
index bdfde3c8145e..ba1db60bc635 100644
--- a/test/functional/page_objects/timelion_page.ts
+++ b/test/functional/page_objects/timelion_page.ts
@@ -7,13 +7,21 @@
*/
import { FtrService } from '../ftr_provider_context';
+import type { WebElementWrapper } from '../services/lib/web_element_wrapper';
export class TimelionPageObject extends FtrService {
private readonly testSubjects = this.ctx.getService('testSubjects');
+ private readonly retry = this.ctx.getService('retry');
public async getSuggestionItemsText() {
- const timelionCodeEditor = await this.testSubjects.find('timelionCodeEditor');
- const lists = await timelionCodeEditor.findAllByClassName('monaco-list-row');
+ let lists: WebElementWrapper[] = [];
+ await this.retry.try(async () => {
+ const timelionCodeEditor = await this.testSubjects.find('timelionCodeEditor');
+ lists = await timelionCodeEditor.findAllByClassName('monaco-list-row');
+ if (lists.length === 0) {
+ throw new Error('suggestion list not populated');
+ }
+ });
return await Promise.all(lists.map(async (element) => await element.getVisibleText()));
}
diff --git a/x-pack/plugins/apm/server/lib/fleet/get_apm_package_policy_definition.test.ts b/x-pack/plugins/apm/server/lib/fleet/get_apm_package_policy_definition.test.ts
new file mode 100644
index 000000000000..3940fa60a38f
--- /dev/null
+++ b/x-pack/plugins/apm/server/lib/fleet/get_apm_package_policy_definition.test.ts
@@ -0,0 +1,43 @@
+/*
+ * 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 { preprocessLegacyFields } from './get_apm_package_policy_definition';
+
+const apmServerSchema = {
+ 'apm-server.host': '0.0.0.0:8200',
+ 'apm-server.secret_token': 'asdfkjhasdf',
+ 'apm-server.read_timeout': 3600,
+ 'apm-server.rum.event_rate.limit': 100,
+ 'apm-server.rum.event_rate.lru_size': 100,
+ 'apm-server.rum.allow_service_names': 'opbeans-test',
+ 'logging.level': 'error',
+ 'queue.mem.events': 2000,
+ 'queue.mem.flush.timeout': '1s',
+ 'setup.template.settings.index.number_of_jshards': 1,
+};
+
+describe('get_apm_package_policy_definition', () => {
+ describe('preprocessLegacyFields', () => {
+ it('should replace legacy fields with supported fields', () => {
+ const result = preprocessLegacyFields({ apmServerSchema });
+ expect(result).toMatchInlineSnapshot(`
+ Object {
+ "apm-server.auth.anonymous.allow_service": "opbeans-test",
+ "apm-server.auth.anonymous.rate_limit.event_limit": 100,
+ "apm-server.auth.anonymous.rate_limit.ip_limit": 100,
+ "apm-server.auth.secret_token": "asdfkjhasdf",
+ "apm-server.host": "0.0.0.0:8200",
+ "apm-server.read_timeout": 3600,
+ "logging.level": "error",
+ "queue.mem.events": 2000,
+ "queue.mem.flush.timeout": "1s",
+ "setup.template.settings.index.number_of_jshards": 1,
+ }
+ `);
+ });
+ });
+});
diff --git a/x-pack/plugins/apm/server/lib/fleet/get_apm_package_policy_definition.ts b/x-pack/plugins/apm/server/lib/fleet/get_apm_package_policy_definition.ts
index 98b6a6489c47..df922dd18fe4 100644
--- a/x-pack/plugins/apm/server/lib/fleet/get_apm_package_policy_definition.ts
+++ b/x-pack/plugins/apm/server/lib/fleet/get_apm_package_policy_definition.ts
@@ -45,7 +45,7 @@ export function getApmPackagePolicyDefinition(
};
}
-function preprocessLegacyFields({
+export function preprocessLegacyFields({
apmServerSchema,
}: {
apmServerSchema: Record
;
@@ -64,6 +64,10 @@ function preprocessLegacyFields({
key: 'apm-server.auth.anonymous.allow_service',
legacyKey: 'apm-server.rum.allow_service_names',
},
+ {
+ key: 'apm-server.auth.secret_token',
+ legacyKey: 'apm-server.secret_token',
+ },
].forEach(({ key, legacyKey }) => {
if (!copyOfApmServerSchema[key]) {
copyOfApmServerSchema[key] = copyOfApmServerSchema[legacyKey];
diff --git a/x-pack/plugins/apm/server/lib/fleet/get_unsupported_apm_server_schema.test.ts b/x-pack/plugins/apm/server/lib/fleet/get_unsupported_apm_server_schema.test.ts
new file mode 100644
index 000000000000..cdc56ba9794f
--- /dev/null
+++ b/x-pack/plugins/apm/server/lib/fleet/get_unsupported_apm_server_schema.test.ts
@@ -0,0 +1,58 @@
+/*
+ * 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 { SavedObjectsClientContract } from 'kibana/server';
+import { getUnsupportedApmServerSchema } from './get_unsupported_apm_server_schema';
+
+const apmServerSchema = {
+ 'apm-server.host': '0.0.0.0:8200',
+ 'apm-server.secret_token': 'asdfkjhasdf',
+ 'apm-server.read_timeout': 3600,
+ 'apm-server.rum.event_rate.limit': 100,
+ 'apm-server.rum.event_rate.lru_size': 100,
+ 'apm-server.rum.allow_service_names': 'opbeans-test',
+ 'logging.level': 'error',
+ 'queue.mem.events': 2000,
+ 'queue.mem.flush.timeout': '1s',
+ 'setup.template.settings.index.number_of_jshards': 1,
+};
+
+const mockSavaedObectsClient = {
+ get: () => ({
+ attributes: { schemaJson: JSON.stringify(apmServerSchema) },
+ }),
+} as unknown as SavedObjectsClientContract;
+
+describe('get_unsupported_apm_server_schema', () => {
+ describe('getUnsupportedApmServerSchema', () => {
+ it('should return key-value pairs of unsupported configs', async () => {
+ const result = await getUnsupportedApmServerSchema({
+ savedObjectsClient: mockSavaedObectsClient,
+ });
+ expect(result).toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "key": "logging.level",
+ "value": "error",
+ },
+ Object {
+ "key": "queue.mem.events",
+ "value": 2000,
+ },
+ Object {
+ "key": "queue.mem.flush.timeout",
+ "value": "1s",
+ },
+ Object {
+ "key": "setup.template.settings.index.number_of_jshards",
+ "value": 1,
+ },
+ ]
+ `);
+ });
+ });
+});
diff --git a/x-pack/plugins/apm/server/lib/fleet/get_unsupported_apm_server_schema.ts b/x-pack/plugins/apm/server/lib/fleet/get_unsupported_apm_server_schema.ts
index 5fec3c94cf7a..2ced15245b59 100644
--- a/x-pack/plugins/apm/server/lib/fleet/get_unsupported_apm_server_schema.ts
+++ b/x-pack/plugins/apm/server/lib/fleet/get_unsupported_apm_server_schema.ts
@@ -10,7 +10,10 @@ import {
APM_SERVER_SCHEMA_SAVED_OBJECT_TYPE,
APM_SERVER_SCHEMA_SAVED_OBJECT_ID,
} from '../../../common/apm_saved_object_constants';
-import { apmConfigMapping } from './get_apm_package_policy_definition';
+import {
+ apmConfigMapping,
+ preprocessLegacyFields,
+} from './get_apm_package_policy_definition';
export async function getUnsupportedApmServerSchema({
savedObjectsClient,
@@ -24,7 +27,10 @@ export async function getUnsupportedApmServerSchema({
const apmServerSchema: Record = JSON.parse(
(attributes as { schemaJson: string }).schemaJson
);
- return Object.entries(apmServerSchema)
+ const preprocessedApmServerSchema = preprocessLegacyFields({
+ apmServerSchema,
+ });
+ return Object.entries(preprocessedApmServerSchema)
.filter(([name]) => !(name in apmConfigMapping))
.map(([key, value]) => ({ key, value }));
}
diff --git a/x-pack/plugins/cases/public/components/configure_cases/index.test.tsx b/x-pack/plugins/cases/public/components/configure_cases/index.test.tsx
index 1fed1d90689b..990d44584cf0 100644
--- a/x-pack/plugins/cases/public/components/configure_cases/index.test.tsx
+++ b/x-pack/plugins/cases/public/components/configure_cases/index.test.tsx
@@ -47,6 +47,7 @@ describe('ConfigureCases', () => {
iconClass: 'logoSecurity',
});
});
+
beforeEach(() => {
useActionTypesMock.mockImplementation(() => useActionTypesResponse);
});
@@ -451,150 +452,149 @@ describe('ConfigureCases', () => {
).toBe('Update My Connector 2');
});
});
-});
-// Failing: See https://github.com/elastic/kibana/issues/115366
-describe.skip('closure options', () => {
- let wrapper: ReactWrapper;
- let persistCaseConfigure: jest.Mock;
+ describe('closure options', () => {
+ let wrapper: ReactWrapper;
+ let persistCaseConfigure: jest.Mock;
- beforeEach(() => {
- persistCaseConfigure = jest.fn();
- useCaseConfigureMock.mockImplementation(() => ({
- ...useCaseConfigureResponse,
- mapping: null,
- closureType: 'close-by-user',
- connector: {
- id: 'servicenow-1',
- name: 'My connector',
- type: ConnectorTypes.serviceNowITSM,
- fields: null,
- },
- currentConfiguration: {
+ beforeEach(() => {
+ persistCaseConfigure = jest.fn();
+ useCaseConfigureMock.mockImplementation(() => ({
+ ...useCaseConfigureResponse,
+ mapping: null,
+ closureType: 'close-by-user',
connector: {
- id: 'My connector',
+ id: 'servicenow-1',
name: 'My connector',
- type: ConnectorTypes.jira,
+ type: ConnectorTypes.serviceNowITSM,
fields: null,
},
- closureType: 'close-by-user',
- },
- persistCaseConfigure,
- }));
- useConnectorsMock.mockImplementation(() => useConnectorsResponse);
- useGetUrlSearchMock.mockImplementation(() => searchURL);
+ currentConfiguration: {
+ connector: {
+ id: 'My connector',
+ name: 'My connector',
+ type: ConnectorTypes.jira,
+ fields: null,
+ },
+ closureType: 'close-by-user',
+ },
+ persistCaseConfigure,
+ }));
+ useConnectorsMock.mockImplementation(() => useConnectorsResponse);
+ useGetUrlSearchMock.mockImplementation(() => searchURL);
- wrapper = mount(, {
- wrappingComponent: TestProviders,
+ wrapper = mount(, {
+ wrappingComponent: TestProviders,
+ });
});
- });
- test('it submits the configuration correctly when changing closure type', () => {
- wrapper.find('input[id="close-by-pushing"]').simulate('change');
- wrapper.update();
+ test('it submits the configuration correctly when changing closure type', () => {
+ wrapper.find('input[id="close-by-pushing"]').simulate('change');
+ wrapper.update();
- expect(persistCaseConfigure).toHaveBeenCalled();
- expect(persistCaseConfigure).toHaveBeenCalledWith({
- connector: {
- id: 'servicenow-1',
- name: 'My connector',
- type: ConnectorTypes.serviceNowITSM,
- fields: null,
- },
- closureType: 'close-by-pushing',
+ expect(persistCaseConfigure).toHaveBeenCalled();
+ expect(persistCaseConfigure).toHaveBeenCalledWith({
+ connector: {
+ id: 'servicenow-1',
+ name: 'My connector',
+ type: ConnectorTypes.serviceNowITSM,
+ fields: null,
+ },
+ closureType: 'close-by-pushing',
+ });
});
});
-});
-describe('user interactions', () => {
- beforeEach(() => {
- useCaseConfigureMock.mockImplementation(() => ({
- ...useCaseConfigureResponse,
- mapping: null,
- closureType: 'close-by-user',
- connector: {
- id: 'resilient-2',
- name: 'unchanged',
- type: ConnectorTypes.resilient,
- fields: null,
- },
- currentConfiguration: {
+ describe('user interactions', () => {
+ beforeEach(() => {
+ useCaseConfigureMock.mockImplementation(() => ({
+ ...useCaseConfigureResponse,
+ mapping: null,
+ closureType: 'close-by-user',
connector: {
id: 'resilient-2',
name: 'unchanged',
- type: ConnectorTypes.serviceNowITSM,
+ type: ConnectorTypes.resilient,
fields: null,
},
- closureType: 'close-by-user',
- },
- }));
- useConnectorsMock.mockImplementation(() => useConnectorsResponse);
- useGetUrlSearchMock.mockImplementation(() => searchURL);
- });
-
- test('it show the add flyout when pressing the add connector button', async () => {
- const wrapper = mount(, {
- wrappingComponent: TestProviders,
+ currentConfiguration: {
+ connector: {
+ id: 'resilient-2',
+ name: 'unchanged',
+ type: ConnectorTypes.serviceNowITSM,
+ fields: null,
+ },
+ closureType: 'close-by-user',
+ },
+ }));
+ useConnectorsMock.mockImplementation(() => useConnectorsResponse);
+ useGetUrlSearchMock.mockImplementation(() => searchURL);
});
- wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click');
- wrapper.find('button[data-test-subj="dropdown-connector-add-connector"]').simulate('click');
+ test('it show the add flyout when pressing the add connector button', async () => {
+ const wrapper = mount(, {
+ wrappingComponent: TestProviders,
+ });
- await waitFor(() => {
- wrapper.update();
- expect(wrapper.find('ConnectorAddFlyout').exists()).toBe(true);
- expect(wrapper.find('ConnectorAddFlyout').prop('actionTypes')).toEqual([
- expect.objectContaining({
- id: '.servicenow',
- }),
- expect.objectContaining({
- id: '.jira',
- }),
- expect.objectContaining({
- id: '.resilient',
- }),
- expect.objectContaining({
- id: '.servicenow-sir',
- }),
- ]);
+ wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click');
+ wrapper.find('button[data-test-subj="dropdown-connector-add-connector"]').simulate('click');
+
+ await waitFor(() => {
+ wrapper.update();
+ expect(wrapper.find('ConnectorAddFlyout').exists()).toBe(true);
+ expect(wrapper.find('ConnectorAddFlyout').prop('actionTypes')).toEqual([
+ expect.objectContaining({
+ id: '.servicenow',
+ }),
+ expect.objectContaining({
+ id: '.jira',
+ }),
+ expect.objectContaining({
+ id: '.resilient',
+ }),
+ expect.objectContaining({
+ id: '.servicenow-sir',
+ }),
+ ]);
+ });
});
- });
- test('it show the edit flyout when pressing the update connector button', async () => {
- const actionType = actionTypeRegistryMock.createMockActionTypeModel({
- id: '.resilient',
- validateConnector: () => {
- return Promise.resolve({});
- },
- validateParams: () => {
- const validationResult = { errors: {} };
- return Promise.resolve(validationResult);
- },
- actionConnectorFields: null,
- });
-
- useKibanaMock().services.triggersActionsUi.actionTypeRegistry.get = jest
- .fn()
- .mockReturnValue(actionType);
- useKibanaMock().services.triggersActionsUi.actionTypeRegistry.has = jest
- .fn()
- .mockReturnValue(true);
-
- const wrapper = mount(, {
- wrappingComponent: TestProviders,
- });
- wrapper
- .find('button[data-test-subj="case-configure-update-selected-connector-button"]')
- .simulate('click');
-
- await waitFor(() => {
- wrapper.update();
- expect(wrapper.find('ConnectorEditFlyout').exists()).toBe(true);
- expect(wrapper.find('ConnectorEditFlyout').prop('initialConnector')).toEqual(connectors[1]);
- });
+ test('it show the edit flyout when pressing the update connector button', async () => {
+ const actionType = actionTypeRegistryMock.createMockActionTypeModel({
+ id: '.resilient',
+ validateConnector: () => {
+ return Promise.resolve({});
+ },
+ validateParams: () => {
+ const validationResult = { errors: {} };
+ return Promise.resolve(validationResult);
+ },
+ actionConnectorFields: null,
+ });
+
+ useKibanaMock().services.triggersActionsUi.actionTypeRegistry.get = jest
+ .fn()
+ .mockReturnValue(actionType);
+ useKibanaMock().services.triggersActionsUi.actionTypeRegistry.has = jest
+ .fn()
+ .mockReturnValue(true);
+
+ const wrapper = mount(, {
+ wrappingComponent: TestProviders,
+ });
+ wrapper
+ .find('button[data-test-subj="case-configure-update-selected-connector-button"]')
+ .simulate('click');
+
+ await waitFor(() => {
+ wrapper.update();
+ expect(wrapper.find('ConnectorEditFlyout').exists()).toBe(true);
+ expect(wrapper.find('ConnectorEditFlyout').prop('initialConnector')).toEqual(connectors[1]);
+ });
- expect(
- wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists()
- ).toBeFalsy();
+ expect(
+ wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists()
+ ).toBeFalsy();
+ });
});
});
diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/integration_preference.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/integration_preference.tsx
index 9c9027fb94ac..fa9b9a7ed190 100644
--- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/integration_preference.tsx
+++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/integration_preference.tsx
@@ -22,6 +22,8 @@ import {
EuiFlexItem,
} from '@elastic/eui';
+import { useStartServices } from '../../../hooks';
+
export type IntegrationPreferenceType = 'recommended' | 'beats' | 'agent';
interface Option {
@@ -34,23 +36,6 @@ export interface Props {
onChange: (type: IntegrationPreferenceType) => void;
}
-const link = (
-
-
-
-);
-
-const title = (
-
-);
-
const recommendedTooltip = (
{
const [idSelected, setIdSelected] = React.useState(initialType);
+
+ const { docLinks } = useStartServices();
+
+ const link = (
+
+
+
+ );
+
+ const title = (
+
+ );
+
const radios = options.map((option) => ({
id: option.type,
value: option.type,
diff --git a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap
deleted file mode 100644
index 8433d98c232d..000000000000
--- a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap
+++ /dev/null
@@ -1,44 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`SearchBar correctly filters and sorts results 1`] = `
-Array [
- "Canvas • Kibana",
- "Discover • Kibana",
- "Graph • Kibana",
-]
-`;
-
-exports[`SearchBar correctly filters and sorts results 2`] = `
-Array [
- "Discover • Kibana",
- "My Dashboard • Test",
-]
-`;
-
-exports[`SearchBar only display results from the last search 1`] = `
-Array [
- "Visualize • Kibana",
- "Map • Kibana",
-]
-`;
-
-exports[`SearchBar only display results from the last search 2`] = `
-Array [
- "Visualize • Kibana",
- "Map • Kibana",
-]
-`;
-
-exports[`SearchBar supports keyboard shortcuts 1`] = `
-
-`;
diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx
index c8bd54540e6a..dd7b1f266694 100644
--- a/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx
+++ b/x-pack/plugins/global_search_bar/public/components/search_bar.test.tsx
@@ -6,15 +6,21 @@
*/
import React from 'react';
-import { waitFor, act } from '@testing-library/react';
-import { ReactWrapper } from 'enzyme';
+import { act, render, screen, fireEvent } from '@testing-library/react';
import { of, BehaviorSubject } from 'rxjs';
import { filter, map } from 'rxjs/operators';
-import { mountWithIntl } from '@kbn/test/jest';
import { applicationServiceMock } from '../../../../../src/core/public/mocks';
import { globalSearchPluginMock } from '../../../global_search/public/mocks';
import { GlobalSearchBatchedResults, GlobalSearchResult } from '../../../global_search/public';
import { SearchBar } from './search_bar';
+import { __IntlProvider as IntlProvider } from '@kbn/i18n/react';
+
+jest.mock(
+ 'react-virtualized-auto-sizer',
+ () =>
+ ({ children }: any) =>
+ children({ height: 600, width: 600 })
+);
type Result = { id: string; type: string } | string;
@@ -36,9 +42,7 @@ const createResult = (result: Result): GlobalSearchResult => {
const createBatch = (...results: Result[]): GlobalSearchBatchedResults => ({
results: results.map(createResult),
});
-
-const getSelectableProps: any = (component: any) => component.find('EuiSelectable').props();
-const getSearchProps: any = (component: any) => component.find('EuiFieldSearch').props();
+jest.useFakeTimers();
describe('SearchBar', () => {
let searchService: ReturnType;
@@ -46,31 +50,37 @@ describe('SearchBar', () => {
const basePathUrl = '/plugins/globalSearchBar/assets/';
const darkMode = false;
- let component: ReactWrapper;
-
beforeEach(() => {
applications = applicationServiceMock.createStartContract();
searchService = globalSearchPluginMock.createStartContract();
- jest.useFakeTimers();
});
- const triggerFocus = () => {
- component.find('input[data-test-subj="nav-search-input"]').simulate('focus');
- };
-
const update = () => {
act(() => {
jest.runAllTimers();
});
- component.update();
};
- const simulateTypeChar = async (text: string) => {
- await waitFor(() => getSearchProps(component).onInput({ currentTarget: { value: text } }));
+ const focusAndUpdate = async () => {
+ await act(async () => {
+ (await screen.findByTestId('nav-search-input')).focus();
+ jest.runAllTimers();
+ });
};
- const getDisplayedOptionsTitle = () => {
- return getSelectableProps(component).options.map((option: any) => option.title);
+ const simulateTypeChar = (text: string) => {
+ fireEvent.input(screen.getByTestId('nav-search-input'), { target: { value: text } });
+ act(() => {
+ jest.runAllTimers();
+ });
+ };
+
+ const assertSearchResults = async (list: string[]) => {
+ for (let i = 0; i < list.length; i++) {
+ expect(await screen.findByTitle(list[i])).toBeInTheDocument();
+ }
+
+ expect(await screen.findAllByTestId('nav-search-option')).toHaveLength(list.length);
};
it('correctly filters and sorts results', async () => {
@@ -83,53 +93,52 @@ describe('SearchBar', () => {
)
.mockReturnValueOnce(of(createBatch('Discover', { id: 'My Dashboard', type: 'test' })));
- component = mountWithIntl(
-
+ render(
+
+
+
);
expect(searchService.find).toHaveBeenCalledTimes(0);
- triggerFocus();
- update();
+ await focusAndUpdate();
expect(searchService.find).toHaveBeenCalledTimes(1);
expect(searchService.find).toHaveBeenCalledWith({}, {});
- expect(getDisplayedOptionsTitle()).toMatchSnapshot();
+ await assertSearchResults(['Canvas • Kibana', 'Discover • Kibana', 'Graph • Kibana']);
- await simulateTypeChar('d');
- update();
+ simulateTypeChar('d');
- expect(getDisplayedOptionsTitle()).toMatchSnapshot();
+ await assertSearchResults(['Discover • Kibana', 'My Dashboard • Test']);
expect(searchService.find).toHaveBeenCalledTimes(2);
- expect(searchService.find).toHaveBeenCalledWith({ term: 'd' }, {});
+ expect(searchService.find).toHaveBeenLastCalledWith({ term: 'd' }, {});
});
- it('supports keyboard shortcuts', () => {
- mountWithIntl(
- ,
- { attachTo: document.body }
+ it('supports keyboard shortcuts', async () => {
+ render(
+
+
+
);
+ act(() => {
+ fireEvent.keyDown(window, { key: '/', ctrlKey: true, metaKey: true });
+ });
- const searchEvent = new KeyboardEvent('keydown', {
- key: '/',
- ctrlKey: true,
- metaKey: true,
- } as any);
- window.dispatchEvent(searchEvent);
+ const inputElement = await screen.findByTestId('nav-search-input');
- expect(document.activeElement).toMatchSnapshot();
+ expect(document.activeElement).toEqual(inputElement);
});
it('only display results from the last search', async () => {
@@ -144,30 +153,29 @@ describe('SearchBar', () => {
searchService.find.mockReturnValueOnce(firstSearch).mockReturnValueOnce(secondSearch);
- component = mountWithIntl(
-
+ render(
+
+
+
);
- triggerFocus();
- update();
+ await focusAndUpdate();
expect(searchService.find).toHaveBeenCalledTimes(1);
-
- await simulateTypeChar('d');
- update();
-
- expect(getDisplayedOptionsTitle()).toMatchSnapshot();
+ //
+ simulateTypeChar('d');
+ await assertSearchResults(['Visualize • Kibana', 'Map • Kibana']);
firstSearchTrigger.next(true);
update();
- expect(getDisplayedOptionsTitle()).toMatchSnapshot();
+ await assertSearchResults(['Visualize • Kibana', 'Map • Kibana']);
});
});
diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx
index c459b2c04568..97e19bab3d2d 100644
--- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx
+++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx
@@ -180,6 +180,7 @@ export function SearchBar({
darkMode,
}: Props) {
const isMounted = useMountedState();
+ const [initialLoad, setInitialLoad] = useState(false);
const [searchValue, setSearchValue] = useState('');
const [searchTerm, setSearchTerm] = useState('');
const [searchRef, setSearchRef] = useState(null);
@@ -190,12 +191,14 @@ export function SearchBar({
const UNKNOWN_TAG_ID = '__unknown__';
useEffect(() => {
- const fetch = async () => {
- const types = await globalSearch.getSearchableTypes();
- setSearchableTypes(types);
- };
- fetch();
- }, [globalSearch]);
+ if (initialLoad) {
+ const fetch = async () => {
+ const types = await globalSearch.getSearchableTypes();
+ setSearchableTypes(types);
+ };
+ fetch();
+ }
+ }, [globalSearch, initialLoad]);
const loadSuggestions = useCallback(
(term: string) => {
@@ -234,75 +237,80 @@ export function SearchBar({
useDebounce(
() => {
- // cancel pending search if not completed yet
- if (searchSubscription.current) {
- searchSubscription.current.unsubscribe();
- searchSubscription.current = null;
- }
+ if (initialLoad) {
+ // cancel pending search if not completed yet
+ if (searchSubscription.current) {
+ searchSubscription.current.unsubscribe();
+ searchSubscription.current = null;
+ }
+
+ const suggestions = loadSuggestions(searchValue);
+
+ let aggregatedResults: GlobalSearchResult[] = [];
+ if (searchValue.length !== 0) {
+ trackUiMetric(METRIC_TYPE.COUNT, 'search_request');
+ }
+
+ const rawParams = parseSearchParams(searchValue);
+ const tagIds =
+ taggingApi && rawParams.filters.tags
+ ? rawParams.filters.tags.map(
+ (tagName) => taggingApi.ui.getTagIdFromName(tagName) ?? UNKNOWN_TAG_ID
+ )
+ : undefined;
+ const searchParams: GlobalSearchFindParams = {
+ term: rawParams.term,
+ types: rawParams.filters.types,
+ tags: tagIds,
+ };
+ // TODO technically a subtle bug here
+ // this term won't be set until the next time the debounce is fired
+ // so the SearchOption won't highlight anything if only one call is fired
+ // in practice, this is hard to spot, unlikely to happen, and is a negligible issue
+ setSearchTerm(rawParams.term ?? '');
+
+ searchSubscription.current = globalSearch.find(searchParams, {}).subscribe({
+ next: ({ results }) => {
+ if (searchValue.length > 0) {
+ aggregatedResults = [...results, ...aggregatedResults].sort(sortByScore);
+ setOptions(aggregatedResults, suggestions, searchParams.tags);
+ return;
+ }
+
+ // if searchbar is empty, filter to only applications and sort alphabetically
+ results = results.filter(({ type }: GlobalSearchResult) => type === 'application');
+
+ aggregatedResults = [...results, ...aggregatedResults].sort(sortByTitle);
- const suggestions = loadSuggestions(searchValue);
-
- let aggregatedResults: GlobalSearchResult[] = [];
- if (searchValue.length !== 0) {
- trackUiMetric(METRIC_TYPE.COUNT, 'search_request');
- }
-
- const rawParams = parseSearchParams(searchValue);
- const tagIds =
- taggingApi && rawParams.filters.tags
- ? rawParams.filters.tags.map(
- (tagName) => taggingApi.ui.getTagIdFromName(tagName) ?? UNKNOWN_TAG_ID
- )
- : undefined;
- const searchParams: GlobalSearchFindParams = {
- term: rawParams.term,
- types: rawParams.filters.types,
- tags: tagIds,
- };
- // TODO technically a subtle bug here
- // this term won't be set until the next time the debounce is fired
- // so the SearchOption won't highlight anything if only one call is fired
- // in practice, this is hard to spot, unlikely to happen, and is a negligible issue
- setSearchTerm(rawParams.term ?? '');
-
- searchSubscription.current = globalSearch.find(searchParams, {}).subscribe({
- next: ({ results }) => {
- if (searchValue.length > 0) {
- aggregatedResults = [...results, ...aggregatedResults].sort(sortByScore);
setOptions(aggregatedResults, suggestions, searchParams.tags);
- return;
- }
-
- // if searchbar is empty, filter to only applications and sort alphabetically
- results = results.filter(({ type }: GlobalSearchResult) => type === 'application');
-
- aggregatedResults = [...results, ...aggregatedResults].sort(sortByTitle);
-
- setOptions(aggregatedResults, suggestions, searchParams.tags);
- },
- error: () => {
- // Not doing anything on error right now because it'll either just show the previous
- // results or empty results which is basically what we want anyways
- trackUiMetric(METRIC_TYPE.COUNT, 'unhandled_error');
- },
- complete: () => {},
- });
+ },
+ error: () => {
+ // Not doing anything on error right now because it'll either just show the previous
+ // results or empty results which is basically what we want anyways
+ trackUiMetric(METRIC_TYPE.COUNT, 'unhandled_error');
+ },
+ complete: () => {},
+ });
+ }
},
350,
- [searchValue, loadSuggestions]
+ [searchValue, loadSuggestions, searchableTypes, initialLoad]
);
- const onKeyDown = (event: KeyboardEvent) => {
- if (event.key === '/' && (isMac ? event.metaKey : event.ctrlKey)) {
- event.preventDefault();
- trackUiMetric(METRIC_TYPE.COUNT, 'shortcut_used');
- if (searchRef) {
- searchRef.focus();
- } else if (buttonRef) {
- (buttonRef.children[0] as HTMLButtonElement).click();
+ const onKeyDown = useCallback(
+ (event: KeyboardEvent) => {
+ if (event.key === '/' && (isMac ? event.metaKey : event.ctrlKey)) {
+ event.preventDefault();
+ trackUiMetric(METRIC_TYPE.COUNT, 'shortcut_used');
+ if (searchRef) {
+ searchRef.focus();
+ } else if (buttonRef) {
+ (buttonRef.children[0] as HTMLButtonElement).click();
+ }
}
- }
- };
+ },
+ [buttonRef, searchRef, trackUiMetric]
+ );
const onChange = (selection: EuiSelectableTemplateSitewideOption[]) => {
const selected = selection.find(({ checked }) => checked === 'on');
@@ -411,6 +419,7 @@ export function SearchBar({
}),
onFocus: () => {
trackUiMetric(METRIC_TYPE.COUNT, 'search_focus');
+ setInitialLoad(true);
},
}}
popoverProps={{
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/form_validation/timing.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/form_validation/timing.test.ts
index be4f99103b31..4c553cac0230 100644
--- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/form_validation/timing.test.ts
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/form_validation/timing.test.ts
@@ -12,7 +12,8 @@ import { PhaseWithTiming } from '../../../../common/types';
import { setupEnvironment } from '../../helpers';
import { setupValidationTestBed, ValidationTestBed } from './validation.helpers';
-describe(' timing validation', () => {
+// FLAKY: https://github.com/elastic/kibana/issues/115307
+describe.skip(' timing validation', () => {
let testBed: ValidationTestBed;
let actions: ValidationTestBed['actions'];
const { server, httpRequestsMockHelpers } = setupEnvironment();
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_list/components/policy_table.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_list/components/policy_table.tsx
index d6d030c3ec73..61ce87860d89 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_list/components/policy_table.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_list/components/policy_table.tsx
@@ -191,7 +191,9 @@ export const PolicyTable: React.FunctionComponent = ({ policies }) => {
direction: 'asc',
},
}}
- search={{ box: { incremental: true } }}
+ search={{
+ box: { incremental: true, 'data-test-subj': 'ilmSearchBar' },
+ }}
tableLayout="auto"
items={policies}
columns={columns}
diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/forecasting_modal/forecasts_list.js b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/forecasting_modal/forecasts_list.js
index 1854982c8db0..7f9fcc7bc551 100644
--- a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/forecasting_modal/forecasts_list.js
+++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/forecasting_modal/forecasts_list.js
@@ -78,6 +78,12 @@ function getColumns(viewForecast) {
// TODO - add in ml-info-icon to the h3 element,
// then remove tooltip and inline style.
export function ForecastsList({ forecasts, viewForecast }) {
+ const getRowProps = (item) => {
+ return {
+ 'data-test-subj': `mlForecastsListRow row-${item.rowId}`,
+ };
+ };
+
return (
);
diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.js b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.js
index 87131583e44e..cad5bb68fb62 100644
--- a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.js
+++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.js
@@ -547,9 +547,18 @@ class TimeseriesChartIntl extends Component {
// Create the path elements for the forecast value line and bounds area.
if (contextForecastData) {
- fcsGroup.append('path').attr('class', 'area forecast');
- fcsGroup.append('path').attr('class', 'values-line forecast');
- fcsGroup.append('g').attr('class', 'focus-chart-markers forecast');
+ fcsGroup
+ .append('path')
+ .attr('class', 'area forecast')
+ .attr('data-test-subj', 'mlForecastArea');
+ fcsGroup
+ .append('path')
+ .attr('class', 'values-line forecast')
+ .attr('data-test-subj', 'mlForecastValuesline');
+ fcsGroup
+ .append('g')
+ .attr('class', 'focus-chart-markers forecast')
+ .attr('data-test-subj', 'mlForecastMarkers');
}
fcsGroup
diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js
index 9b8770350909..e4d7fc457de0 100644
--- a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js
+++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js
@@ -1170,9 +1170,13 @@ export class TimeSeriesExplorer extends React.Component {
+ {i18n.translate('xpack.ml.timeSeriesExplorer.showForecastLabel', {
+ defaultMessage: 'show forecast',
+ })}
+
+ }
checked={showForecast}
onChange={this.toggleShowForecastHandler}
/>
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.tsx
index 496e7a10f9c4..eca18f0eb0dd 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.tsx
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.tsx
@@ -13,6 +13,8 @@ import {
EuiListGroup,
EuiListGroupItem,
EuiBadge,
+ EuiText,
+ EuiLoadingSpinner,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
@@ -33,7 +35,7 @@ export function ReportMetricOptions({ seriesId, series, seriesConfig }: Props) {
const [showOptions, setShowOptions] = useState(false);
const metricOptions = seriesConfig?.metricOptions;
- const { indexPatterns } = useAppIndexPatternContext();
+ const { indexPatterns, loading } = useAppIndexPatternContext();
const onChange = (value?: string) => {
setSeries(seriesId, {
@@ -78,6 +80,10 @@ export function ReportMetricOptions({ seriesId, series, seriesConfig }: Props) {
};
});
+ if (!indexPattern && !loading) {
+ return {NO_DATA_AVAILABLE};
+ }
+
return (
<>
{!series.selectedMetricField && (
@@ -88,6 +94,7 @@ export function ReportMetricOptions({ seriesId, series, seriesConfig }: Props) {
onClick={() => setShowOptions((prevState) => !prevState)}
fill
size="s"
+ isLoading={!indexPattern && loading}
>
{SELECT_REPORT_METRIC_LABEL}
@@ -107,19 +114,23 @@ export function ReportMetricOptions({ seriesId, series, seriesConfig }: Props) {
)}
- {series.selectedMetricField && (
- onChange(undefined)}
- iconOnClickAriaLabel={REMOVE_REPORT_METRIC_LABEL}
- >
- {
- seriesConfig?.metricOptions?.find((option) => option.id === series.selectedMetricField)
- ?.label
- }
-
- )}
+ {series.selectedMetricField &&
+ (indexPattern && !loading ? (
+ onChange(undefined)}
+ iconOnClickAriaLabel={REMOVE_REPORT_METRIC_LABEL}
+ >
+ {
+ seriesConfig?.metricOptions?.find(
+ (option) => option.id === series.selectedMetricField
+ )?.label
+ }
+
+ ) : (
+
+ ))}
>
);
}
@@ -137,3 +148,7 @@ const REMOVE_REPORT_METRIC_LABEL = i18n.translate(
defaultMessage: 'Remove report metric',
}
);
+
+const NO_DATA_AVAILABLE = i18n.translate('xpack.observability.expView.seriesEditor.noData', {
+ defaultMessage: 'No data available',
+});
diff --git a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts
index 7677f37702f0..7b4cc2008a67 100644
--- a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts
+++ b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts
@@ -28,7 +28,8 @@ type SetupServerReturn = UnwrapPromise>;
const devtoolMessage = 'DevTools listening on (ws://localhost:4000)';
const fontNotFoundMessage = 'Could not find the default font';
-describe('POST /diagnose/browser', () => {
+// FLAKY: https://github.com/elastic/kibana/issues/89369
+describe.skip('POST /diagnose/browser', () => {
jest.setTimeout(6000);
const reportingSymbol = Symbol('reporting');
const mockLogger = createMockLevelLogger();
diff --git a/x-pack/plugins/reporting/server/routes/lib/request_handler.ts b/x-pack/plugins/reporting/server/routes/lib/request_handler.ts
index a87f5c291303..2100c4c3c43a 100644
--- a/x-pack/plugins/reporting/server/routes/lib/request_handler.ts
+++ b/x-pack/plugins/reporting/server/routes/lib/request_handler.ts
@@ -6,6 +6,7 @@
*/
import Boom from '@hapi/boom';
+import { i18n } from '@kbn/i18n';
import { KibanaRequest, KibanaResponseFactory } from 'kibana/server';
import { ReportingCore } from '../..';
import { API_BASE_URL } from '../../../common/constants';
@@ -153,7 +154,13 @@ export class RequestHandler {
});
}
- // unknown error, can't convert to 4xx
- throw err;
+ return this.res.customError({
+ statusCode: 500,
+ body:
+ err?.message ||
+ i18n.translate('xpack.reporting.errorHandler.unknownError', {
+ defaultMessage: 'Unknown error',
+ }),
+ });
}
}
diff --git a/x-pack/plugins/reporting/server/routes/management/jobs.test.ts b/x-pack/plugins/reporting/server/routes/management/jobs.test.ts
index 02a0ddc94a04..a54be44258ed 100644
--- a/x-pack/plugins/reporting/server/routes/management/jobs.test.ts
+++ b/x-pack/plugins/reporting/server/routes/management/jobs.test.ts
@@ -178,6 +178,36 @@ describe('GET /api/reporting/jobs/download', () => {
await supertest(httpSetup.server.listener).get('/api/reporting/jobs/download/poo').expect(401);
});
+ it(`returns job's info`, async () => {
+ mockEsClient.search.mockResolvedValueOnce({
+ body: getHits({
+ jobtype: 'base64EncodedJobType',
+ payload: {}, // payload is irrelevant
+ }),
+ } as any);
+
+ registerJobInfoRoutes(core);
+
+ await server.start();
+
+ await supertest(httpSetup.server.listener).get('/api/reporting/jobs/info/test').expect(200);
+ });
+
+ it(`returns 403 if a user cannot view a job's info`, async () => {
+ mockEsClient.search.mockResolvedValueOnce({
+ body: getHits({
+ jobtype: 'customForbiddenJobType',
+ payload: {}, // payload is irrelevant
+ }),
+ } as any);
+
+ registerJobInfoRoutes(core);
+
+ await server.start();
+
+ await supertest(httpSetup.server.listener).get('/api/reporting/jobs/info/test').expect(403);
+ });
+
it('when a job is incomplete', async () => {
mockEsClient.search.mockResolvedValueOnce({
body: getHits({
diff --git a/x-pack/plugins/reporting/server/routes/management/jobs.ts b/x-pack/plugins/reporting/server/routes/management/jobs.ts
index 99c317453ca0..54fc13ffbb61 100644
--- a/x-pack/plugins/reporting/server/routes/management/jobs.ts
+++ b/x-pack/plugins/reporting/server/routes/management/jobs.ts
@@ -5,8 +5,8 @@
* 2.0.
*/
-import Boom from '@hapi/boom';
import { schema } from '@kbn/config-schema';
+import { i18n } from '@kbn/i18n';
import { ReportingCore } from '../../';
import { ROUTE_TAG_CAN_REDIRECT } from '../../../../security/server';
import { API_BASE_URL } from '../../../common/constants';
@@ -115,7 +115,12 @@ export function registerJobInfoRoutes(reporting: ReportingCore) {
const { jobtype: jobType } = result;
if (!jobTypes.includes(jobType)) {
- throw Boom.unauthorized(`Sorry, you are not authorized to view ${jobType} info`);
+ return res.forbidden({
+ body: i18n.translate('xpack.reporting.jobsQuery.infoError.unauthorizedErrorMessage', {
+ defaultMessage: 'Sorry, you are not authorized to view {jobType} info',
+ values: { jobType },
+ }),
+ });
}
return res.ok({
diff --git a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts
index 1c59e56c0466..bd95e7e94252 100644
--- a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts
+++ b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts
@@ -50,6 +50,11 @@ export const technicalRuleFieldMap = {
array: false,
required: false,
},
+ [Fields.ALERT_RISK_SCORE]: {
+ type: 'float',
+ array: false,
+ required: false,
+ },
[Fields.ALERT_WORKFLOW_STATUS]: {
type: 'keyword',
array: false,
diff --git a/x-pack/plugins/rule_registry/common/field_map/types.ts b/x-pack/plugins/rule_registry/common/field_map/types.ts
index 3ff68315e93a..d4bdd34656ec 100644
--- a/x-pack/plugins/rule_registry/common/field_map/types.ts
+++ b/x-pack/plugins/rule_registry/common/field_map/types.ts
@@ -6,5 +6,5 @@
*/
export interface FieldMap {
- [key: string]: { type: string; required?: boolean; array?: boolean };
+ [key: string]: { type: string; required?: boolean; array?: boolean; path?: string };
}
diff --git a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.ts b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.ts
index 041dfdeed42e..3798506eeacd 100644
--- a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.ts
+++ b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.ts
@@ -315,6 +315,7 @@ export class ResourceInstaller {
// @ts-expect-error
rollover_alias: primaryNamespacedAlias,
},
+ 'index.mapping.total_fields.limit': 1100,
},
mappings: {
dynamic: false,
diff --git a/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_wrapper.ts b/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_wrapper.ts
index 7dea0f917247..e575b49d1776 100644
--- a/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_wrapper.ts
+++ b/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_wrapper.ts
@@ -30,7 +30,7 @@ export const createPersistenceRuleTypeWrapper: CreatePersistenceRuleTypeWrapper
.getWriter({ namespace: options.spaceId })
.bulk({
body: alerts.flatMap((alert) => [
- { index: {} },
+ { index: { _id: alert.id } },
{
[VERSION]: ruleDataClient.kibanaVersion,
...commonRuleFields,
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts
index 2cde29ec9da6..803ff4b4d0d8 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts
@@ -46,9 +46,10 @@ describe('Alert details with unmapped fields', () => {
});
});
+ // This test needs to be updated to not look for the field in a specific row, as it prevents us from adding/removing fields
it('Displays the unmapped field on the table', () => {
const expectedUnmmappedField = {
- row: 54,
+ row: 82,
field: 'unmapped',
text: 'This is the unmapped field',
};
diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/from_alert.spec.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/from_alert.spec.ts
index 84ad93fa0894..cea290eeef17 100644
--- a/x-pack/plugins/security_solution/cypress/integration/exceptions/from_alert.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/exceptions/from_alert.spec.ts
@@ -35,7 +35,7 @@ import {
import { ALERTS_URL } from '../../urls/navigation';
import { cleanKibana } from '../../tasks/common';
-describe('From alert', () => {
+describe.skip('From alert', () => {
const NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS = '1 alert';
beforeEach(() => {
diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/from_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/from_rule.spec.ts
index ea6b6cf0186b..4af6467e5d33 100644
--- a/x-pack/plugins/security_solution/cypress/integration/exceptions/from_rule.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/exceptions/from_rule.spec.ts
@@ -35,7 +35,7 @@ import { refreshPage } from '../../tasks/security_header';
import { ALERTS_URL } from '../../urls/navigation';
import { cleanKibana } from '../../tasks/common';
-describe('From rule', () => {
+describe.skip('From rule', () => {
const NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS = '1';
beforeEach(() => {
cleanKibana();
diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_edit_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_edit_extension.tsx
index 0a912598c572..0717ca5193be 100644
--- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_edit_extension.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_edit_extension.tsx
@@ -6,7 +6,7 @@
*/
import React, { memo, useEffect, useState, useMemo } from 'react';
-import { EuiSpacer, EuiText } from '@elastic/eui';
+import { EuiCallOut, EuiLoadingSpinner, EuiSpacer, EuiText } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { useDispatch } from 'react-redux';
@@ -23,7 +23,11 @@ import { getPolicyDetailPath, getPolicyTrustedAppsPath } from '../../../../commo
import { PolicyDetailsForm } from '../policy_details_form';
import { AppAction } from '../../../../../common/store/actions';
import { usePolicyDetailsSelector } from '../policy_hooks';
-import { policyDetailsForUpdate } from '../../store/policy_details/selectors';
+import {
+ apiError,
+ policyDetails,
+ policyDetailsForUpdate,
+} from '../../store/policy_details/selectors';
import { FleetTrustedAppsCard } from './endpoint_package_custom_extension/components/fleet_trusted_apps_card';
import { LinkWithIcon } from './endpoint_package_custom_extension/components/link_with_icon';
/**
@@ -48,6 +52,8 @@ const WrappedPolicyDetailsForm = memo<{
}>(({ policyId, onChange }) => {
const dispatch = useDispatch<(a: AppAction) => void>();
const updatedPolicy = usePolicyDetailsSelector(policyDetailsForUpdate);
+ const endpointPolicyDetails = usePolicyDetailsSelector(policyDetails);
+ const endpointDetailsLoadingError = usePolicyDetailsSelector(apiError);
const { getAppUrl } = useAppUrl();
const [, setLastUpdatedPolicy] = useState(updatedPolicy);
// TODO: Remove this and related code when removing FF
@@ -185,7 +191,25 @@ const WrappedPolicyDetailsForm = memo<{
-
+ {endpointDetailsLoadingError ? (
+
+ }
+ iconType="alert"
+ color="warning"
+ data-test-subj="endpiontPolicySettingsLoadingError"
+ >
+ {endpointDetailsLoadingError.message}
+
+ ) : !endpointPolicyDetails ? (
+
+ ) : (
+
+ )}
>
) : (
diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts
index 4ef3291e1b8f..b5d4c6033e98 100644
--- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts
+++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts
@@ -41,7 +41,7 @@ import { findAllUnenrolledAgentIds } from './support/unenroll';
import { getAllEndpointPackagePolicies } from './support/endpoint_package_policies';
import { findAgentIdsByStatus } from './support/agent_status';
import { EndpointAppContextService } from '../../endpoint_app_context_services';
-import { fleetAgentStatusToEndpointHostStatus } from '../../utils';
+import { catchAndWrapError, fleetAgentStatusToEndpointHostStatus } from '../../utils';
import {
queryResponseToHostListResult,
queryResponseToHostResult,
@@ -194,7 +194,9 @@ export async function getHostMetaData(
const query = getESQueryHostMetadataByID(id);
- const response = await esClient.asCurrentUser.search