Skip to content

Commit

Permalink
avoid 'app not found' flickering while awaiting for mount (#56483)
Browse files Browse the repository at this point in the history
  • Loading branch information
pgayvallet authored Feb 3, 2020
1 parent 27a4fe2 commit cc9ff6d
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 8 deletions.
88 changes: 88 additions & 0 deletions src/core/public/application/ui/app_container.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import React from 'react';
import { mount } from 'enzyme';

import { AppContainer } from './app_container';
import { Mounter, AppMountParameters, AppStatus } from '../types';

describe('AppContainer', () => {
const appId = 'someApp';
const setAppLeaveHandler = jest.fn();

const flushPromises = async () => {
await new Promise(async resolve => {
setImmediate(() => resolve());
});
};

const createResolver = (): [Promise<void>, () => void] => {
let resolve: () => void | undefined;
const promise = new Promise<void>(r => {
resolve = r;
});
return [promise, resolve!];
};

const createMounter = (promise: Promise<void>): Mounter => ({
appBasePath: '/base-path',
appRoute: '/some-route',
unmountBeforeMounting: false,
mount: async ({ element }: AppMountParameters) => {
await promise;
const container = document.createElement('div');
container.innerHTML = 'some-content';
element.appendChild(container);
return () => container.remove();
},
});

it('should hide the "not found" page before mounting the route', async () => {
const [waitPromise, resolvePromise] = createResolver();
const mounter = createMounter(waitPromise);

const wrapper = mount(
<AppContainer
appId={appId}
appStatus={AppStatus.inaccessible}
mounter={mounter}
setAppLeaveHandler={setAppLeaveHandler}
/>
);

expect(wrapper.text()).toContain('Application Not Found');

wrapper.setProps({
appId,
setAppLeaveHandler,
mounter,
appStatus: AppStatus.accessible,
});
wrapper.update();

expect(wrapper.text()).toEqual('');

resolvePromise();
await flushPromises();
wrapper.update();

expect(wrapper.text()).toContain('some-content');
});
});
18 changes: 10 additions & 8 deletions src/core/public/application/ui/app_container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,25 +53,27 @@ export const AppContainer: FunctionComponent<Props> = ({
unmountRef.current = null;
}
};
const mount = async () => {
if (!mounter || appStatus !== AppStatus.accessible) {
return setAppNotFound(true);
}

if (mounter.unmountBeforeMounting) {
unmount();
}
if (!mounter || appStatus !== AppStatus.accessible) {
return setAppNotFound(true);
}
setAppNotFound(false);

if (mounter.unmountBeforeMounting) {
unmount();
}

const mount = async () => {
unmountRef.current =
(await mounter.mount({
appBasePath: mounter.appBasePath,
element: elementRef.current!,
onAppLeave: handler => setAppLeaveHandler(appId, handler),
})) || null;
setAppNotFound(false);
};

mount();

return unmount;
}, [appId, appStatus, mounter, setAppLeaveHandler]);

Expand Down

0 comments on commit cc9ff6d

Please sign in to comment.