diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/__snapshots__/page_view.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/endpoint/__snapshots__/page_view.test.tsx.snap
deleted file mode 100644
index bed5ac6950a2b..0000000000000
--- a/x-pack/plugins/security_solution/public/common/components/endpoint/__snapshots__/page_view.test.tsx.snap
+++ /dev/null
@@ -1,802 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`PageView component should display body header custom element 1`] = `
-.c0.endpoint--isListView {
- padding: 0 24px;
-}
-
-.c0.endpoint--isListView .endpoint-header {
- padding: 24px;
- margin-bottom: 0;
-}
-
-.c0.endpoint--isListView .endpoint-page-content {
- border-left: none;
- border-right: none;
-}
-
-.c0.endpoint--isDetailsView .endpoint-page-content {
- padding: 0;
- border: none;
- background: none;
-}
-
-.c0 .endpoint-navTabs {
- margin-left: 12px;
-}
-
-.c0 .endpoint-header-leftSection {
- overflow: hidden;
-}
-
-
- body header
-
- }
- viewType="list"
->
-
-
-
-
-
-
-
-
-
-
-
-
-
- body content
-
-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`PageView component should display body header wrapped in EuiTitle 1`] = `
-.c0.endpoint--isListView {
- padding: 0 24px;
-}
-
-.c0.endpoint--isListView .endpoint-header {
- padding: 24px;
- margin-bottom: 0;
-}
-
-.c0.endpoint--isListView .endpoint-page-content {
- border-left: none;
- border-right: none;
-}
-
-.c0.endpoint--isDetailsView .endpoint-page-content {
- padding: 0;
- border: none;
- background: none;
-}
-
-.c0 .endpoint-navTabs {
- margin-left: 12px;
-}
-
-.c0 .endpoint-header-leftSection {
- overflow: hidden;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- body header
-
-
-
-
-
-
-
-
-
- body content
-
-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`PageView component should display header left and right 1`] = `
-.c0.endpoint--isListView {
- padding: 0 24px;
-}
-
-.c0.endpoint--isListView .endpoint-header {
- padding: 24px;
- margin-bottom: 0;
-}
-
-.c0.endpoint--isListView .endpoint-page-content {
- border-left: none;
- border-right: none;
-}
-
-.c0.endpoint--isDetailsView .endpoint-page-content {
- padding: 0;
- border: none;
- background: none;
-}
-
-.c0 .endpoint-navTabs {
- margin-left: 12px;
-}
-
-.c0 .endpoint-header-leftSection {
- overflow: hidden;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- page title
-
-
-
-
-
-
-
- right side actions
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`PageView component should display only body if not header props used 1`] = `
-.c0.endpoint--isListView {
- padding: 0 24px;
-}
-
-.c0.endpoint--isListView .endpoint-header {
- padding: 24px;
- margin-bottom: 0;
-}
-
-.c0.endpoint--isListView .endpoint-page-content {
- border-left: none;
- border-right: none;
-}
-
-.c0.endpoint--isDetailsView .endpoint-page-content {
- padding: 0;
- border: none;
- background: none;
-}
-
-.c0 .endpoint-navTabs {
- margin-left: 12px;
-}
-
-.c0 .endpoint-header-leftSection {
- overflow: hidden;
-}
-
-
-
-
-
-
-
-
-`;
-
-exports[`PageView component should display only header left 1`] = `
-.c0.endpoint--isListView {
- padding: 0 24px;
-}
-
-.c0.endpoint--isListView .endpoint-header {
- padding: 24px;
- margin-bottom: 0;
-}
-
-.c0.endpoint--isListView .endpoint-page-content {
- border-left: none;
- border-right: none;
-}
-
-.c0.endpoint--isDetailsView .endpoint-page-content {
- padding: 0;
- border: none;
- background: none;
-}
-
-.c0 .endpoint-navTabs {
- margin-left: 12px;
-}
-
-.c0 .endpoint-header-leftSection {
- overflow: hidden;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- page title
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`PageView component should display only header right but include an empty left side 1`] = `
-.c0.endpoint--isListView {
- padding: 0 24px;
-}
-
-.c0.endpoint--isListView .endpoint-header {
- padding: 24px;
- margin-bottom: 0;
-}
-
-.c0.endpoint--isListView .endpoint-page-content {
- border-left: none;
- border-right: none;
-}
-
-.c0.endpoint--isDetailsView .endpoint-page-content {
- padding: 0;
- border: none;
- background: none;
-}
-
-.c0 .endpoint-navTabs {
- margin-left: 12px;
-}
-
-.c0 .endpoint-header-leftSection {
- overflow: hidden;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- right side actions
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`PageView component should pass through EuiPage props 1`] = `
-.c0.endpoint--isListView {
- padding: 0 24px;
-}
-
-.c0.endpoint--isListView .endpoint-header {
- padding: 24px;
- margin-bottom: 0;
-}
-
-.c0.endpoint--isListView .endpoint-page-content {
- border-left: none;
- border-right: none;
-}
-
-.c0.endpoint--isDetailsView .endpoint-page-content {
- padding: 0;
- border: none;
- background: none;
-}
-
-.c0 .endpoint-navTabs {
- margin-left: 12px;
-}
-
-.c0 .endpoint-header-leftSection {
- overflow: hidden;
-}
-
-
-
-
-
-
-
-
-`;
-
-exports[`PageView component should use custom element for header left and not wrap in EuiTitle 1`] = `
-.c0.endpoint--isListView {
- padding: 0 24px;
-}
-
-.c0.endpoint--isListView .endpoint-header {
- padding: 24px;
- margin-bottom: 0;
-}
-
-.c0.endpoint--isListView .endpoint-page-content {
- border-left: none;
- border-right: none;
-}
-
-.c0.endpoint--isDetailsView .endpoint-page-content {
- padding: 0;
- border: none;
- background: none;
-}
-
-.c0 .endpoint-navTabs {
- margin-left: 12px;
-}
-
-.c0 .endpoint-header-leftSection {
- overflow: hidden;
-}
-
-
- title here
-
- }
- viewType="list"
->
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-`;
diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/page_view.test.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/page_view.test.tsx
deleted file mode 100644
index 2c14f66b64865..0000000000000
--- a/x-pack/plugins/security_solution/public/common/components/endpoint/page_view.test.tsx
+++ /dev/null
@@ -1,88 +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;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import React from 'react';
-import { mount } from 'enzyme';
-import { PageView } from './page_view';
-import { EuiThemeProvider } from '../../../../../../legacy/common/eui_styled_components';
-
-describe('PageView component', () => {
- const render = (ui: Parameters[0]) =>
- mount(ui, { wrappingComponent: EuiThemeProvider });
-
- it('should display only body if not header props used', () => {
- expect(render({'body content'})).toMatchSnapshot();
- });
- it('should display header left and right', () => {
- expect(
- render(
-
- {'body content'}
-
- )
- ).toMatchSnapshot();
- });
- it('should display only header left', () => {
- expect(
- render(
-
- {'body content'}
-
- )
- ).toMatchSnapshot();
- });
- it('should display only header right but include an empty left side', () => {
- expect(
- render(
-
- {'body content'}
-
- )
- ).toMatchSnapshot();
- });
- it(`should use custom element for header left and not wrap in EuiTitle`, () => {
- expect(
- render(
- {'title here'}}>
- {'body content'}
-
- )
- ).toMatchSnapshot();
- });
- it('should display body header wrapped in EuiTitle', () => {
- expect(
- render(
-
- {'body content'}
-
- )
- ).toMatchSnapshot();
- });
- it('should display body header custom element', () => {
- expect(
- render(
- {'body header'}}>
- {'body content'}
-
- )
- ).toMatchSnapshot();
- });
- it('should pass through EuiPage props', () => {
- expect(
- render(
-
- {'body content'}
-
- )
- ).toMatchSnapshot();
- });
-});
diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/page_view.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/page_view.tsx
deleted file mode 100644
index d4753b3a64e24..0000000000000
--- a/x-pack/plugins/security_solution/public/common/components/endpoint/page_view.tsx
+++ /dev/null
@@ -1,184 +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;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import {
- EuiPage,
- EuiPageBody,
- EuiPageContent,
- EuiPageContentBody,
- EuiPageContentHeader,
- EuiPageContentHeaderSection,
- EuiPageHeader,
- EuiPageHeaderSection,
- EuiPageProps,
- EuiTab,
- EuiTabs,
- EuiTitle,
- EuiTitleProps,
-} from '@elastic/eui';
-import React, { memo, MouseEventHandler, ReactNode, useMemo } from 'react';
-import styled from 'styled-components';
-import { EuiTabProps } from '@elastic/eui/src/components/tabs/tab';
-
-const StyledEuiPage = styled(EuiPage)`
- &.endpoint--isListView {
- padding: 0 ${(props) => props.theme.eui.euiSizeL};
-
- .endpoint-header {
- padding: ${(props) => props.theme.eui.euiSizeL};
- margin-bottom: 0;
- }
- .endpoint-page-content {
- border-left: none;
- border-right: none;
- }
- }
- &.endpoint--isDetailsView {
- .endpoint-page-content {
- padding: 0;
- border: none;
- background: none;
- }
- }
- .endpoint-navTabs {
- margin-left: ${(props) => props.theme.eui.euiSizeM};
- }
- .endpoint-header-leftSection {
- overflow: hidden;
- }
-`;
-
-const isStringOrNumber = /(string|number)/;
-
-/**
- * The `PageView` component used to render `headerLeft` when it is set as a `string`
- * Can be used when wanting to customize the `headerLeft` value but still use the standard
- * title component
- */
-export const PageViewHeaderTitle = memo & { children: ReactNode }>(
- ({ children, size = 'l', ...otherProps }) => {
- return (
-
- {children}
-
- );
- }
-);
-
-PageViewHeaderTitle.displayName = 'PageViewHeaderTitle';
-
-/**
- * The `PageView` component used to render `bodyHeader` when it is set as a `string`
- * Can be used when wanting to customize the `bodyHeader` value but still use the standard
- * title component
- */
-export const PageViewBodyHeaderTitle = memo<{ children: ReactNode }>(
- ({ children, ...otherProps }) => {
- return (
-
- {children}
-
- );
- }
-);
-PageViewBodyHeaderTitle.displayName = 'PageViewBodyHeaderTitle';
-
-export type PageViewProps = EuiPageProps & {
- /**
- * The type of view
- */
- viewType: 'list' | 'details';
- /**
- * content to be placed on the left side of the header. If a `string` is used, then it will
- * be wrapped with ``, else it will just be used as is.
- */
- headerLeft?: ReactNode;
- /** Content for the right side of the header */
- headerRight?: ReactNode;
- /**
- * body (sub-)header section. If a `string` is used, then it will be wrapped with
- * ``
- */
- bodyHeader?: ReactNode;
- /**
- * The list of tab navigation items
- */
- tabs?: Array<
- EuiTabProps & {
- name: ReactNode;
- id: string;
- href?: string;
- onClick?: MouseEventHandler;
- }
- >;
- children?: ReactNode;
-};
-
-/**
- * Page View layout for use in Endpoint
- */
-export const PageView = memo(
- ({ viewType, children, headerLeft, headerRight, bodyHeader, tabs, ...otherProps }) => {
- const tabComponents = useMemo(() => {
- if (!tabs) {
- return [];
- }
- return tabs.map(({ name, id, ...otherEuiTabProps }) => (
-
- {name}
-
- ));
- }, [tabs]);
-
- return (
-
-
- {(headerLeft || headerRight) && (
-
-
- {isStringOrNumber.test(typeof headerLeft) ? (
- {headerLeft}
- ) : (
- headerLeft
- )}
-
- {headerRight && (
-
- {headerRight}
-
- )}
-
- )}
- {tabComponents.length > 0 && (
- {tabComponents}
- )}
-
- {bodyHeader && (
-
-
- {isStringOrNumber.test(typeof bodyHeader) ? (
- {bodyHeader}
- ) : (
- bodyHeader
- )}
-
-
- )}
- {children}
-
-
-
- );
- }
-);
-
-PageView.displayName = 'PageView';
diff --git a/x-pack/plugins/security_solution/public/common/components/wrapper_page/index.tsx b/x-pack/plugins/security_solution/public/common/components/wrapper_page/index.tsx
index 373c1f7aaec75..f3136b0a40b3e 100644
--- a/x-pack/plugins/security_solution/public/common/components/wrapper_page/index.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/wrapper_page/index.tsx
@@ -7,14 +7,15 @@
import classNames from 'classnames';
import React, { useEffect } from 'react';
import styled from 'styled-components';
+import { CommonProps } from '@elastic/eui';
import { useFullScreen } from '../../containers/use_full_screen';
import { gutterTimeline } from '../../lib/helpers';
import { AppGlobalStyle } from '../page/index';
const Wrapper = styled.div`
- padding: ${({ theme }) =>
- `${theme.eui.paddingSizes.l} ${gutterTimeline} ${theme.eui.paddingSizes.l} ${theme.eui.paddingSizes.l}`};
+ padding: ${(props) => `${props.theme.eui.paddingSizes.l}`};
+
&.siemWrapperPage--restrictWidthDefault,
&.siemWrapperPage--restrictWidthCustom {
box-sizing: content-box;
@@ -29,6 +30,10 @@ const Wrapper = styled.div`
height: 100%;
}
+ &.siemWrapperPage--withTimeline {
+ padding-right: ${gutterTimeline};
+ }
+
&.siemWrapperPage--noPadding {
padding: 0;
}
@@ -38,18 +43,20 @@ Wrapper.displayName = 'Wrapper';
interface WrapperPageProps {
children: React.ReactNode;
- className?: string;
restrictWidth?: boolean | number | string;
style?: Record;
noPadding?: boolean;
+ noTimeline?: boolean;
}
-const WrapperPageComponent: React.FC = ({
+const WrapperPageComponent: React.FC = ({
children,
className,
restrictWidth,
style,
noPadding,
+ noTimeline,
+ ...otherProps
}) => {
const { globalFullScreen, setGlobalFullScreen } = useFullScreen();
useEffect(() => {
@@ -59,6 +66,7 @@ const WrapperPageComponent: React.FC = ({
const classes = classNames(className, {
siemWrapperPage: true,
'siemWrapperPage--noPadding': noPadding,
+ 'siemWrapperPage--withTimeline': !noTimeline,
'siemWrapperPage--fullHeight': globalFullScreen,
'siemWrapperPage--restrictWidthDefault':
restrictWidth && typeof restrictWidth === 'boolean' && restrictWidth === true,
@@ -73,7 +81,7 @@ const WrapperPageComponent: React.FC = ({
}
return (
-
+
{children}
diff --git a/x-pack/plugins/security_solution/public/management/common/constants.ts b/x-pack/plugins/security_solution/public/management/common/constants.ts
index 88396cc24a5e2..39d42114f9939 100644
--- a/x-pack/plugins/security_solution/public/management/common/constants.ts
+++ b/x-pack/plugins/security_solution/public/management/common/constants.ts
@@ -13,6 +13,7 @@ export const MANAGEMENT_ROUTING_ROOT_PATH = '';
export const MANAGEMENT_ROUTING_ENDPOINTS_PATH = `${MANAGEMENT_ROUTING_ROOT_PATH}/:tabName(${AdministrationSubTab.endpoints})`;
export const MANAGEMENT_ROUTING_POLICIES_PATH = `${MANAGEMENT_ROUTING_ROOT_PATH}/:tabName(${AdministrationSubTab.policies})`;
export const MANAGEMENT_ROUTING_POLICY_DETAILS_PATH = `${MANAGEMENT_ROUTING_ROOT_PATH}/:tabName(${AdministrationSubTab.policies})/:policyId`;
+export const MANAGEMENT_ROUTING_TRUSTED_APPS_PATH = `${MANAGEMENT_ROUTING_ROOT_PATH}/:tabName(${AdministrationSubTab.trustedApps})`;
// --[ STORE ]---------------------------------------------------------------------------
/** The SIEM global store namespace where the management state will be mounted */
diff --git a/x-pack/plugins/security_solution/public/management/common/routing.ts b/x-pack/plugins/security_solution/public/management/common/routing.ts
index ea162422abb6f..c5ced6f3bcf55 100644
--- a/x-pack/plugins/security_solution/public/management/common/routing.ts
+++ b/x-pack/plugins/security_solution/public/management/common/routing.ts
@@ -13,6 +13,7 @@ import {
MANAGEMENT_ROUTING_ENDPOINTS_PATH,
MANAGEMENT_ROUTING_POLICIES_PATH,
MANAGEMENT_ROUTING_POLICY_DETAILS_PATH,
+ MANAGEMENT_ROUTING_TRUSTED_APPS_PATH,
} from './constants';
import { AdministrationSubTab } from '../types';
import { appendSearch } from '../../common/components/link_to/helpers';
@@ -72,13 +73,21 @@ export const getEndpointDetailsPath = (
})}${appendSearch(`${urlQueryParams ? `${urlQueryParams}${urlSearch}` : urlSearch}`)}`;
};
-export const getPoliciesPath = (search?: string) =>
- `${generatePath(MANAGEMENT_ROUTING_POLICIES_PATH, {
+export const getPoliciesPath = (search?: string) => {
+ return `${generatePath(MANAGEMENT_ROUTING_POLICIES_PATH, {
tabName: AdministrationSubTab.policies,
})}${appendSearch(search)}`;
+};
-export const getPolicyDetailPath = (policyId: string, search?: string) =>
- `${generatePath(MANAGEMENT_ROUTING_POLICY_DETAILS_PATH, {
+export const getPolicyDetailPath = (policyId: string, search?: string) => {
+ return `${generatePath(MANAGEMENT_ROUTING_POLICY_DETAILS_PATH, {
tabName: AdministrationSubTab.policies,
policyId,
})}${appendSearch(search)}`;
+};
+
+export const getTrustedAppsListPath = (search?: string) => {
+ return `${generatePath(MANAGEMENT_ROUTING_TRUSTED_APPS_PATH, {
+ tabName: AdministrationSubTab.trustedApps,
+ })}${appendSearch(search)}`;
+};
diff --git a/x-pack/plugins/security_solution/public/management/common/translations.ts b/x-pack/plugins/security_solution/public/management/common/translations.ts
index 03f6a80ef99a4..d24eb1bd315fa 100644
--- a/x-pack/plugins/security_solution/public/management/common/translations.ts
+++ b/x-pack/plugins/security_solution/public/management/common/translations.ts
@@ -13,3 +13,11 @@ export const ENDPOINTS_TAB = i18n.translate('xpack.securitySolution.endpointsTab
export const POLICIES_TAB = i18n.translate('xpack.securitySolution.policiesTab', {
defaultMessage: 'Policies',
});
+
+export const TRUSTED_APPS_TAB = i18n.translate('xpack.securitySolution.trustedAppsTab', {
+ defaultMessage: 'Trusted applications',
+});
+
+export const BETA_BADGE_LABEL = i18n.translate('xpack.securitySolution.administration.list.beta', {
+ defaultMessage: 'Beta',
+});
diff --git a/x-pack/plugins/security_solution/public/management/components/administration_list_page.tsx b/x-pack/plugins/security_solution/public/management/components/administration_list_page.tsx
new file mode 100644
index 0000000000000..3df525b4d59d6
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/management/components/administration_list_page.tsx
@@ -0,0 +1,65 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React, { FC, memo } from 'react';
+import { EuiPanel, EuiSpacer, CommonProps } from '@elastic/eui';
+import { SecurityPageName } from '../../../common/constants';
+import { WrapperPage } from '../../common/components/wrapper_page';
+import { HeaderPage } from '../../common/components/header_page';
+import { SiemNavigation } from '../../common/components/navigation';
+import { SpyRoute } from '../../common/utils/route/spy_routes';
+import { AdministrationSubTab } from '../types';
+import { ENDPOINTS_TAB, TRUSTED_APPS_TAB, BETA_BADGE_LABEL } from '../common/translations';
+import { getEndpointListPath, getTrustedAppsListPath } from '../common/routing';
+
+interface AdministrationListPageProps {
+ beta: boolean;
+ title: React.ReactNode;
+ subtitle: React.ReactNode;
+ actions?: React.ReactNode;
+}
+
+export const AdministrationListPage: FC = memo(
+ ({ beta, title, subtitle, actions, children, ...otherProps }) => {
+ const badgeOptions = !beta ? undefined : { beta: true, text: BETA_BADGE_LABEL };
+
+ return (
+
+
+ {actions}
+
+
+
+
+
+
+ {children}
+
+
+
+ );
+ }
+);
+
+AdministrationListPage.displayName = 'AdministrationListPage';
diff --git a/x-pack/plugins/security_solution/public/management/components/management_page_view.tsx b/x-pack/plugins/security_solution/public/management/components/management_page_view.tsx
deleted file mode 100644
index 54d9131209d0d..0000000000000
--- a/x-pack/plugins/security_solution/public/management/components/management_page_view.tsx
+++ /dev/null
@@ -1,19 +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;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import React, { memo } from 'react';
-import { EuiErrorBoundary } from '@elastic/eui';
-import { PageView, PageViewProps } from '../../common/components/endpoint/page_view';
-
-export const ManagementPageView = memo>((options) => {
- return (
-
-
-
- );
-});
-
-ManagementPageView.displayName = 'ManagementPageView';
diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx
index 09df6d6ece042..fe06bcc8131f8 100644
--- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx
@@ -8,6 +8,7 @@ import React from 'react';
import * as reactTestingLibrary from '@testing-library/react';
import { EndpointList } from './index';
+import '../../../../common/mock/match_media.ts';
import {
mockEndpointDetailsApiResult,
mockEndpointResultList,
diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx
index a923d49012d70..611e69391ab06 100644
--- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx
@@ -10,15 +10,10 @@ import {
EuiBasicTable,
EuiBasicTableColumn,
EuiText,
- EuiTitle,
- EuiSpacer,
EuiLink,
EuiHealth,
EuiToolTip,
EuiSelectableProps,
- EuiBetaBadge,
- EuiFlexGroup,
- EuiFlexItem,
} from '@elastic/eui';
import { useHistory } from 'react-router-dom';
import { i18n } from '@kbn/i18n';
@@ -36,8 +31,6 @@ import {
import { useNavigateByRouterEventHandler } from '../../../../common/hooks/endpoint/use_navigate_by_router_event_handler';
import { CreateStructuredSelector } from '../../../../common/store';
import { Immutable, HostInfo } from '../../../../../common/endpoint/types';
-import { SpyRoute } from '../../../../common/utils/route/spy_routes';
-import { ManagementPageView } from '../../../components/management_page_view';
import { PolicyEmptyState, HostsEmptyState } from '../../../components/management_empty_state';
import { FormattedDate } from '../../../../common/components/formatted_date';
import { useNavigateToAppEventHandler } from '../../../../common/hooks/endpoint/use_navigate_to_app_event_handler';
@@ -50,6 +43,7 @@ import { getEndpointListPath, getEndpointDetailsPath } from '../../../common/rou
import { useFormatUrl } from '../../../../common/components/link_to';
import { EndpointAction } from '../store/action';
import { EndpointPolicyLink } from './components/endpoint_policy_link';
+import { AdministrationListPage } from '../../../components/administration_list_page';
const EndpointListNavLink = memo<{
name: string;
@@ -375,40 +369,20 @@ export const EndpointList = () => {
]);
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
+ beta={true}
+ title={
+
+ }
+ subtitle={
+
}
>
{hasSelectedEndpoint && }
@@ -425,7 +399,6 @@ export const EndpointList = () => {
>
)}
{renderTableOrEmptyState}
-
-
+
);
};
diff --git a/x-pack/plugins/security_solution/public/management/pages/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/index.test.tsx
index 9e496ce6c0b50..c04d3b1ec1a90 100644
--- a/x-pack/plugins/security_solution/public/management/pages/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/index.test.tsx
@@ -7,6 +7,7 @@
import React from 'react';
import { ManagementContainer } from './index';
+import '../../common/mock/match_media.ts';
import { AppContextTestRender, createAppRootMockRenderer } from '../../common/mock/endpoint';
import { useIngestEnabledCheck } from '../../common/hooks/endpoint/ingest_enabled';
@@ -22,15 +23,13 @@ describe('when in the Admistration tab', () => {
it('should display the No Permissions view when Ingest is OFF', async () => {
(useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: false });
- const renderResult = render();
- const noIngestPermissions = await renderResult.findByTestId('noIngestPermissions');
- expect(noIngestPermissions).not.toBeNull();
+
+ expect(await render().findByTestId('noIngestPermissions')).not.toBeNull();
});
it('should display the Management view when Ingest is ON', async () => {
(useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: true });
- const renderResult = render();
- const endpointPage = await renderResult.findByTestId('endpointPage');
- expect(endpointPage).not.toBeNull();
+
+ expect(await render().findByTestId('endpointPage')).not.toBeNull();
});
});
diff --git a/x-pack/plugins/security_solution/public/management/pages/index.tsx b/x-pack/plugins/security_solution/public/management/pages/index.tsx
index c20a3dd31d6a4..959753cba7bd7 100644
--- a/x-pack/plugins/security_solution/public/management/pages/index.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/index.tsx
@@ -11,55 +11,50 @@ import { useHistory, Route, Switch } from 'react-router-dom';
import { ChromeBreadcrumb } from 'kibana/public';
import { EuiText, EuiEmptyPrompt } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
-import { PolicyContainer } from './policy';
import {
MANAGEMENT_ROUTING_ENDPOINTS_PATH,
MANAGEMENT_ROUTING_POLICIES_PATH,
MANAGEMENT_ROUTING_ROOT_PATH,
+ MANAGEMENT_ROUTING_TRUSTED_APPS_PATH,
} from '../common/constants';
import { NotFoundPage } from '../../app/404';
import { EndpointsContainer } from './endpoint_hosts';
+import { PolicyContainer } from './policy';
+import { TrustedAppsContainer } from './trusted_apps';
import { getEndpointListPath } from '../common/routing';
import { APP_ID, SecurityPageName } from '../../../common/constants';
import { GetUrlForApp } from '../../common/components/navigation/types';
import { AdministrationRouteSpyState } from '../../common/utils/route/types';
import { ADMINISTRATION } from '../../app/home/translations';
import { AdministrationSubTab } from '../types';
-import { ENDPOINTS_TAB, POLICIES_TAB } from '../common/translations';
+import { ENDPOINTS_TAB, POLICIES_TAB, TRUSTED_APPS_TAB } from '../common/translations';
import { SpyRoute } from '../../common/utils/route/spy_routes';
import { useIngestEnabledCheck } from '../../common/hooks/endpoint/ingest_enabled';
-const TabNameMappedToI18nKey: Record = {
+const TabNameMappedToI18nKey: Record = {
[AdministrationSubTab.endpoints]: ENDPOINTS_TAB,
[AdministrationSubTab.policies]: POLICIES_TAB,
+ [AdministrationSubTab.trustedApps]: TRUSTED_APPS_TAB,
};
-export const getBreadcrumbs = (
+export function getBreadcrumbs(
params: AdministrationRouteSpyState,
search: string[],
getUrlForApp: GetUrlForApp
-): ChromeBreadcrumb[] => {
- let breadcrumb = [
+): ChromeBreadcrumb[] {
+ return [
{
text: ADMINISTRATION,
href: getUrlForApp(`${APP_ID}:${SecurityPageName.administration}`, {
path: !isEmpty(search[0]) ? search[0] : '',
}),
},
- ];
-
- const tabName = params?.tabName;
- if (!tabName) return breadcrumb;
-
- breadcrumb = [
- ...breadcrumb,
- {
+ ...(params?.tabName ? [params?.tabName] : []).map((tabName) => ({
text: TabNameMappedToI18nKey[tabName],
href: '',
- },
+ })),
];
- return breadcrumb;
-};
+}
const NoPermissions = memo(() => {
return (
@@ -104,6 +99,7 @@ export const ManagementContainer = memo(() => {
+
{
it('should display back to list button and policy title', () => {
policyView.update();
- const pageHeaderLeft = policyView.find(
- 'EuiPageHeaderSection[data-test-subj="pageViewHeaderLeft"]'
- );
- const backToListButton = pageHeaderLeft.find('EuiButtonEmpty');
- expect(backToListButton.prop('iconType')).toBe('arrowLeft');
- expect(backToListButton.prop('href')).toBe(endpointListPath);
- expect(backToListButton.text()).toBe('Back to endpoint hosts');
+ const backToListLink = policyView.find('LinkIcon[dataTestSubj="policyDetailsBackLink"]');
+ expect(backToListLink.prop('iconType')).toBe('arrowLeft');
+ expect(backToListLink.prop('href')).toBe(endpointListPath);
+ expect(backToListLink.text()).toBe('Back to endpoint hosts');
- const pageTitle = pageHeaderLeft.find('[data-test-subj="pageViewHeaderLeftTitle"]');
+ const pageTitle = policyView.find('h1[data-test-subj="header-page-title"]');
expect(pageTitle).toHaveLength(1);
expect(pageTitle.text()).toEqual(policyPackageConfig.name);
});
it('should navigate to list if back to link is clicked', async () => {
policyView.update();
- const backToListButton = policyView.find(
- 'EuiPageHeaderSection[data-test-subj="pageViewHeaderLeft"] EuiButtonEmpty'
- );
+
+ const backToListLink = policyView.find('a[data-test-subj="policyDetailsBackLink"]');
expect(history.location.pathname).toEqual(policyDetailsPathUrl);
- backToListButton.simulate('click', { button: 0 });
+ backToListLink.simulate('click', { button: 0 });
expect(history.location.pathname).toEqual(endpointListPath);
});
it('should display agent stats', async () => {
await asyncActions;
policyView.update();
- const headerRight = policyView.find(
- 'EuiPageHeaderSection[data-test-subj="pageViewHeaderRight"]'
- );
- const agentsSummary = headerRight.find('EuiFlexGroup[data-test-subj="policyAgentsSummary"]');
+
+ const agentsSummary = policyView.find('EuiFlexGroup[data-test-subj="policyAgentsSummary"]');
expect(agentsSummary).toHaveLength(1);
expect(agentsSummary.text()).toBe('Endpoints5Online3Offline1Error1');
});
diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx
index e54e684d788c0..636c0e5e6a0c3 100644
--- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx
@@ -38,9 +38,6 @@ import { WindowsEvents, MacEvents, LinuxEvents } from './policy_forms/events';
import { MalwareProtections } from './policy_forms/protections/malware';
import { useToasts } from '../../../../common/lib/kibana';
import { AppAction } from '../../../../common/store/actions';
-import { useNavigateByRouterEventHandler } from '../../../../common/hooks/endpoint/use_navigate_by_router_event_handler';
-import { PageViewHeaderTitle } from '../../../../common/components/endpoint/page_view';
-import { ManagementPageView } from '../../../components/management_page_view';
import { SpyRoute } from '../../../../common/utils/route/spy_routes';
import { SecurityPageName } from '../../../../app/types';
import { getEndpointListPath } from '../../../common/routing';
@@ -48,6 +45,8 @@ import { useFormatUrl } from '../../../../common/components/link_to';
import { useNavigateToAppEventHandler } from '../../../../common/hooks/endpoint/use_navigate_to_app_event_handler';
import { MANAGEMENT_APP_ID } from '../../../common/constants';
import { PolicyDetailsRouteState } from '../../../../../common/endpoint/types';
+import { WrapperPage } from '../../../../common/components/wrapper_page';
+import { HeaderPage } from '../../../../common/components/header_page';
export const PolicyDetails = React.memo(() => {
const dispatch = useDispatch<(action: AppAction) => void>();
@@ -109,8 +108,6 @@ export const PolicyDetails = React.memo(() => {
}
}, [navigateToApp, toasts, policyName, policyUpdateStatus, routeState]);
- const handleBackToListOnClick = useNavigateByRouterEventHandler(hostListRouterPath);
-
const navigateToAppArguments = useMemo((): Parameters => {
return routeState?.onCancelNavigateTo ?? [MANAGEMENT_APP_ID, { path: hostListRouterPath }];
}, [hostListRouterPath, routeState?.onCancelNavigateTo]);
@@ -142,7 +139,7 @@ export const PolicyDetails = React.memo(() => {
// Else, if we have an error, then show error on the page.
if (!policyItem) {
return (
-
+
{isPolicyLoading ? (
) : policyApiError ? (
@@ -151,28 +148,10 @@ export const PolicyDetails = React.memo(() => {
) : null}
-
+
);
}
- const headerLeftContent = (
-
- {/* eslint-disable-next-line @elastic/eui/href-or-on-click */}
-
-
-
-
{policyItem.name}
-
- );
-
const headerRightContent = (
@@ -222,12 +201,21 @@ export const PolicyDetails = React.memo(() => {
onConfirm={handleSaveConfirmation}
/>
)}
-
+
+
+ {headerRightContent}
+
+
{
/>
+
+
{
/>
+
-
+
+
>
);
diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.test.tsx
index 97eaceff91e9c..b0139bf3ecb21 100644
--- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.test.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.test.tsx
@@ -6,6 +6,7 @@
import React from 'react';
import { PolicyList } from './index';
+import '../../../../common/mock/match_media.ts';
import { AppContextTestRender, createAppRootMockRenderer } from '../../../../common/mock/endpoint';
import { setPolicyListApiMockImplementation } from '../store/policy_list/test_mock_utils';
diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx
index 39b77d259add1..b97ea958fd1c2 100644
--- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx
@@ -8,7 +8,6 @@ import React, { useCallback, useEffect, useMemo, CSSProperties, useState } from
import {
EuiBasicTable,
EuiText,
- EuiTitle,
EuiSpacer,
EuiFlexGroup,
EuiFlexItem,
@@ -23,7 +22,6 @@ import {
EuiConfirmModal,
EuiCallOut,
EuiButton,
- EuiBetaBadge,
EuiHorizontalRule,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
@@ -41,9 +39,7 @@ import { useKibana } from '../../../../../../../../src/plugins/kibana_react/publ
import { Immutable, PolicyData } from '../../../../../common/endpoint/types';
import { useNavigateByRouterEventHandler } from '../../../../common/hooks/endpoint/use_navigate_by_router_event_handler';
import { LinkToApp } from '../../../../common/components/endpoint/link_to_app';
-import { ManagementPageView } from '../../../components/management_page_view';
import { PolicyEmptyState } from '../../../components/management_empty_state';
-import { SpyRoute } from '../../../../common/utils/route/spy_routes';
import { FormattedDateAndTime } from '../../../../common/components/endpoint/formatted_date_time';
import { SecurityPageName } from '../../../../app/types';
import { useFormatUrl } from '../../../../common/components/link_to';
@@ -51,6 +47,7 @@ import { getPolicyDetailPath, getPoliciesPath } from '../../../common/routing';
import { useNavigateToAppEventHandler } from '../../../../common/hooks/endpoint/use_navigate_to_app_event_handler';
import { CreatePackageConfigRouteState } from '../../../../../../ingest_manager/public';
import { MANAGEMENT_APP_ID } from '../../../common/constants';
+import { AdministrationListPage } from '../../../components/administration_list_page';
interface TableChangeCallbackArguments {
page: { index: number; size: number };
@@ -405,42 +402,22 @@ export const PolicyList = React.memo(() => {
}}
/>
)}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
+ beta={true}
+ title={
+
+ }
+ subtitle={
+
}
- headerRight={
+ actions={
{
>
)}
{bodyContent}
-
-
+
>
);
});
diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/index.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/index.tsx
new file mode 100644
index 0000000000000..ddc16cc448c8a
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/index.tsx
@@ -0,0 +1,20 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { Switch, Route } from 'react-router-dom';
+import React from 'react';
+import { TrustedAppsPage } from './view';
+import { MANAGEMENT_ROUTING_TRUSTED_APPS_PATH } from '../../common/constants';
+import { NotFoundPage } from '../../../app/404';
+
+export function TrustedAppsContainer() {
+ return (
+
+
+
+
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/__snapshots__/trusted_apps_page.test.tsx.snap b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/__snapshots__/trusted_apps_page.test.tsx.snap
new file mode 100644
index 0000000000000..6f074f3809036
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/__snapshots__/trusted_apps_page.test.tsx.snap
@@ -0,0 +1,21 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`TrustedAppsPage rendering 1`] = `
+
+ }
+ title={
+
+ }
+/>
+`;
diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/index.ts b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/index.ts
new file mode 100644
index 0000000000000..af6f7e2863dfb
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/index.ts
@@ -0,0 +1,6 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+export * from './trusted_apps_page';
diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/routes.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx
similarity index 51%
rename from x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/routes.tsx
rename to x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx
index 727d2715f0974..cc7dbd42d7a7d 100644
--- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/routes.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx
@@ -3,16 +3,13 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-
+import { shallow } from 'enzyme';
import React from 'react';
-import { Route, Switch } from 'react-router-dom';
-import { EndpointList } from './view';
+import { TrustedAppsPage } from './trusted_apps_page';
-export const EndpointHostsRoutes: React.FC = () => (
-
-
-
-
-
-);
+describe('TrustedAppsPage', () => {
+ test('rendering', () => {
+ expect(shallow()).toMatchSnapshot();
+ });
+});
diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.tsx
new file mode 100644
index 0000000000000..7045fa49ffad3
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.tsx
@@ -0,0 +1,28 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React from 'react';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { AdministrationListPage } from '../../../components/administration_list_page';
+
+export function TrustedAppsPage() {
+ return (
+
+ }
+ subtitle={
+
+ }
+ />
+ );
+}
diff --git a/x-pack/plugins/security_solution/public/management/types.ts b/x-pack/plugins/security_solution/public/management/types.ts
index c35c9277b4488..21214241d1981 100644
--- a/x-pack/plugins/security_solution/public/management/types.ts
+++ b/x-pack/plugins/security_solution/public/management/types.ts
@@ -27,6 +27,7 @@ export type ManagementState = CombinedState<{
export enum AdministrationSubTab {
endpoints = 'endpoints',
policies = 'policy',
+ trustedApps = 'trusted_apps',
}
/**
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 8c92e7359b2f7..e21806e1a1e01 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -16251,7 +16251,6 @@
"xpack.securitySolution.endpoint.details.policyResponse.success": "成功",
"xpack.securitySolution.endpoint.details.policyResponse.warning": "警告",
"xpack.securitySolution.endpoint.details.policyResponse.workflow": "ワークフロー",
- "xpack.securitySolution.endpoint.list.beta": "ベータ",
"xpack.securitySolution.endpoint.list.loadingPolicies": "ポリシー構成を読み込んでいます…",
"xpack.securitySolution.endpoint.list.noEndpointsInstructions": "セキュリティポリシーを作成しました。以下のステップに従い、エージェントでElastic Endpoint Security機能を有効にする必要があります。",
"xpack.securitySolution.endpoint.list.noEndpointsPrompt": "エージェントでElastic Endpoint Securityを有効にする",
@@ -16310,7 +16309,6 @@
"xpack.securitySolution.endpoint.policyList.actionButtonText": "Endpoint Securityを追加",
"xpack.securitySolution.endpoint.policyList.actionMenu": "開く",
"xpack.securitySolution.endpoint.policyList.agentConfigAction": "エージェント構成を表示",
- "xpack.securitySolution.endpoint.policyList.beta": "ベータ",
"xpack.securitySolution.endpoint.policyList.createdAt": "作成日時",
"xpack.securitySolution.endpoint.policyList.createdBy": "作成者",
"xpack.securitySolution.endpoint.policyList.createNewButton": "新しいポリシーを作成",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 5ab70ff7a9d04..13ae52bdd0af3 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -16257,7 +16257,6 @@
"xpack.securitySolution.endpoint.details.policyResponse.success": "成功",
"xpack.securitySolution.endpoint.details.policyResponse.warning": "警告",
"xpack.securitySolution.endpoint.details.policyResponse.workflow": "工作流",
- "xpack.securitySolution.endpoint.list.beta": "公测版",
"xpack.securitySolution.endpoint.list.loadingPolicies": "正在加载政策配置",
"xpack.securitySolution.endpoint.list.noEndpointsInstructions": "您已创建安全策略。现在您需要按照下面的步骤在代理上启用 Elastic Endpoint Security 功能。",
"xpack.securitySolution.endpoint.list.noEndpointsPrompt": "在您的代理上启用 Elastic Endpoint Security",
@@ -16317,7 +16316,6 @@
"xpack.securitySolution.endpoint.policyList.actionButtonText": "添加 Endpoint Security",
"xpack.securitySolution.endpoint.policyList.actionMenu": "打开",
"xpack.securitySolution.endpoint.policyList.agentConfigAction": "查看代理配置",
- "xpack.securitySolution.endpoint.policyList.beta": "公测版",
"xpack.securitySolution.endpoint.policyList.createdAt": "创建日期",
"xpack.securitySolution.endpoint.policyList.createdBy": "创建者",
"xpack.securitySolution.endpoint.policyList.createNewButton": "创建新策略",
diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts
index 0037c39b8fed2..1843fca29758a 100644
--- a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts
+++ b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts
@@ -27,8 +27,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
});
it('finds page title', async () => {
- const title = await testSubjects.getVisibleText('pageViewHeaderLeftTitle');
- expect(title).to.equal('Endpoints');
+ const title = await testSubjects.getVisibleText('header-page-title');
+ expect(title).to.equal('Endpoints BETA');
});
it('displays table data', async () => {
diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts
index 1119906ba5cfa..9efba2b595bde 100644
--- a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts
+++ b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts
@@ -47,7 +47,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
});
it('should display policy view', async () => {
- expect(await testSubjects.getVisibleText('pageViewHeaderLeftTitle')).to.equal(
+ expect(await testSubjects.getVisibleText('header-page-title')).to.equal(
policyInfo.packageConfig.name
);
});
diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_list.ts
index 0c5e15ed4104c..cf93ca1b68991 100644
--- a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_list.ts
+++ b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_list.ts
@@ -29,8 +29,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await testSubjects.existOrFail('policyListPage');
});
it('displays page title', async () => {
- const policyTitle = await testSubjects.getVisibleText('pageViewHeaderLeftTitle');
- expect(policyTitle).to.equal('Policies');
+ const policyTitle = await testSubjects.getVisibleText('header-page-title');
+ expect(policyTitle).to.equal('Policies BETA');
});
it('shows header create policy button', async () => {
const createButtonTitle = await testSubjects.getVisibleText('headerCreateNewPolicyButton');
diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/trusted_apps_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/trusted_apps_list.ts
new file mode 100644
index 0000000000000..5f749ac272474
--- /dev/null
+++ b/x-pack/test/security_solution_endpoint/apps/endpoint/trusted_apps_list.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;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import expect from '@kbn/expect';
+import { FtrProviderContext } from '../../ftr_provider_context';
+
+export default ({ getPageObjects, getService }: FtrProviderContext) => {
+ const pageObjects = getPageObjects(['trustedApps']);
+ const testSubjects = getService('testSubjects');
+
+ describe('endpoint list', function () {
+ this.tags('ciGroup7');
+
+ describe('when there is data', () => {
+ before(async () => {
+ await pageObjects.trustedApps.navigateToTrustedAppsList();
+ });
+
+ it('finds page title', async () => {
+ expect(await testSubjects.getVisibleText('header-page-title')).to.equal(
+ 'Trusted applications BETA'
+ );
+ });
+ });
+ });
+};
diff --git a/x-pack/test/security_solution_endpoint/page_objects/index.ts b/x-pack/test/security_solution_endpoint/page_objects/index.ts
index 68e1ad00619c7..05762ba887c6f 100644
--- a/x-pack/test/security_solution_endpoint/page_objects/index.ts
+++ b/x-pack/test/security_solution_endpoint/page_objects/index.ts
@@ -7,6 +7,7 @@
import { pageObjects as xpackFunctionalPageObjects } from '../../functional/page_objects';
import { EndpointPageProvider } from './endpoint_page';
import { EndpointPolicyPageProvider } from './policy_page';
+import { TrustedAppsPageProvider } from './trusted_apps_page';
import { EndpointPageUtils } from './page_utils';
import { IngestManagerCreatePackageConfig } from './ingest_manager_create_package_config_page';
@@ -14,6 +15,7 @@ export const pageObjects = {
...xpackFunctionalPageObjects,
endpoint: EndpointPageProvider,
policy: EndpointPolicyPageProvider,
+ trustedApps: TrustedAppsPageProvider,
endpointPageUtils: EndpointPageUtils,
ingestManagerCreatePackageConfig: IngestManagerCreatePackageConfig,
};
diff --git a/x-pack/test/security_solution_endpoint/page_objects/trusted_apps_page.ts b/x-pack/test/security_solution_endpoint/page_objects/trusted_apps_page.ts
new file mode 100644
index 0000000000000..c02ac0ca9ffe0
--- /dev/null
+++ b/x-pack/test/security_solution_endpoint/page_objects/trusted_apps_page.ts
@@ -0,0 +1,20 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import { FtrProviderContext } from '../ftr_provider_context';
+
+export function TrustedAppsPageProvider({ getPageObjects }: FtrProviderContext) {
+ const pageObjects = getPageObjects(['common', 'header', 'endpointPageUtils']);
+
+ return {
+ async navigateToTrustedAppsList(searchParams?: string) {
+ await pageObjects.common.navigateToUrlWithBrowserHistory(
+ 'securitySolutionManagement',
+ `/trusted_apps${searchParams ? `?${searchParams}` : ''}`
+ );
+ await pageObjects.header.waitUntilLoadingHasFinished();
+ },
+ };
+}