From 09a262c3b45a8020172afb0e07bbee2b2252babc Mon Sep 17 00:00:00 2001 From: spalger Date: Fri, 30 Mar 2018 15:45:57 -0700 Subject: [PATCH] [uiApp] replace uiApp.injectVars with server.injectUiAppVars() --- src/core_plugins/kibana/index.js | 4 +- src/core_plugins/timelion/index.js | 8 -- src/core_plugins/timelion/init.js | 9 +- src/ui/__tests__/fixtures/test_app/index.js | 10 +- .../__snapshots__/ui_apps_mixin.test.js.snap | 93 ++++++++++++++++ src/ui/ui_apps/__tests__/ui_app.js | 54 ---------- src/ui/ui_apps/ui_app.js | 25 +---- src/ui/ui_apps/ui_apps_mixin.js | 14 +++ src/ui/ui_apps/ui_apps_mixin.test.js | 100 ++++++++++++++++++ src/ui/ui_exports/ui_export_types/ui_apps.js | 4 +- src/ui/ui_render/ui_render_mixin.js | 2 +- 11 files changed, 227 insertions(+), 96 deletions(-) create mode 100644 src/ui/ui_apps/__snapshots__/ui_apps_mixin.test.js.snap create mode 100644 src/ui/ui_apps/ui_apps_mixin.test.js diff --git a/src/core_plugins/kibana/index.js b/src/core_plugins/kibana/index.js index 6175bfd1155990b..9a44918d5b20ea1 100644 --- a/src/core_plugins/kibana/index.js +++ b/src/core_plugins/kibana/index.js @@ -64,7 +64,6 @@ export default function (kibana) { 'docViews', 'embeddableFactories', ], - injectVars, }, links: [ @@ -155,8 +154,7 @@ export default function (kibana) { registerTutorials(server); server.expose('systemApi', systemApi); server.expose('handleEsError', handleEsError); - server.expose('injectVars', injectVars); - + server.injectUiAppVars('kibana', () => injectVars(server)); } }); } diff --git a/src/core_plugins/timelion/index.js b/src/core_plugins/timelion/index.js index 98f6121e5561121..2cea72d494e8cab 100644 --- a/src/core_plugins/timelion/index.js +++ b/src/core_plugins/timelion/index.js @@ -8,14 +8,6 @@ export default function (kibana) { description: 'Time series expressions for everything', icon: 'plugins/timelion/icon.svg', main: 'plugins/timelion/app', - injectVars: function (server) { - const config = server.config(); - return { - kbnIndex: config.get('kibana.index'), - esShardTimeout: config.get('elasticsearch.shardTimeout'), - esApiVersion: config.get('elasticsearch.apiVersion') - }; - }, uses: [ 'fieldFormats', 'savedObjectTypes' diff --git a/src/core_plugins/timelion/init.js b/src/core_plugins/timelion/init.js index bf562caefae5ac0..b8a90192f3668b5 100644 --- a/src/core_plugins/timelion/init.js +++ b/src/core_plugins/timelion/init.js @@ -24,5 +24,12 @@ export default function (server) { getFunction: getFunction }; - + server.injectUiAppVars('timelion', () => { + const config = server.config(); + return { + kbnIndex: config.get('kibana.index'), + esShardTimeout: config.get('elasticsearch.shardTimeout'), + esApiVersion: config.get('elasticsearch.apiVersion') + }; + }); } diff --git a/src/ui/__tests__/fixtures/test_app/index.js b/src/ui/__tests__/fixtures/test_app/index.js index 129804e69e4908e..92cb63830616845 100644 --- a/src/ui/__tests__/fixtures/test_app/index.js +++ b/src/ui/__tests__/fixtures/test_app/index.js @@ -3,11 +3,6 @@ export default kibana => new kibana.Plugin({ app: { name: 'test_app', main: 'plugins/test_app/index.js', - injectVars() { - return { - from_test_app: true - }; - } }, injectDefaultVars() { @@ -15,5 +10,10 @@ export default kibana => new kibana.Plugin({ from_defaults: true }; } + }, + init(server) { + server.injectUiAppVars('test_app', () => ({ + from_test_app: true + })); } }); diff --git a/src/ui/ui_apps/__snapshots__/ui_apps_mixin.test.js.snap b/src/ui/ui_apps/__snapshots__/ui_apps_mixin.test.js.snap new file mode 100644 index 000000000000000..c4d0bca9b553715 --- /dev/null +++ b/src/ui/ui_apps/__snapshots__/ui_apps_mixin.test.js.snap @@ -0,0 +1,93 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`UiAppsMixin creates kbnServer.uiApps from uiExports 1`] = ` +Array [ + StubUiApp { + "_hidden": true, + "_id": "foo", + }, + StubUiApp { + "_hidden": false, + "_id": "bar", + }, +] +`; + +exports[`UiAppsMixin decorates server with methods 1`] = ` +Array [ + Array [ + "server", + "getAllUiApps", + [Function], + ], + Array [ + "server", + "getUiAppById", + [Function], + ], + Array [ + "server", + "getHiddenUiAppById", + [Function], + ], + Array [ + "server", + "injectUiAppVars", + [Function], + ], + Array [ + "server", + "getInjectedUiAppVars", + [Function], + ], +] +`; + +exports[`UiAppsMixin server.getAllUiApps() returns hidden and non-hidden apps 1`] = ` +Array [ + StubUiApp { + "_hidden": true, + "_id": "foo", + }, + StubUiApp { + "_hidden": false, + "_id": "bar", + }, +] +`; + +exports[`UiAppsMixin server.getHiddenUiAppById() returns hidden apps when requested, undefined for non-hidden and unknown apps: hidden 1`] = ` +StubUiApp { + "_hidden": true, + "_id": "foo", +} +`; + +exports[`UiAppsMixin server.getHiddenUiAppById() returns hidden apps when requested, undefined for non-hidden and unknown apps: non-hidden 1`] = `undefined`; + +exports[`UiAppsMixin server.getHiddenUiAppById() returns hidden apps when requested, undefined for non-hidden and unknown apps: unknown 1`] = `undefined`; + +exports[`UiAppsMixin server.getUiAppById() returns non-hidden apps when requested, undefined for non-hidden and unknown apps: hidden 1`] = `undefined`; + +exports[`UiAppsMixin server.getUiAppById() returns non-hidden apps when requested, undefined for non-hidden and unknown apps: non-hidden 1`] = ` +StubUiApp { + "_hidden": false, + "_id": "bar", +} +`; + +exports[`UiAppsMixin server.getUiAppById() returns non-hidden apps when requested, undefined for non-hidden and unknown apps: unknown 1`] = `undefined`; + +exports[`UiAppsMixin server.injectUiAppVars()/server.getInjectedUiAppVars() stored injectVars provider and returns provider result when requested: bar 1`] = ` +Object { + "thisIsFoo": false, +} +`; + +exports[`UiAppsMixin server.injectUiAppVars()/server.getInjectedUiAppVars() stored injectVars provider and returns provider result when requested: foo 1`] = ` +Object { + "thisIsFoo": true, +} +`; + +exports[`UiAppsMixin server.injectUiAppVars()/server.getInjectedUiAppVars() stored injectVars provider and returns provider result when requested: unknown 1`] = `Object {}`; diff --git a/src/ui/ui_apps/__tests__/ui_app.js b/src/ui/ui_apps/__tests__/ui_app.js index de3f39bf2c54bb4..6ac0f60f3120f0e 100644 --- a/src/ui/ui_apps/__tests__/ui_app.js +++ b/src/ui/ui_apps/__tests__/ui_app.js @@ -23,9 +23,6 @@ function createStubUiAppSpec(extraParams) { 'chromeNavControls', 'hacks', ], - injectVars() { - return { foo: 'bar' }; - }, ...extraParams }; } @@ -84,10 +81,6 @@ describe('ui apps / UiApp', () => { expect(app.getNavLink()).to.be.a(UiNavLink); }); - it('has no injected vars', () => { - expect(app.getInjectedVars()).to.be(undefined); - }); - it('has an empty modules list', () => { expect(app.getModules()).to.eql([]); }); @@ -133,10 +126,6 @@ describe('ui apps / UiApp', () => { expect(app.getNavLink()).to.be(undefined); }); - it('has injected vars', () => { - expect(app.getInjectedVars()).to.eql({ foo: 'bar' }); - }); - it('includes main and hack modules', () => { expect(app.getModules()).to.eql([ 'main.js', @@ -295,49 +284,6 @@ describe('ui apps / UiApp', () => { }); describe('pluginId', () => { - describe('not specified', () => { - it('passes the root server and undefined for plugin/optoins to injectVars()', () => { - const injectVars = sinon.stub(); - const kbnServer = createStubKbnServer(); - createUiApp(createStubUiAppSpec({ injectVars }), kbnServer).getInjectedVars(); - - sinon.assert.calledOnce(injectVars); - sinon.assert.calledOn(injectVars, sinon.match.same(undefined)); - sinon.assert.calledWithExactly( - injectVars, - // server arg, uses root server because there is no plugin - sinon.match.same(kbnServer.server), - // options is undefined because there is no plugin - sinon.match.same(undefined) - ); - }); - }); - describe('matches a kbnServer plugin', () => { - it('passes the plugin/server/options from the plugin to injectVars()', () => { - const server = {}; - const options = {}; - const plugin = { - id: 'test plugin id', - getServer() { - return server; - }, - getOptions() { - return options; - } - }; - - const kbnServer = createStubKbnServer(); - kbnServer.plugins.push(plugin); - - const injectVars = sinon.stub(); - const spec = createStubUiAppSpec({ pluginId: plugin.id, injectVars }); - createUiApp(spec, kbnServer).getInjectedVars(); - - sinon.assert.calledOnce(injectVars); - sinon.assert.calledOn(injectVars, sinon.match.same(plugin)); - sinon.assert.calledWithExactly(injectVars, sinon.match.same(server), sinon.match.same(options)); - }); - }); describe('does not match a kbnServer plugin', () => { it('throws an error at instantiation', () => { expect(() => { diff --git a/src/ui/ui_apps/ui_app.js b/src/ui/ui_apps/ui_app.js index 4cd0fcc67bec522..27bebfae2118f59 100644 --- a/src/ui/ui_apps/ui_app.js +++ b/src/ui/ui_apps/ui_app.js @@ -13,7 +13,6 @@ export class UiApp { hidden, linkToLastSubUrl, listed, - injectVars, url = `/app/${id}`, uses = [] } = spec; @@ -22,6 +21,10 @@ export class UiApp { throw new Error('Every app must specify an id'); } + if (spec.injectVars) { + throw new Error(`uiApp.injectVars has been removed. Use server.injectUiAppVars('${id}', () => { ... })`); + } + this._id = id; this._main = main; this._title = title; @@ -32,7 +35,6 @@ export class UiApp { this._hidden = hidden; this._listed = listed; this._url = url; - this._injectedVarsProvider = injectVars; this._pluginId = pluginId; this._kbnServer = kbnServer; @@ -94,25 +96,6 @@ export class UiApp { } } - getInjectedVars() { - const provider = this._injectedVarsProvider; - const plugin = this._getPlugin(); - - if (!provider) { - return; - } - - return provider.call( - plugin, - plugin - ? plugin.getServer() - : this._kbnServer.server, - plugin - ? plugin.getOptions() - : undefined - ); - } - getModules() { return this._modules; } diff --git a/src/ui/ui_apps/ui_apps_mixin.js b/src/ui/ui_apps/ui_apps_mixin.js index a3d20e9fbffb1da..a0c57875cbc64cd 100644 --- a/src/ui/ui_apps/ui_apps_mixin.js +++ b/src/ui/ui_apps/ui_apps_mixin.js @@ -29,4 +29,18 @@ export function uiAppsMixin(kbnServer, server) { server.decorate('server', 'getAllUiApps', () => kbnServer.uiApps.slice(0)); server.decorate('server', 'getUiAppById', id => appsById.get(id)); server.decorate('server', 'getHiddenUiAppById', id => hiddenAppsById.get(id)); + + const injectedVarProviders = []; + server.decorate('server', 'injectUiAppVars', function (id, provider) { + injectedVarProviders.push({ id, provider, }); + }); + + server.decorate('server', 'getInjectedUiAppVars', async (id) => { + return await injectedVarProviders + .filter(p => p.id === id) + .reduce(async (acc, { provider }) => ({ + ...await acc, + ...await provider(server) + }), {}); + }); } diff --git a/src/ui/ui_apps/ui_apps_mixin.test.js b/src/ui/ui_apps/ui_apps_mixin.test.js new file mode 100644 index 000000000000000..78ab12ef3f9e1f6 --- /dev/null +++ b/src/ui/ui_apps/ui_apps_mixin.test.js @@ -0,0 +1,100 @@ +import { uiAppsMixin } from './ui_apps_mixin'; + +jest.mock('./ui_app', () => ({ + UiApp: class StubUiApp { + constructor(kbnServer, spec) { + this._id = spec.id; + this._hidden = !!spec.hidden; + } + getId() { + return this._id; + } + isHidden() { + return this._hidden; + } + } +})); + +describe('UiAppsMixin', () => { + let kbnServer; + let server; + + beforeAll(() => { + kbnServer = { + uiExports: { + uiAppSpecs: [ + { + id: 'foo', + hidden: true, + }, + { + id: 'bar', + hidden: false, + }, + ] + } + }; + + server = { + decorate: jest.fn((type, name, value) => { + if (type !== 'server') { + return; + } + + server[name] = value; + }), + }; + + uiAppsMixin(kbnServer, server); + }); + + it('creates kbnServer.uiApps from uiExports', () => { + expect(kbnServer.uiApps).toMatchSnapshot(); + }); + + it('decorates server with methods', () => { + expect(server.decorate.mock.calls).toMatchSnapshot(); + }); + + describe('server.getAllUiApps()', () => { + it('returns hidden and non-hidden apps', () => { + expect(server.getAllUiApps()).toMatchSnapshot(); + }); + }); + + describe('server.getUiAppById()', () => { + it('returns non-hidden apps when requested, undefined for non-hidden and unknown apps', () => { + expect(server.getUiAppById('foo')).toMatchSnapshot('hidden'); + expect(server.getUiAppById('bar')).toMatchSnapshot('non-hidden'); + expect(server.getUiAppById('baz')).toMatchSnapshot('unknown'); + }); + }); + + describe('server.getHiddenUiAppById()', () => { + it('returns hidden apps when requested, undefined for non-hidden and unknown apps', () => { + expect(server.getHiddenUiAppById('foo')).toMatchSnapshot('hidden'); + expect(server.getHiddenUiAppById('bar')).toMatchSnapshot('non-hidden'); + expect(server.getHiddenUiAppById('baz')).toMatchSnapshot('unknown'); + }); + }); + + describe('server.injectUiAppVars()/server.getInjectedUiAppVars()', () => { + it('stored injectVars provider and returns provider result when requested', async () => { + + server.injectUiAppVars('foo', () => ({ + thisIsFoo: true + })); + + server.injectUiAppVars('bar', async () => ({ + thisIsFoo: false + })); + + await expect(server.getInjectedUiAppVars('foo')) + .resolves.toMatchSnapshot('foo'); + await expect(server.getInjectedUiAppVars('bar')) + .resolves.toMatchSnapshot('bar'); + await expect(server.getInjectedUiAppVars('baz')) + .resolves.toMatchSnapshot('unknown'); + }); + }); +}); diff --git a/src/ui/ui_exports/ui_export_types/ui_apps.js b/src/ui/ui_exports/ui_export_types/ui_apps.js index 5e801c675f601b7..ab4c939d49a7321 100644 --- a/src/ui/ui_exports/ui_export_types/ui_apps.js +++ b/src/ui/ui_exports/ui_export_types/ui_apps.js @@ -1,4 +1,4 @@ -import { noop, uniq } from 'lodash'; +import { uniq } from 'lodash'; import { flatConcatAtType } from './reduce'; import { alias, mapSpec, wrap } from './modify_reduce'; @@ -16,7 +16,6 @@ function applySpecDefaults(spec, type, pluginSpec) { linkToLastSubUrl = true, listed = !hidden, templateName = 'ui_app', - injectVars = noop, url = `/app/${id}`, uses = [], } = spec; @@ -33,7 +32,6 @@ function applySpecDefaults(spec, type, pluginSpec) { linkToLastSubUrl, listed, templateName, - injectVars, url, uses: uniq([ ...uses, diff --git a/src/ui/ui_render/ui_render_mixin.js b/src/ui/ui_render/ui_render_mixin.js index 1bb367ad33b0f3b..6387177ed7c5aca 100644 --- a/src/ui/ui_render/ui_render_mixin.js +++ b/src/ui/ui_render/ui_render_mixin.js @@ -108,7 +108,7 @@ export function uiRenderMixin(kbnServer, server, config) { request, defaults( injectedVarsOverrides, - await app.getInjectedVars() || {}, + await server.getInjectedUiAppVars(app.getId()), defaultInjectedVars, ), )