[ui/UiApp] sort used modules so entry files can be cache keys (#15910)

* [ui/UiApp] sort used modules so entry files can be cache keys

* [ui/bundles+apps] test changes and verify assumptions down to appEntryTemplate
This commit is contained in:
Spencer 2018-01-09 13:41:27 -07:00 committed by GitHub
parent fb61c7d9ac
commit 2ee17cd1ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 138 additions and 9 deletions

View file

@ -1,9 +1,12 @@
import sinon from 'sinon';
import expect from 'expect.js';
import Chance from 'chance';
import { UiApp } from '../ui_app';
import { UiNavLink } from '../../ui_nav_links';
const chance = new Chance();
function createStubUiAppSpec(extraParams) {
return {
id: 'uiapp-test',
@ -51,7 +54,7 @@ function createUiApp(spec = createStubUiAppSpec(), kbnServer = createStubKbnServ
return new UiApp(kbnServer, spec);
}
describe('UiApp', () => {
describe('ui apps / UiApp', () => {
describe('constructor', () => {
it('throws an exception if an ID is not given', () => {
const spec = {}; // should have id property
@ -354,4 +357,45 @@ describe('UiApp', () => {
});
});
});
describe('#getModules', () => {
it('returns empty array by default', () => {
const app = createUiApp({ id: 'foo' });
expect(app.getModules()).to.eql([]);
});
it('returns main module if not using appExtensions', () => {
const app = createUiApp({ id: 'foo', main: 'bar' });
expect(app.getModules()).to.eql(['bar']);
});
it('returns appExtensions for used types only, in alphabetical order, starting with main module', () => {
const kbnServer = createStubKbnServer();
kbnServer.uiExports.appExtensions = {
abc: chance.shuffle([
'a',
'b',
'c',
]),
def: chance.shuffle([
'd',
'e',
'f',
])
};
const appExtensionType = chance.shuffle(Object.keys(kbnServer.uiExports.appExtensions))[0];
const appSpec = {
id: 'foo',
main: 'bar',
uses: [appExtensionType],
};
const app = createUiApp(appSpec, kbnServer);
expect(app.getModules()).to.eql([
'bar',
...appExtensionType.split(''),
]);
});
});
});

View file

@ -43,14 +43,16 @@ export class UiApp {
}
const { appExtensions = [] } = kbnServer.uiExports;
this._modules = []
.concat(this._main, ...uses.map(type => appExtensions[type] || []))
.filter(Boolean)
.reduce((modules, item) => (
modules.includes(item)
? modules
: modules.concat(item)
), []);
this._modules = [].concat(
this._main || [],
uses
// flatten appExtensions for used types
.reduce((acc, type) => acc.concat(appExtensions[type] || []), [])
// de-dupe app extension module ids
.reduce((acc, item) => !item || acc.includes(item) ? acc : acc.concat(item), [])
// sort app extension module ids alphabetically
.sort((a, b) => a.localeCompare(b))
);
if (!this.isHidden()) {
// unless an app is hidden it gets a navlink, but we only respond to `getNavLink()`

View file

@ -0,0 +1,30 @@
import sinon from 'sinon';
import expect from 'expect.js';
import { appEntryTemplate } from '../app_entry_template';
function createMockBundle() {
return {
getContext: sinon.stub().returns(''),
getRequires: sinon.stub().returns([])
};
}
describe('ui bundles / appEntryTemplate', () => {
it('embeds bundle.getContext() result', () => {
const bundle = createMockBundle();
bundle.getContext.returns('foo bar baz');
expect(appEntryTemplate(bundle)).to.contain('foo bar baz');
});
it('joins requires into list', () => {
const bundle = createMockBundle();
const requires = [
'foo',
'bar',
'baz'
];
bundle.getRequires.returns(requires);
expect(appEntryTemplate(bundle)).to.contain(requires.join('\n'));
});
});

View file

@ -0,0 +1,53 @@
import expect from 'expect.js';
import { UiBundle } from '../ui_bundle';
describe('ui bundles / UiBundle', () => {
describe('#getRequires', () => {
it('returns modules option as a list of require calls', () => {
const bundle = new UiBundle({
modules: [
'a',
'b',
'c'
]
});
expect(bundle.getRequires()).to.eql([
`require('a');`,
`require('b');`,
`require('c');`,
]);
});
it('does not sort modules', () => {
const bundle = new UiBundle({
modules: [
'c',
'a',
'b'
]
});
expect(bundle.getRequires()).to.eql([
`require('c');`,
`require('a');`,
`require('b');`,
]);
});
it('converts \\ to /', () => {
const bundle = new UiBundle({
modules: [
'a\\b\\c',
'd/e/f',
]
});
expect(bundle.getRequires()).to.eql([
`require('a/b/c');`,
`require('d/e/f');`,
]);
});
});
});