Skip to content

Commit

Permalink
[7.x] Redirect to full path when calling navigateToApp to a legacy app (
Browse files Browse the repository at this point in the history
  • Loading branch information
joshdover authored May 7, 2020
1 parent e23e273 commit a4f0b1f
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 11 deletions.
9 changes: 7 additions & 2 deletions src/core/public/application/application_service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ export class ApplicationService {
context,
http: { basePath },
injectedMetadata,
redirectTo = (path: string) => (window.location.href = path),
redirectTo = (path: string) => {
window.location.assign(path);
},
history,
}: SetupDeps): InternalApplicationSetup {
const basename = basePath.get();
Expand Down Expand Up @@ -210,7 +212,10 @@ export class ApplicationService {
}

const appBasePath = basePath.prepend(appRoute);
const mount: LegacyAppMounter = () => redirectTo(appBasePath);
const mount: LegacyAppMounter = ({ history: appHistory }) => {
redirectTo(appHistory.createHref(appHistory.location));
window.location.reload();
};

const { updater$, ...appProps } = app;
this.apps.set(app.id, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,20 @@
*/

import { take } from 'rxjs/operators';
import { createRenderer } from './utils';
import { act } from 'react-dom/test-utils';
import { createMemoryHistory, MemoryHistory } from 'history';

import { createRenderer } from './utils';
import { ApplicationService } from '../application_service';
import { httpServiceMock } from '../../http/http_service.mock';
import { contextServiceMock } from '../../context/context_service.mock';
import { injectedMetadataServiceMock } from '../../injected_metadata/injected_metadata_service.mock';
import { MockLifecycle } from '../test_types';
import { overlayServiceMock } from '../../overlays/overlay_service.mock';
import { AppMountParameters } from '../types';
import { ScopedHistory } from '../scoped_history';

const flushPromises = () => new Promise(resolve => setImmediate(resolve));

describe('ApplicationService', () => {
let setupDeps: MockLifecycle<'setup'>;
Expand Down Expand Up @@ -83,7 +88,10 @@ describe('ApplicationService', () => {

expect(await currentAppId$.pipe(take(1)).toPromise()).toEqual('app1');

resolveMount!();
await act(async () => {
resolveMount!();
await flushPromises();
});

expect(await currentAppId$.pipe(take(1)).toPromise()).toEqual('app1');
});
Expand All @@ -109,7 +117,7 @@ describe('ApplicationService', () => {

const { navigateToApp, currentAppId$ } = await service.start(startDeps);

await navigateToApp('app1');
await act(() => navigateToApp('app1'));

expect(await currentAppId$.pipe(take(1)).toPromise()).toEqual('app1');

Expand All @@ -120,6 +128,46 @@ describe('ApplicationService', () => {
});
});

it('redirects to full path when navigating to legacy app', async () => {
const redirectTo = jest.fn();
const reloadSpy = jest.spyOn(window.location, 'reload').mockImplementation(() => {});

// In the real application, we use a BrowserHistory instance configured with `basename`. However, in tests we must
// use MemoryHistory which does not support `basename`. In order to emulate this behavior, we will wrap this
// instance with a ScopedHistory configured with a basepath.
history.push(setupDeps.http.basePath.get()); // ScopedHistory constructor will fail if underlying history is not currently at basePath.
const { register, registerLegacyApp } = service.setup({
...setupDeps,
redirectTo,
history: new ScopedHistory(history, setupDeps.http.basePath.get()),
});

register(Symbol(), {
id: 'app1',
title: 'App1',
mount: ({ onAppLeave }: AppMountParameters) => {
onAppLeave(actions => actions.default());
return () => undefined;
},
});
registerLegacyApp({
id: 'myLegacyTestApp',
appUrl: '/app/myLegacyTestApp',
title: 'My Legacy Test App',
});

const { navigateToApp, getComponent } = await service.start(startDeps);

update = createRenderer(getComponent());

await navigate('/test/app/app1');
await act(() => navigateToApp('myLegacyTestApp', { path: '#/some-path' }));

expect(redirectTo).toHaveBeenCalledWith('/test/app/myLegacyTestApp#/some-path');
expect(reloadSpy).toHaveBeenCalled();
reloadSpy.mockRestore();
});

describe('leaving an application that registered an app leave handler', () => {
it('navigates to the new app if action is default', async () => {
startDeps.overlays.openConfirm.mockResolvedValue(true);
Expand All @@ -146,8 +194,10 @@ describe('ApplicationService', () => {

update = createRenderer(getComponent());

await navigate('/app/app1');
await navigateToApp('app2');
await act(async () => {
await navigate('/app/app1');
await navigateToApp('app2');
});

expect(startDeps.overlays.openConfirm).not.toHaveBeenCalled();
expect(history.entries.length).toEqual(3);
Expand Down Expand Up @@ -179,8 +229,10 @@ describe('ApplicationService', () => {

update = createRenderer(getComponent());

await navigate('/app/app1');
await navigateToApp('app2');
await act(async () => {
await navigate('/app/app1');
await navigateToApp('app2');
});

expect(startDeps.overlays.openConfirm).toHaveBeenCalledTimes(1);
expect(startDeps.overlays.openConfirm).toHaveBeenCalledWith(
Expand Down Expand Up @@ -216,8 +268,10 @@ describe('ApplicationService', () => {

update = createRenderer(getComponent());

await navigate('/app/app1');
await navigateToApp('app2');
await act(async () => {
await navigate('/app/app1');
await navigateToApp('app2');
});

expect(startDeps.overlays.openConfirm).toHaveBeenCalledTimes(1);
expect(startDeps.overlays.openConfirm).toHaveBeenCalledWith(
Expand Down

0 comments on commit a4f0b1f

Please sign in to comment.