Skip to content

Commit

Permalink
add missing conditional classes on app-wrapper and application contai…
Browse files Browse the repository at this point in the history
…ners
  • Loading branch information
pgayvallet committed Jan 13, 2020
1 parent aeebedf commit b487fe5
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/core/public/chrome/chrome_service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export class ChromeService {
)
)
);
this.isVisible$ = combineLatest(this.appHidden$, this.toggleHidden$).pipe(
this.isVisible$ = combineLatest([this.appHidden$, this.toggleHidden$]).pipe(
map(([appHidden, toggleHidden]) => !(appHidden || toggleHidden)),
takeUntil(this.stop$)
);
Expand Down
77 changes: 77 additions & 0 deletions src/core/public/rendering/app_containers.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* 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 { BehaviorSubject } from 'rxjs';
import { act } from 'react-dom/test-utils';
import { mount } from 'enzyme';
import React from 'react';

import { AppWrapper, AppContainer } from './app_containers';

describe('AppWrapper', () => {
it('toggles the `hidden-chrome` class depending on the chrome visibility state', () => {
const chromeVisible$ = new BehaviorSubject<boolean>(true);

const component = mount(<AppWrapper chromeVisible$={chromeVisible$}>app-content</AppWrapper>);
expect(component.html()).toMatchInlineSnapshot(
`"<div class=\\"app-wrapper\\">app-content</div>"`
);

act(() => chromeVisible$.next(false));
component.update();
expect(component.html()).toMatchInlineSnapshot(
`"<div class=\\"app-wrapper hidden-chrome\\">app-content</div>"`
);

act(() => chromeVisible$.next(true));
component.update();
expect(component.html()).toMatchInlineSnapshot(
`"<div class=\\"app-wrapper\\">app-content</div>"`
);
});
});

describe('AppContainer', () => {
it('adds classes supplied by chrome', () => {
const appClasses$ = new BehaviorSubject<string[]>([]);

const component = mount(<AppContainer classes$={appClasses$}>app-content</AppContainer>);
expect(component.html()).toMatchInlineSnapshot(
`"<div class=\\"application\\">app-content</div>"`
);

act(() => appClasses$.next(['classA', 'classB']));
component.update();
expect(component.html()).toMatchInlineSnapshot(
`"<div class=\\"application classA classB\\">app-content</div>"`
);

act(() => appClasses$.next(['classC']));
component.update();
expect(component.html()).toMatchInlineSnapshot(
`"<div class=\\"application classC\\">app-content</div>"`
);

act(() => appClasses$.next([]));
component.update();
expect(component.html()).toMatchInlineSnapshot(
`"<div class=\\"application\\">app-content</div>"`
);
});
});
37 changes: 37 additions & 0 deletions src/core/public/rendering/app_containers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* 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 { Observable } from 'rxjs';
import useObservable from 'react-use/lib/useObservable';
import cn from 'classnames';

export const AppWrapper: React.FunctionComponent<{
chromeVisible$: Observable<boolean>;
}> = ({ chromeVisible$, children }) => {
const visible = useObservable(chromeVisible$);
return <div className={cn('app-wrapper', { 'hidden-chrome': !visible })}>{children}</div>;
};

export const AppContainer: React.FunctionComponent<{
classes$: Observable<string[]>;
}> = ({ classes$, children }) => {
const classes = useObservable(classes$);
return <div className={cn('application', classes)}>{children}</div>;
};
7 changes: 4 additions & 3 deletions src/core/public/rendering/rendering_service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { InternalChromeStart } from '../chrome';
import { InternalApplicationStart } from '../application';
import { InjectedMetadataStart } from '../injected_metadata';
import { OverlayStart } from '../overlays';
import { AppWrapper, AppContainer } from './app_containers';

interface StartDeps {
application: InternalApplicationStart;
Expand Down Expand Up @@ -65,12 +66,12 @@ export class RenderingService {
{chromeUi}

{!legacyMode && (
<div className="app-wrapper">
<AppWrapper chromeVisible$={chrome.getIsVisible$()}>
<div className="app-wrapper-panel">
<div id="globalBannerList">{bannerUi}</div>
<div className="application">{appUi}</div>
<AppContainer classes$={chrome.getApplicationClasses$()}>{appUi}</AppContainer>
</div>
</div>
</AppWrapper>
)}

{legacyMode && <div ref={legacyRef} />}
Expand Down
14 changes: 14 additions & 0 deletions test/plugin_functional/test_suites/core_plugins/applications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,18 @@ export default function({ getService, getPageObjects }: PluginFunctionalProvider
const browser = getService('browser');
const appsMenu = getService('appsMenu');
const testSubjects = getService('testSubjects');
const find = getService('find');

const loadingScreenNotShown = async () =>
expect(await testSubjects.exists('kbnLoadingMessage')).to.be(false);

const loadingScreenShown = () => testSubjects.existOrFail('kbnLoadingMessage');

const getAppWrapperWidth = async () => {
const wrapper = await find.byClassName('app-wrapper');
return (await wrapper.getSize()).width;
};

const getKibanaUrl = (pathname?: string, search?: string) =>
url.format({
protocol: 'http:',
Expand Down Expand Up @@ -99,12 +105,20 @@ export default function({ getService, getPageObjects }: PluginFunctionalProvider
await PageObjects.common.navigateToApp('chromeless');
await loadingScreenNotShown();
expect(await testSubjects.exists('headerGlobalNav')).to.be(false);

const wrapperWidth = await getAppWrapperWidth();
const windowWidth = (await browser.getWindowSize()).width;
expect(wrapperWidth).to.eql(windowWidth);
});

it('navigating away from chromeless application shows chrome', async () => {
await PageObjects.common.navigateToApp('foo');
await loadingScreenNotShown();
expect(await testSubjects.exists('headerGlobalNav')).to.be(true);

const wrapperWidth = await getAppWrapperWidth();
const windowWidth = (await browser.getWindowSize()).width;
expect(wrapperWidth).to.be.below(windowWidth);
});

it.skip('can navigate from NP apps to legacy apps', async () => {
Expand Down

0 comments on commit b487fe5

Please sign in to comment.