Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 86 additions & 9 deletions src/core/public/application/integration_tests/router.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { createMemoryHistory, History, createHashHistory } from 'history';

import { AppRouter, AppNotFound } from '../ui';
import { EitherApp, MockedMounterMap, MockedMounterTuple } from '../test_types';
import { createRenderer, createAppMounter, createLegacyAppMounter } from './utils';
import { createRenderer, createAppMounter, createLegacyAppMounter, getUnmounter } from './utils';
import { AppStatus } from '../types';

describe('AppContainer', () => {
Expand All @@ -36,7 +36,6 @@ describe('AppContainer', () => {
history.push(path);
return update();
};

const mockMountersToMounters = () =>
new Map([...mounters].map(([appId, { mounter }]) => [appId, mounter]));
const setAppLeaveHandlerMock = () => undefined;
Expand All @@ -58,7 +57,8 @@ describe('AppContainer', () => {
createLegacyAppMounter('legacyApp1', jest.fn()),
createAppMounter('app2', '<div>App 2</div>'),
createLegacyAppMounter('baseApp:legacyApp2', jest.fn()),
createAppMounter('app3', '<div>App 3</div>', '/custom/path'),
createAppMounter('app3', '<div>Chromeless A</div>', '/chromeless-a/path'),
createAppMounter('app4', '<div>Chromeless B</div>', '/chromeless-b/path'),
createAppMounter('disabledApp', '<div>Disabled app</div>'),
createLegacyAppMounter('disabledLegacyApp', jest.fn()),
] as Array<MockedMounterTuple<EitherApp>>);
Expand All @@ -75,30 +75,107 @@ describe('AppContainer', () => {
});

it('calls mount handler and returned unmount function when navigating between apps', async () => {
const dom1 = await navigate('/app/app1');
const app1 = mounters.get('app1')!;
const app2 = mounters.get('app2')!;
let dom = await navigate('/app/app1');

expect(app1.mounter.mount).toHaveBeenCalled();
expect(dom1?.html()).toMatchInlineSnapshot(`
expect(dom?.html()).toMatchInlineSnapshot(`
"<div><div>
basename: /app/app1
html: <span>App 1</span>
</div></div>"
`);

const app1Unmount = await app1.mounter.mount.mock.results[0].value;
const dom2 = await navigate('/app/app2');
const app1Unmount = await getUnmounter(app1);
dom = await navigate('/app/app2');

expect(app1Unmount).toHaveBeenCalled();
expect(mounters.get('app2')!.mounter.mount).toHaveBeenCalled();
expect(dom2?.html()).toMatchInlineSnapshot(`
expect(app2.mounter.mount).toHaveBeenCalled();
expect(dom?.html()).toMatchInlineSnapshot(`
"<div><div>
basename: /app/app2
html: <div>App 2</div>
</div></div>"
`);
});

it('can navigate between standard application and one with custom appRoute', async () => {
const standardApp = mounters.get('app1')!;
const chromelessApp = mounters.get('app3')!;
let dom = await navigate('/app/app1');

expect(standardApp.mounter.mount).toHaveBeenCalled();
expect(dom?.html()).toMatchInlineSnapshot(`
"<div><div>
basename: /app/app1
html: <span>App 1</span>
</div></div>"
`);

const standardAppUnmount = await getUnmounter(standardApp);
dom = await navigate('/chromeless-a/path');

expect(standardAppUnmount).toHaveBeenCalled();
expect(chromelessApp.mounter.mount).toHaveBeenCalled();
expect(dom?.html()).toMatchInlineSnapshot(`
"<div><div>
basename: /chromeless-a/path
html: <div>Chromeless A</div>
</div></div>"
`);

const chromelessAppUnmount = await getUnmounter(standardApp);
dom = await navigate('/app/app1');

expect(chromelessAppUnmount).toHaveBeenCalled();
expect(standardApp.mounter.mount).toHaveBeenCalledTimes(2);
expect(dom?.html()).toMatchInlineSnapshot(`
"<div><div>
basename: /app/app1
html: <span>App 1</span>
</div></div>"
`);
});

it('can navigate between two applications with custom appRoutes', async () => {
const chromelessAppA = mounters.get('app3')!;
const chromelessAppB = mounters.get('app4')!;
let dom = await navigate('/chromeless-a/path');

expect(chromelessAppA.mounter.mount).toHaveBeenCalled();
expect(dom?.html()).toMatchInlineSnapshot(`
"<div><div>
basename: /chromeless-a/path
html: <div>Chromeless A</div>
</div></div>"
`);

const chromelessAppAUnmount = await getUnmounter(chromelessAppA);
dom = await navigate('/chromeless-b/path');

expect(chromelessAppAUnmount).toHaveBeenCalled();
expect(chromelessAppB.mounter.mount).toHaveBeenCalled();
expect(dom?.html()).toMatchInlineSnapshot(`
"<div><div>
basename: /chromeless-b/path
html: <div>Chromeless B</div>
</div></div>"
`);

const chromelessAppBUnmount = await getUnmounter(chromelessAppB);
dom = await navigate('/chromeless-a/path');

expect(chromelessAppBUnmount).toHaveBeenCalled();
expect(chromelessAppA.mounter.mount).toHaveBeenCalledTimes(2);
expect(dom?.html()).toMatchInlineSnapshot(`
"<div><div>
basename: /chromeless-a/path
html: <div>Chromeless A</div>
</div></div>"
`);
});

it('should not mount when partial route path matches', async () => {
mounters.set(...createAppMounter('spaces', '<div>Custom Space</div>', '/spaces/fake-login'));
mounters.set(...createAppMounter('login', '<div>Login Page</div>', '/fake-login'));
Expand Down
6 changes: 5 additions & 1 deletion src/core/public/application/integration_tests/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { mount } from 'enzyme';
import { I18nProvider } from '@kbn/i18n/react';

import { App, LegacyApp, AppMountParameters } from '../types';
import { MockedMounter, MockedMounterTuple } from '../test_types';
import { EitherApp, MockedMounter, MockedMounterTuple, Mountable } from '../test_types';

type Dom = ReturnType<typeof mount> | null;
type Renderer = () => Dom | Promise<Dom>;
Expand Down Expand Up @@ -80,3 +80,7 @@ export const createLegacyAppMounter = (
unmount: jest.fn(),
},
];

export function getUnmounter(app: Mountable<EitherApp>) {
return app.mounter.mount.mock.results[0].value;
}
17 changes: 9 additions & 8 deletions src/core/public/application/test_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,19 @@ export type ApplicationServiceContract = PublicMethodsOf<ApplicationService>;
export type EitherApp = App | LegacyApp;
/** @internal */
export type MockedUnmount = jest.Mocked<AppUnmount>;

/** @internal */
export interface Mountable<T extends EitherApp> {
mounter: MockedMounter<T>;
unmount: MockedUnmount;
}

/** @internal */
export type MockedMounter<T extends EitherApp> = jest.Mocked<Mounter<jest.Mocked<T>>>;
/** @internal */
export type MockedMounterTuple<T extends EitherApp> = [
string,
{ mounter: MockedMounter<T>; unmount: MockedUnmount }
];
export type MockedMounterTuple<T extends EitherApp> = [string, Mountable<T>];
/** @internal */
export type MockedMounterMap<T extends EitherApp> = Map<
string,
{ mounter: MockedMounter<T>; unmount: MockedUnmount }
>;
export type MockedMounterMap<T extends EitherApp> = Map<string, Mountable<T>>;
/** @internal */
export type MockLifecycle<
T extends keyof ApplicationService,
Expand Down
12 changes: 12 additions & 0 deletions test/functional/services/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,11 +313,23 @@ export async function BrowserProvider({ getService }: FtrProviderContext) {
/**
* Moves forwards in the browser history.
* https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_Navigation.html#forward
*
* @return {Promise<void>}
*/
public async goForward() {
await driver.navigate().forward();
}

/**
* Navigates to a URL via the browser history.
* https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_Navigation.html#to
*
* @return {Promise<void>}
*/
public async navigateTo(url: string) {
await driver.navigate().to(url);
}

/**
* Sends a sequance of keyboard keys. For each key, this will record a pair of keyDown and keyUp actions
* https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/input_exports_Actions.html#sendKeys
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@ export class CorePluginChromelessPlugin
return renderApp(context, params);
},
});

return {
getGreeting() {
return 'Hello from Plugin Chromeless!';
},
};
}

public start() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,24 @@ export class RenderingPlugin implements Plugin {
core.application.register({
id: 'rendering',
title: 'Rendering',
appRoute: '/render',
appRoute: '/render/core',
async mount(context, { element }) {
render(<h1 data-test-subj="renderingHeader">rendering service</h1>, element);

return () => unmountComponentAtNode(element);
},
});

core.application.register({
id: 'custom-app-route',
title: 'Custom App Route',
appRoute: '/custom/appRoute',
async mount(context, { element }) {
render(<h1 data-test-subj="customAppRouteHeader">Custom App Route</h1>, element);

return () => unmountComponentAtNode(element);
},
});
}

public start() {}
Expand Down
Loading