diff --git a/test/functional/page_objects/common_page.ts b/test/functional/page_objects/common_page.ts
index 9629b8ccf28e1..75a15cc16db2e 100644
--- a/test/functional/page_objects/common_page.ts
+++ b/test/functional/page_objects/common_page.ts
@@ -39,6 +39,14 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo
const defaultTryTimeout = config.get('timeouts.try');
const defaultFindTimeout = config.get('timeouts.find');
+ interface NavigateProps {
+ appConfig: {};
+ ensureCurrentUrl: boolean;
+ shouldLoginIfPrompted: boolean;
+ shouldAcceptAlert: boolean;
+ useActualUrl: boolean;
+ }
+
class CommonPage {
/**
* Navigates the browser window to provided URL
@@ -115,6 +123,34 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo
return currentUrl;
}
+ private async navigate(navigateProps: NavigateProps) {
+ const {
+ appConfig,
+ ensureCurrentUrl,
+ shouldLoginIfPrompted,
+ shouldAcceptAlert,
+ useActualUrl,
+ } = navigateProps;
+ const appUrl = getUrl.noAuth(config.get('servers.kibana'), appConfig);
+
+ await retry.try(async () => {
+ if (useActualUrl) {
+ log.debug(`navigateToActualUrl ${appUrl}`);
+ await browser.get(appUrl);
+ } else {
+ await CommonPage.navigateToUrlAndHandleAlert(appUrl, shouldAcceptAlert);
+ }
+
+ const currentUrl = shouldLoginIfPrompted
+ ? await this.loginIfPrompted(appUrl)
+ : await browser.getCurrentUrl();
+
+ if (ensureCurrentUrl && !currentUrl.includes(appUrl)) {
+ throw new Error(`expected ${currentUrl}.includes(${appUrl})`);
+ }
+ });
+ }
+
/**
* Navigates browser using the pathname from the appConfig and subUrl as the hash
* @param appName As defined in the apps config, e.g. 'home'
@@ -137,23 +173,44 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo
hash: useActualUrl ? subUrl : `/${appName}/${subUrl}`,
};
- const appUrl = getUrl.noAuth(config.get('servers.kibana'), appConfig);
-
- await retry.try(async () => {
- if (useActualUrl) {
- log.debug(`navigateToActualUrl ${appUrl}`);
- await browser.get(appUrl);
- } else {
- await CommonPage.navigateToUrlAndHandleAlert(appUrl, shouldAcceptAlert);
- }
+ await this.navigate({
+ appConfig,
+ ensureCurrentUrl,
+ shouldLoginIfPrompted,
+ shouldAcceptAlert,
+ useActualUrl,
+ });
+ }
- const currentUrl = shouldLoginIfPrompted
- ? await this.loginIfPrompted(appUrl)
- : await browser.getCurrentUrl();
+ /**
+ * Navigates browser using the pathname from the appConfig and subUrl as the extended path.
+ * This was added to be able to test an application that uses browser history over hash history.
+ * @param appName As defined in the apps config, e.g. 'home'
+ * @param subUrl The route after the appUrl, e.g. 'tutorial_directory/sampleData'
+ * @param args additional arguments
+ */
+ public async navigateToUrlWithBrowserHistory(
+ appName: string,
+ subUrl?: string,
+ {
+ basePath = '',
+ ensureCurrentUrl = true,
+ shouldLoginIfPrompted = true,
+ shouldAcceptAlert = true,
+ useActualUrl = true,
+ } = {}
+ ) {
+ const appConfig = {
+ // subUrl following the basePath, assumes no hashes. Ex: 'app/endpoint/management'
+ pathname: `${basePath}${config.get(['apps', appName]).pathname}${subUrl}`,
+ };
- if (ensureCurrentUrl && !currentUrl.includes(appUrl)) {
- throw new Error(`expected ${currentUrl}.includes(${appUrl})`);
- }
+ await this.navigate({
+ appConfig,
+ ensureCurrentUrl,
+ shouldLoginIfPrompted,
+ shouldAcceptAlert,
+ useActualUrl,
});
}
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx
index 1af27f039aca7..82c95b37ee7b0 100644
--- a/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx
@@ -8,24 +8,55 @@ import * as React from 'react';
import ReactDOM from 'react-dom';
import { CoreStart, AppMountParameters } from 'kibana/public';
import { I18nProvider, FormattedMessage } from '@kbn/i18n/react';
+import { Route, BrowserRouter, Switch } from 'react-router-dom';
/**
* This module will be loaded asynchronously to reduce the bundle size of your plugin's main bundle.
*/
-export function renderApp(coreStart: CoreStart, { element }: AppMountParameters) {
+export function renderApp(coreStart: CoreStart, { appBasePath, element }: AppMountParameters) {
coreStart.http.get('/api/endpoint/hello-world');
- ReactDOM.render(, element);
+ ReactDOM.render(, element);
return () => {
ReactDOM.unmountComponentAtNode(element);
};
}
-const AppRoot = React.memo(() => (
+interface RouterProps {
+ basename: string;
+}
+
+const AppRoot: React.FunctionComponent = React.memo(({ basename }) => (
-
-
-
+
+
+ (
+
+
+
+ )}
+ />
+ (
+
+
+
+ )}
+ />
+ (
+
+ )}
+ />
+
+
));
diff --git a/x-pack/test/functional/apps/endpoint/feature_controls/endpoint_spaces.ts b/x-pack/test/functional/apps/endpoint/feature_controls/endpoint_spaces.ts
index 6b3b423e293c2..1d1fb566eb075 100644
--- a/x-pack/test/functional/apps/endpoint/feature_controls/endpoint_spaces.ts
+++ b/x-pack/test/functional/apps/endpoint/feature_controls/endpoint_spaces.ts
@@ -42,6 +42,15 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
});
await testSubjects.existOrFail('welcomeTitle');
});
+
+ it(`endpoint management shows 'Manage Endpoints'`, async () => {
+ await pageObjects.common.navigateToUrlWithBrowserHistory('endpoint', '/management', {
+ basePath: '/s/custom_space',
+ ensureCurrentUrl: false,
+ shouldLoginIfPrompted: false,
+ });
+ await testSubjects.existOrFail('endpointManagement');
+ });
});
describe('space with endpoint disabled', () => {