mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
* Making schema async, and plugin discovery expose raw package jsons * Addressing some peer review comments * Modifying the way we emit the extendedConfig * Removing errant config * Adding filter and last so we only get the last non-null one
This commit is contained in:
parent
1fd0f7aae9
commit
c9cb8108e4
23 changed files with 485 additions and 292 deletions
|
@ -5,22 +5,17 @@ import { map as promiseMap, fromNode } from 'bluebird';
|
|||
import { Agent as HttpsAgent } from 'https';
|
||||
import { readFileSync } from 'fs';
|
||||
|
||||
import { Config } from '../../server/config/config';
|
||||
import { setupConnection } from '../../server/http/setup_connection';
|
||||
import { registerHapiPlugins } from '../../server/http/register_hapi_plugins';
|
||||
import { setupLogging } from '../../server/logging';
|
||||
import { transformDeprecations } from '../../server/config/transform_deprecations';
|
||||
|
||||
const alphabet = 'abcdefghijklmnopqrztuvwxyz'.split('');
|
||||
|
||||
export default class BasePathProxy {
|
||||
constructor(clusterManager, userSettings) {
|
||||
constructor(clusterManager, config) {
|
||||
this.clusterManager = clusterManager;
|
||||
this.server = new Server();
|
||||
|
||||
const settings = transformDeprecations(userSettings);
|
||||
const config = Config.withDefaultSchema(settings);
|
||||
|
||||
this.targetPort = config.get('dev.basePathProxyTarget');
|
||||
this.basePath = config.get('server.basePath');
|
||||
|
||||
|
|
|
@ -4,11 +4,20 @@ import { debounce, invoke, bindAll, once, uniq } from 'lodash';
|
|||
import Log from '../log';
|
||||
import Worker from './worker';
|
||||
import BasePathProxy from './base_path_proxy';
|
||||
import { Config } from '../../server/config/config';
|
||||
import { transformDeprecations } from '../../server/config/transform_deprecations';
|
||||
|
||||
process.env.kbnWorkerType = 'managr';
|
||||
|
||||
export default class ClusterManager {
|
||||
constructor(opts = {}, settings = {}) {
|
||||
static async create(opts = {}, settings = {}) {
|
||||
const transformedSettings = transformDeprecations(settings);
|
||||
const config = await Config.withDefaultSchema(transformedSettings);
|
||||
|
||||
return new ClusterManager(opts, config);
|
||||
}
|
||||
|
||||
constructor(opts, config) {
|
||||
this.log = new Log(opts.quiet, opts.silent);
|
||||
this.addedCount = 0;
|
||||
|
||||
|
@ -19,7 +28,7 @@ export default class ClusterManager {
|
|||
];
|
||||
|
||||
if (opts.basePath) {
|
||||
this.basePathProxy = new BasePathProxy(this, settings);
|
||||
this.basePathProxy = new BasePathProxy(this, config);
|
||||
|
||||
optimizerArgv.push(
|
||||
`--server.basePath=${this.basePathProxy.basePath}`,
|
||||
|
@ -63,14 +72,16 @@ export default class ClusterManager {
|
|||
bindAll(this, 'onWatcherAdd', 'onWatcherError', 'onWatcherChange');
|
||||
|
||||
if (opts.watch) {
|
||||
const pluginPaths = config.get('plugins.paths');
|
||||
const scanDirs = config.get('plugins.scanDirs');
|
||||
const extraPaths = [
|
||||
...settings.plugins.paths,
|
||||
...settings.plugins.scanDirs,
|
||||
...pluginPaths,
|
||||
...scanDirs,
|
||||
];
|
||||
|
||||
const extraIgnores = settings.plugins.scanDirs
|
||||
const extraIgnores = scanDirs
|
||||
.map(scanDir => resolve(scanDir, '*'))
|
||||
.concat(settings.plugins.paths)
|
||||
.concat(pluginPaths)
|
||||
.reduce((acc, path) => acc.concat(
|
||||
resolve(path, 'test'),
|
||||
resolve(path, 'build'),
|
||||
|
|
|
@ -26,8 +26,8 @@ describe('CLI cluster manager', function () {
|
|||
sandbox.restore();
|
||||
});
|
||||
|
||||
it('has two workers', function () {
|
||||
const manager = new ClusterManager({});
|
||||
it('has two workers', async function () {
|
||||
const manager = await ClusterManager.create({});
|
||||
|
||||
expect(manager.workers).toHaveLength(2);
|
||||
for (const worker of manager.workers) expect(worker).toBeInstanceOf(Worker);
|
||||
|
@ -36,8 +36,8 @@ describe('CLI cluster manager', function () {
|
|||
expect(manager.server).toBeInstanceOf(Worker);
|
||||
});
|
||||
|
||||
it('delivers broadcast messages to other workers', function () {
|
||||
const manager = new ClusterManager({});
|
||||
it('delivers broadcast messages to other workers', async function () {
|
||||
const manager = await ClusterManager.create({});
|
||||
|
||||
for (const worker of manager.workers) {
|
||||
Worker.prototype.start.call(worker);// bypass the debounced start method
|
||||
|
|
|
@ -184,7 +184,7 @@ export default function (program) {
|
|||
if (CAN_CLUSTER && opts.dev && !isWorker) {
|
||||
// stop processing the action and handoff to cluster manager
|
||||
const ClusterManager = require(CLUSTER_MANAGER_PATH);
|
||||
new ClusterManager(opts, settings);
|
||||
await ClusterManager.create(opts, settings);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -216,10 +216,10 @@ export default function (program) {
|
|||
process.exit(exitCode);
|
||||
}
|
||||
|
||||
process.on('SIGHUP', function reloadConfig() {
|
||||
process.on('SIGHUP', async function reloadConfig() {
|
||||
const settings = getCurrentSettings();
|
||||
kbnServer.server.log(['info', 'config'], 'Reloading logging configuration due to SIGHUP.');
|
||||
kbnServer.applyLoggingConfiguration(settings);
|
||||
await kbnServer.applyLoggingConfiguration(settings);
|
||||
kbnServer.server.log(['info', 'config'], 'Reloaded logging configuration due to SIGHUP.');
|
||||
});
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { resolve } from 'path';
|
||||
|
||||
import expect from 'expect.js';
|
||||
import { isEqual } from 'lodash';
|
||||
import { findPluginSpecs } from '../find_plugin_specs';
|
||||
import { PluginSpec } from '../plugin_spec';
|
||||
|
||||
|
@ -11,107 +12,183 @@ describe('plugin discovery', () => {
|
|||
describe('findPluginSpecs()', function () {
|
||||
this.timeout(10000);
|
||||
|
||||
it('finds specs for specified plugin paths', async () => {
|
||||
const { spec$ } = findPluginSpecs({
|
||||
plugins: {
|
||||
paths: [
|
||||
resolve(PLUGIN_FIXTURES, 'foo'),
|
||||
resolve(PLUGIN_FIXTURES, 'bar'),
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
const specs = await spec$.toArray().toPromise();
|
||||
expect(specs).to.have.length(3);
|
||||
specs.forEach(spec => {
|
||||
expect(spec).to.be.a(PluginSpec);
|
||||
});
|
||||
expect(specs.map(s => s.getId()).sort())
|
||||
.to.eql(['bar:one', 'bar:two', 'foo']);
|
||||
});
|
||||
|
||||
it('finds all specs in scanDirs', async () => {
|
||||
const { spec$ } = findPluginSpecs({
|
||||
// used to ensure the dev_mode plugin is enabled
|
||||
env: 'development',
|
||||
|
||||
plugins: {
|
||||
scanDirs: [PLUGIN_FIXTURES]
|
||||
}
|
||||
});
|
||||
|
||||
const specs = await spec$.toArray().toPromise();
|
||||
expect(specs).to.have.length(3);
|
||||
specs.forEach(spec => {
|
||||
expect(spec).to.be.a(PluginSpec);
|
||||
});
|
||||
expect(specs.map(s => s.getId()).sort())
|
||||
.to.eql(['bar:one', 'bar:two', 'foo']);
|
||||
});
|
||||
|
||||
it('does not find disabled plugins', async () => {
|
||||
const { spec$ } = findPluginSpecs({
|
||||
'bar:one': {
|
||||
enabled: false
|
||||
},
|
||||
|
||||
plugins: {
|
||||
paths: [
|
||||
resolve(PLUGIN_FIXTURES, 'foo'),
|
||||
resolve(PLUGIN_FIXTURES, 'bar')
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
const specs = await spec$.toArray().toPromise();
|
||||
expect(specs).to.have.length(2);
|
||||
specs.forEach(spec => {
|
||||
expect(spec).to.be.a(PluginSpec);
|
||||
});
|
||||
expect(specs.map(s => s.getId()).sort())
|
||||
.to.eql(['bar:two', 'foo']);
|
||||
});
|
||||
|
||||
it('dedupes duplicate packs', async () => {
|
||||
const { spec$ } = findPluginSpecs({
|
||||
plugins: {
|
||||
scanDirs: [PLUGIN_FIXTURES],
|
||||
paths: [
|
||||
resolve(PLUGIN_FIXTURES, 'foo'),
|
||||
resolve(PLUGIN_FIXTURES, 'foo'),
|
||||
resolve(PLUGIN_FIXTURES, 'bar'),
|
||||
resolve(PLUGIN_FIXTURES, 'bar'),
|
||||
],
|
||||
}
|
||||
});
|
||||
|
||||
const specs = await spec$.toArray().toPromise();
|
||||
expect(specs).to.have.length(3);
|
||||
specs.forEach(spec => {
|
||||
expect(spec).to.be.a(PluginSpec);
|
||||
});
|
||||
expect(specs.map(s => s.getId()).sort())
|
||||
.to.eql(['bar:one', 'bar:two', 'foo']);
|
||||
});
|
||||
|
||||
describe('conflicting plugin spec ids', () => {
|
||||
it('fails with informative message', async () => {
|
||||
describe('spec$', () => {
|
||||
it('finds specs for specified plugin paths', async () => {
|
||||
const { spec$ } = findPluginSpecs({
|
||||
plugins: {
|
||||
scanDirs: [],
|
||||
paths: [
|
||||
resolve(CONFLICT_FIXTURES, 'foo'),
|
||||
resolve(PLUGIN_FIXTURES, 'foo'),
|
||||
resolve(PLUGIN_FIXTURES, 'bar'),
|
||||
resolve(PLUGIN_FIXTURES, 'broken'),
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
const specs = await spec$.toArray().toPromise();
|
||||
expect(specs).to.have.length(3);
|
||||
specs.forEach(spec => {
|
||||
expect(spec).to.be.a(PluginSpec);
|
||||
});
|
||||
expect(specs.map(s => s.getId()).sort())
|
||||
.to.eql(['bar:one', 'bar:two', 'foo']);
|
||||
});
|
||||
|
||||
it('finds all specs in scanDirs', async () => {
|
||||
const { spec$ } = findPluginSpecs({
|
||||
// used to ensure the dev_mode plugin is enabled
|
||||
env: 'development',
|
||||
|
||||
plugins: {
|
||||
scanDirs: [PLUGIN_FIXTURES]
|
||||
}
|
||||
});
|
||||
|
||||
const specs = await spec$.toArray().toPromise();
|
||||
expect(specs).to.have.length(3);
|
||||
specs.forEach(spec => {
|
||||
expect(spec).to.be.a(PluginSpec);
|
||||
});
|
||||
expect(specs.map(s => s.getId()).sort())
|
||||
.to.eql(['bar:one', 'bar:two', 'foo']);
|
||||
});
|
||||
|
||||
it('does not find disabled plugins', async () => {
|
||||
const { spec$ } = findPluginSpecs({
|
||||
'bar:one': {
|
||||
enabled: false
|
||||
},
|
||||
|
||||
plugins: {
|
||||
paths: [
|
||||
resolve(PLUGIN_FIXTURES, 'foo'),
|
||||
resolve(PLUGIN_FIXTURES, 'bar'),
|
||||
resolve(PLUGIN_FIXTURES, 'broken'),
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
const specs = await spec$.toArray().toPromise();
|
||||
expect(specs).to.have.length(2);
|
||||
specs.forEach(spec => {
|
||||
expect(spec).to.be.a(PluginSpec);
|
||||
});
|
||||
expect(specs.map(s => s.getId()).sort())
|
||||
.to.eql(['bar:two', 'foo']);
|
||||
});
|
||||
|
||||
it('dedupes duplicate packs', async () => {
|
||||
const { spec$ } = findPluginSpecs({
|
||||
plugins: {
|
||||
scanDirs: [PLUGIN_FIXTURES],
|
||||
paths: [
|
||||
resolve(PLUGIN_FIXTURES, 'foo'),
|
||||
resolve(PLUGIN_FIXTURES, 'foo'),
|
||||
resolve(PLUGIN_FIXTURES, 'bar'),
|
||||
resolve(PLUGIN_FIXTURES, 'bar'),
|
||||
resolve(PLUGIN_FIXTURES, 'broken'),
|
||||
resolve(PLUGIN_FIXTURES, 'broken'),
|
||||
],
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
await spec$.toArray().toPromise();
|
||||
throw new Error('expected spec$ to throw an error');
|
||||
} catch (error) {
|
||||
expect(error.message).to.contain('Multple plugins found with the id "foo"');
|
||||
expect(error.message).to.contain(CONFLICT_FIXTURES);
|
||||
}
|
||||
const specs = await spec$.toArray().toPromise();
|
||||
expect(specs).to.have.length(3);
|
||||
specs.forEach(spec => {
|
||||
expect(spec).to.be.a(PluginSpec);
|
||||
});
|
||||
expect(specs.map(s => s.getId()).sort())
|
||||
.to.eql(['bar:one', 'bar:two', 'foo']);
|
||||
});
|
||||
|
||||
describe('conflicting plugin spec ids', () => {
|
||||
it('fails with informative message', async () => {
|
||||
const { spec$ } = findPluginSpecs({
|
||||
plugins: {
|
||||
scanDirs: [],
|
||||
paths: [
|
||||
resolve(CONFLICT_FIXTURES, 'foo'),
|
||||
],
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
await spec$.toArray().toPromise();
|
||||
throw new Error('expected spec$ to throw an error');
|
||||
} catch (error) {
|
||||
expect(error.message).to.contain('Multple plugins found with the id "foo"');
|
||||
expect(error.message).to.contain(CONFLICT_FIXTURES);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('packageJson$', () => {
|
||||
const checkPackageJsons = (packageJsons) => {
|
||||
expect(packageJsons).to.have.length(2);
|
||||
const package1 = packageJsons.find(packageJson => isEqual({
|
||||
directoryPath: resolve(PLUGIN_FIXTURES, 'foo'),
|
||||
contents: {
|
||||
name: 'foo',
|
||||
version: 'kibana'
|
||||
}
|
||||
}, packageJson));
|
||||
expect(package1).to.be.an(Object);
|
||||
const package2 = packageJsons.find(packageJson => isEqual({
|
||||
directoryPath: resolve(PLUGIN_FIXTURES, 'bar'),
|
||||
contents: {
|
||||
name: 'foo',
|
||||
version: 'kibana'
|
||||
}
|
||||
}, packageJson));
|
||||
expect(package2).to.be.an(Object);
|
||||
};
|
||||
|
||||
it('finds packageJson for specified plugin paths', async () => {
|
||||
const { packageJson$ } = findPluginSpecs({
|
||||
plugins: {
|
||||
paths: [
|
||||
resolve(PLUGIN_FIXTURES, 'foo'),
|
||||
resolve(PLUGIN_FIXTURES, 'bar'),
|
||||
resolve(PLUGIN_FIXTURES, 'broken'),
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
const packageJsons = await packageJson$.toArray().toPromise();
|
||||
checkPackageJsons(packageJsons);
|
||||
});
|
||||
|
||||
it('finds all packageJsons in scanDirs', async () => {
|
||||
const { packageJson$ } = findPluginSpecs({
|
||||
// used to ensure the dev_mode plugin is enabled
|
||||
env: 'development',
|
||||
|
||||
plugins: {
|
||||
scanDirs: [PLUGIN_FIXTURES]
|
||||
}
|
||||
});
|
||||
|
||||
const packageJsons = await packageJson$.toArray().toPromise();
|
||||
checkPackageJsons(packageJsons);
|
||||
});
|
||||
|
||||
it('dedupes duplicate packageJson', async () => {
|
||||
const { packageJson$ } = findPluginSpecs({
|
||||
plugins: {
|
||||
scanDirs: [PLUGIN_FIXTURES],
|
||||
paths: [
|
||||
resolve(PLUGIN_FIXTURES, 'foo'),
|
||||
resolve(PLUGIN_FIXTURES, 'foo'),
|
||||
resolve(PLUGIN_FIXTURES, 'bar'),
|
||||
resolve(PLUGIN_FIXTURES, 'bar'),
|
||||
resolve(PLUGIN_FIXTURES, 'broken'),
|
||||
resolve(PLUGIN_FIXTURES, 'broken'),
|
||||
],
|
||||
}
|
||||
});
|
||||
|
||||
const packageJsons = await packageJson$.toArray().toPromise();
|
||||
checkPackageJsons(packageJsons);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
export default {
|
||||
foo: 'bar'
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "baz",
|
||||
"version": "kibana"
|
||||
}
|
|
@ -9,8 +9,9 @@ import {
|
|||
} from './plugin_config';
|
||||
|
||||
import {
|
||||
createPackAtPath$,
|
||||
createPacksInDirectory$,
|
||||
createPack$,
|
||||
createPackageJsonAtPath$,
|
||||
createPackageJsonsInDirectory$,
|
||||
} from './plugin_pack';
|
||||
|
||||
import {
|
||||
|
@ -18,8 +19,8 @@ import {
|
|||
isInvalidPackError,
|
||||
} from './errors';
|
||||
|
||||
function defaultConfig(settings) {
|
||||
return Config.withDefaultSchema(
|
||||
async function defaultConfig(settings) {
|
||||
return await Config.withDefaultSchema(
|
||||
transformDeprecations(settings)
|
||||
);
|
||||
}
|
||||
|
@ -45,8 +46,8 @@ function getDistinctKeyForFindResult(result) {
|
|||
}
|
||||
|
||||
// packs are distinct by their absolute and real path
|
||||
if (result.pack) {
|
||||
return realpathSync(result.pack.getPath());
|
||||
if (result.packageJson) {
|
||||
return realpathSync(result.packageJson.directoryPath);
|
||||
}
|
||||
|
||||
// non error/pack results shouldn't exist, but if they do they are all unique
|
||||
|
@ -75,92 +76,114 @@ function groupSpecsById(specs) {
|
|||
* the config from discovered plugin specs
|
||||
* @return {Object<name,Rx>}
|
||||
*/
|
||||
export function findPluginSpecs(settings, config = defaultConfig(settings)) {
|
||||
export function findPluginSpecs(settings, configToMutate) {
|
||||
const config$ = Observable.defer(async () => {
|
||||
if (configToMutate) {
|
||||
return configToMutate;
|
||||
}
|
||||
|
||||
return await defaultConfig(settings);
|
||||
}).shareReplay();
|
||||
|
||||
// find plugin packs in configured paths/dirs
|
||||
const find$ = Observable.merge(
|
||||
...config.get('plugins.paths').map(createPackAtPath$),
|
||||
...config.get('plugins.scanDirs').map(createPacksInDirectory$)
|
||||
)
|
||||
const packageJson$ = config$.mergeMap(config => {
|
||||
return Observable.merge(
|
||||
...config.get('plugins.paths').map(createPackageJsonAtPath$),
|
||||
...config.get('plugins.scanDirs').map(createPackageJsonsInDirectory$)
|
||||
);
|
||||
})
|
||||
.distinct(getDistinctKeyForFindResult)
|
||||
.share();
|
||||
|
||||
const extendConfig$ = find$
|
||||
// get the specs for each found plugin pack
|
||||
.mergeMap(({ pack }) => (
|
||||
pack ? pack.getPluginSpecs() : []
|
||||
))
|
||||
// make sure that none of the plugin specs have conflicting ids, fail
|
||||
// early if conflicts detected or merge the specs back into the stream
|
||||
.toArray()
|
||||
.mergeMap(allSpecs => {
|
||||
for (const [id, specs] of groupSpecsById(allSpecs)) {
|
||||
if (specs.length > 1) {
|
||||
throw new Error(
|
||||
`Multple plugins found with the id "${id}":\n${
|
||||
specs.map(spec => ` - ${id} at ${spec.getPath()}`).join('\n')
|
||||
}`
|
||||
);
|
||||
const pack$ = createPack$(packageJson$)
|
||||
.share();
|
||||
|
||||
const extendConfig$ = config$.mergeMap(config => {
|
||||
return pack$
|
||||
// get the specs for each found plugin pack
|
||||
.mergeMap(({ pack }) => (
|
||||
pack ? pack.getPluginSpecs() : []
|
||||
))
|
||||
// make sure that none of the plugin specs have conflicting ids, fail
|
||||
// early if conflicts detected or merge the specs back into the stream
|
||||
.toArray()
|
||||
.mergeMap(allSpecs => {
|
||||
for (const [id, specs] of groupSpecsById(allSpecs)) {
|
||||
if (specs.length > 1) {
|
||||
throw new Error(
|
||||
`Multple plugins found with the id "${id}":\n${
|
||||
specs.map(spec => ` - ${id} at ${spec.getPath()}`).join('\n')
|
||||
}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return allSpecs;
|
||||
})
|
||||
.mergeMap(async (spec) => {
|
||||
// extend the config service with this plugin spec and
|
||||
// collect its deprecations messages if some of its
|
||||
// settings are outdated
|
||||
const deprecations = [];
|
||||
await extendConfigService(spec, config, settings, (message) => {
|
||||
deprecations.push({ spec, message });
|
||||
return allSpecs;
|
||||
})
|
||||
.mergeMap(async (spec) => {
|
||||
// extend the config service with this plugin spec and
|
||||
// collect its deprecations messages if some of its
|
||||
// settings are outdated
|
||||
const deprecations = [];
|
||||
await extendConfigService(spec, config, settings, (message) => {
|
||||
deprecations.push({ spec, message });
|
||||
});
|
||||
|
||||
return {
|
||||
spec,
|
||||
deprecations,
|
||||
};
|
||||
})
|
||||
// extend the config with all plugins before determining enabled status
|
||||
.let(bufferAllResults)
|
||||
.map(({ spec, deprecations }) => {
|
||||
const isRightVersion = spec.isVersionCompatible(config.get('pkg.version'));
|
||||
const enabled = isRightVersion && spec.isEnabled(config);
|
||||
return {
|
||||
config,
|
||||
spec,
|
||||
deprecations,
|
||||
enabledSpecs: enabled ? [spec] : [],
|
||||
disabledSpecs: enabled ? [] : [spec],
|
||||
invalidVersionSpecs: isRightVersion ? [] : [spec],
|
||||
};
|
||||
})
|
||||
// determine which plugins are disabled before actually removing things from the config
|
||||
.let(bufferAllResults)
|
||||
.do(result => {
|
||||
for (const spec of result.disabledSpecs) {
|
||||
disableConfigExtension(spec, config);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
spec,
|
||||
deprecations,
|
||||
};
|
||||
})
|
||||
// extend the config with all plugins before determining enabled status
|
||||
.let(bufferAllResults)
|
||||
.map(({ spec, deprecations }) => {
|
||||
const isRightVersion = spec.isVersionCompatible(config.get('pkg.version'));
|
||||
const enabled = isRightVersion && spec.isEnabled(config);
|
||||
return {
|
||||
spec,
|
||||
deprecations,
|
||||
enabledSpecs: enabled ? [spec] : [],
|
||||
disabledSpecs: enabled ? [] : [spec],
|
||||
invalidVersionSpecs: isRightVersion ? [] : [spec],
|
||||
};
|
||||
})
|
||||
// determine which plugins are disabled before actually removing things from the config
|
||||
.let(bufferAllResults)
|
||||
.do(result => {
|
||||
for (const spec of result.disabledSpecs) {
|
||||
disableConfigExtension(spec, config);
|
||||
}
|
||||
})
|
||||
})
|
||||
.share();
|
||||
|
||||
return {
|
||||
// package JSONs found when searching configure paths
|
||||
packageJson$: packageJson$
|
||||
.mergeMap(result => (
|
||||
result.packageJson ? [result.packageJson] : []
|
||||
)),
|
||||
|
||||
// plugin packs found when searching configured paths
|
||||
pack$: find$
|
||||
pack$: pack$
|
||||
.mergeMap(result => (
|
||||
result.pack ? [result.pack] : []
|
||||
)),
|
||||
|
||||
// errors caused by invalid directories of plugin directories
|
||||
invalidDirectoryError$: find$
|
||||
invalidDirectoryError$: pack$
|
||||
.mergeMap(result => (
|
||||
isInvalidDirectoryError(result.error) ? [result.error] : []
|
||||
)),
|
||||
|
||||
// errors caused by directories that we expected to be plugin but were invalid
|
||||
invalidPackError$: find$
|
||||
invalidPackError$: pack$
|
||||
.mergeMap(result => (
|
||||
isInvalidPackError(result.error) ? [result.error] : []
|
||||
)),
|
||||
|
||||
otherError$: find$
|
||||
otherError$: pack$
|
||||
.mergeMap(result => (
|
||||
isUnhandledError(result.error) ? [result.error] : []
|
||||
)),
|
||||
|
@ -173,8 +196,9 @@ export function findPluginSpecs(settings, config = defaultConfig(settings)) {
|
|||
// the config service we extended with all of the plugin specs,
|
||||
// only emitted once it is fully extended by all
|
||||
extendedConfig$: extendConfig$
|
||||
.ignoreElements()
|
||||
.concat([config]),
|
||||
.mergeMap(result => result.config)
|
||||
.filter(Boolean)
|
||||
.last(),
|
||||
|
||||
// all enabled PluginSpec objects
|
||||
spec$: extendConfig$
|
||||
|
|
|
@ -77,21 +77,21 @@ describe('plugin discovery/extend config service', () => {
|
|||
});
|
||||
|
||||
it('adds the schema for a plugin spec to its config prefix', async () => {
|
||||
const config = Config.withDefaultSchema();
|
||||
const config = await Config.withDefaultSchema();
|
||||
expect(config.has('foo.bar.baz')).to.be(false);
|
||||
await extendConfigService(pluginSpec, config);
|
||||
expect(config.has('foo.bar.baz')).to.be(true);
|
||||
});
|
||||
|
||||
it('initializes it with the default settings', async () => {
|
||||
const config = Config.withDefaultSchema();
|
||||
const config = await Config.withDefaultSchema();
|
||||
await extendConfigService(pluginSpec, config);
|
||||
expect(config.get('foo.bar.baz.enabled')).to.be(true);
|
||||
expect(config.get('foo.bar.baz.test')).to.be('bonk');
|
||||
});
|
||||
|
||||
it('initializes it with values from root settings if defined', async () => {
|
||||
const config = Config.withDefaultSchema();
|
||||
const config = await Config.withDefaultSchema();
|
||||
await extendConfigService(pluginSpec, config, {
|
||||
foo: {
|
||||
bar: {
|
||||
|
@ -106,7 +106,7 @@ describe('plugin discovery/extend config service', () => {
|
|||
});
|
||||
|
||||
it('throws if root settings are invalid', async () => {
|
||||
const config = Config.withDefaultSchema();
|
||||
const config = await Config.withDefaultSchema();
|
||||
try {
|
||||
await extendConfigService(pluginSpec, config, {
|
||||
foo: {
|
||||
|
@ -126,7 +126,7 @@ describe('plugin discovery/extend config service', () => {
|
|||
});
|
||||
|
||||
it('calls logDeprecation() with deprecation messages', async () => {
|
||||
const config = Config.withDefaultSchema();
|
||||
const config = await Config.withDefaultSchema();
|
||||
const logDeprecation = sinon.stub();
|
||||
await extendConfigService(pluginSpec, config, {
|
||||
foo: {
|
||||
|
@ -142,7 +142,7 @@ describe('plugin discovery/extend config service', () => {
|
|||
});
|
||||
|
||||
it('uses settings after transforming deprecations', async () => {
|
||||
const config = Config.withDefaultSchema();
|
||||
const config = await Config.withDefaultSchema();
|
||||
await extendConfigService(pluginSpec, config, {
|
||||
foo: {
|
||||
bar: {
|
||||
|
@ -158,7 +158,7 @@ describe('plugin discovery/extend config service', () => {
|
|||
|
||||
describe('disableConfigExtension()', () => {
|
||||
it('removes added config', async () => {
|
||||
const config = Config.withDefaultSchema();
|
||||
const config = await Config.withDefaultSchema();
|
||||
await extendConfigService(pluginSpec, config);
|
||||
expect(config.has('foo.bar.baz.test')).to.be(true);
|
||||
await disableConfigExtension(pluginSpec, config);
|
||||
|
@ -166,7 +166,7 @@ describe('plugin discovery/extend config service', () => {
|
|||
});
|
||||
|
||||
it('leaves {configPrefix}.enabled config', async () => {
|
||||
const config = Config.withDefaultSchema();
|
||||
const config = await Config.withDefaultSchema();
|
||||
expect(config.has('foo.bar.baz.enabled')).to.be(false);
|
||||
await extendConfigService(pluginSpec, config);
|
||||
expect(config.get('foo.bar.baz.enabled')).to.be(true);
|
||||
|
|
62
src/plugin_discovery/plugin_pack/__tests__/create_pack.js
Normal file
62
src/plugin_discovery/plugin_pack/__tests__/create_pack.js
Normal file
|
@ -0,0 +1,62 @@
|
|||
import { resolve } from 'path';
|
||||
import { Observable } from 'rxjs';
|
||||
import expect from 'expect.js';
|
||||
|
||||
import { createPack$ } from '../create_pack';
|
||||
import { PluginPack } from '../plugin_pack';
|
||||
|
||||
import {
|
||||
PLUGINS_DIR,
|
||||
assertInvalidPackError,
|
||||
} from './utils';
|
||||
|
||||
describe('plugin discovery/create pack', () => {
|
||||
it('creates PluginPack', async () => {
|
||||
const packageJson$ = Observable.from([
|
||||
{
|
||||
packageJson: {
|
||||
directoryPath: resolve(PLUGINS_DIR, 'prebuilt'),
|
||||
contents: {
|
||||
name: 'prebuilt'
|
||||
}
|
||||
}
|
||||
}
|
||||
]);
|
||||
const results = await createPack$(packageJson$).toArray().toPromise();
|
||||
expect(results).to.have.length(1);
|
||||
expect(results[0]).to.only.have.keys(['pack']);
|
||||
const { pack } = results[0];
|
||||
expect(pack).to.be.a(PluginPack);
|
||||
});
|
||||
|
||||
describe('errors thrown', () => {
|
||||
async function checkError(path, check) {
|
||||
const packageJson$ = Observable.from([{
|
||||
packageJson: {
|
||||
directoryPath: path
|
||||
}
|
||||
}]);
|
||||
|
||||
const results = await createPack$(packageJson$).toArray().toPromise();
|
||||
expect(results).to.have.length(1);
|
||||
expect(results[0]).to.only.have.keys(['error']);
|
||||
const { error } = results[0];
|
||||
await check(error);
|
||||
}
|
||||
it('default export is an object', () => checkError(resolve(PLUGINS_DIR, 'exports_object'), error => {
|
||||
assertInvalidPackError(error);
|
||||
expect(error.message).to.contain('must export a function');
|
||||
}));
|
||||
it('default export is an number', () => checkError(resolve(PLUGINS_DIR, 'exports_number'), error => {
|
||||
assertInvalidPackError(error);
|
||||
expect(error.message).to.contain('must export a function');
|
||||
}));
|
||||
it('default export is an string', () => checkError(resolve(PLUGINS_DIR, 'exports_string'), error => {
|
||||
assertInvalidPackError(error);
|
||||
expect(error.message).to.contain('must export a function');
|
||||
}));
|
||||
it('directory with code that fails when required', () => checkError(resolve(PLUGINS_DIR, 'broken_code'), error => {
|
||||
expect(error.message).to.contain('Cannot find module \'does-not-exist\'');
|
||||
}));
|
||||
});
|
||||
});
|
|
@ -2,8 +2,7 @@ import { resolve } from 'path';
|
|||
|
||||
import expect from 'expect.js';
|
||||
|
||||
import { createPackAtPath$ } from '../pack_at_path';
|
||||
import { PluginPack } from '../plugin_pack';
|
||||
import { createPackageJsonAtPath$ } from '../package_json_at_path';
|
||||
import {
|
||||
PLUGINS_DIR,
|
||||
assertInvalidPackError,
|
||||
|
@ -12,20 +11,22 @@ import {
|
|||
|
||||
|
||||
describe('plugin discovery/plugin_pack', () => {
|
||||
describe('createPackAtPath$()', () => {
|
||||
describe('createPackageJsonAtPath$()', () => {
|
||||
it('returns an observable', () => {
|
||||
expect(createPackAtPath$())
|
||||
expect(createPackageJsonAtPath$())
|
||||
.to.have.property('subscribe').a('function');
|
||||
});
|
||||
it('gets the default provider from prebuilt babel modules', async () => {
|
||||
const results = await createPackAtPath$(resolve(PLUGINS_DIR, 'prebuilt')).toArray().toPromise();
|
||||
const results = await createPackageJsonAtPath$(resolve(PLUGINS_DIR, 'prebuilt')).toArray().toPromise();
|
||||
expect(results).to.have.length(1);
|
||||
expect(results[0]).to.only.have.keys(['pack']);
|
||||
expect(results[0].pack).to.be.a(PluginPack);
|
||||
expect(results[0]).to.only.have.keys(['packageJson']);
|
||||
expect(results[0].packageJson).to.be.an(Object);
|
||||
expect(results[0].packageJson.directoryPath).to.be(resolve(PLUGINS_DIR, 'prebuilt'));
|
||||
expect(results[0].packageJson.contents).to.eql({ name: 'prebuilt' });
|
||||
});
|
||||
describe('errors emitted as { error } results', () => {
|
||||
async function checkError(path, check) {
|
||||
const results = await createPackAtPath$(path).toArray().toPromise();
|
||||
const results = await createPackageJsonAtPath$(path).toArray().toPromise();
|
||||
expect(results).to.have.length(1);
|
||||
expect(results[0]).to.only.have.keys(['error']);
|
||||
const { error } = results[0];
|
||||
|
@ -59,21 +60,6 @@ describe('plugin discovery/plugin_pack', () => {
|
|||
assertInvalidPackError(error);
|
||||
expect(error.message).to.contain('must have a valid package.json file');
|
||||
}));
|
||||
it('default export is an object', () => checkError(resolve(PLUGINS_DIR, 'exports_object'), error => {
|
||||
assertInvalidPackError(error);
|
||||
expect(error.message).to.contain('must export a function');
|
||||
}));
|
||||
it('default export is an number', () => checkError(resolve(PLUGINS_DIR, 'exports_number'), error => {
|
||||
assertInvalidPackError(error);
|
||||
expect(error.message).to.contain('must export a function');
|
||||
}));
|
||||
it('default export is an string', () => checkError(resolve(PLUGINS_DIR, 'exports_string'), error => {
|
||||
assertInvalidPackError(error);
|
||||
expect(error.message).to.contain('must export a function');
|
||||
}));
|
||||
it('directory with code that fails when required', () => checkError(resolve(PLUGINS_DIR, 'broken_code'), error => {
|
||||
expect(error.message).to.contain('Cannot find module \'does-not-exist\'');
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
|
@ -2,8 +2,7 @@ import { resolve } from 'path';
|
|||
|
||||
import expect from 'expect.js';
|
||||
|
||||
import { createPacksInDirectory$ } from '../packs_in_directory';
|
||||
import { PluginPack } from '../plugin_pack';
|
||||
import { createPackageJsonsInDirectory$ } from '../package_jsons_in_directory';
|
||||
|
||||
import {
|
||||
PLUGINS_DIR,
|
||||
|
@ -11,10 +10,10 @@ import {
|
|||
} from './utils';
|
||||
|
||||
describe('plugin discovery/packs in directory', () => {
|
||||
describe('createPacksInDirectory$()', () => {
|
||||
describe('createPackageJsonsInDirectory$()', () => {
|
||||
describe('errors emitted as { error } results', () => {
|
||||
async function checkError(path, check) {
|
||||
const results = await createPacksInDirectory$(path).toArray().toPromise();
|
||||
const results = await createPackageJsonsInDirectory$(path).toArray().toPromise();
|
||||
expect(results).to.have.length(1);
|
||||
expect(results[0]).to.only.have.keys('error');
|
||||
const { error } = results[0];
|
||||
|
@ -43,24 +42,24 @@ describe('plugin discovery/packs in directory', () => {
|
|||
}));
|
||||
});
|
||||
|
||||
it('includes child errors for invalid packs within a valid directory', async () => {
|
||||
const results = await createPacksInDirectory$(PLUGINS_DIR).toArray().toPromise();
|
||||
it('includes child errors for invalid packageJsons within a valid directory', async () => {
|
||||
const results = await createPackageJsonsInDirectory$(PLUGINS_DIR).toArray().toPromise();
|
||||
|
||||
const errors = results
|
||||
.map(result => result.error)
|
||||
.filter(Boolean);
|
||||
|
||||
const packs = results
|
||||
.map(result => result.pack)
|
||||
const packageJsons = results
|
||||
.map(result => result.packageJson)
|
||||
.filter(Boolean);
|
||||
|
||||
packs.forEach(pack => expect(pack).to.be.a(PluginPack));
|
||||
packageJsons.forEach(pack => expect(pack).to.be.an(Object));
|
||||
// there should be one result for each item in PLUGINS_DIR
|
||||
expect(results).to.have.length(9);
|
||||
// six of the fixtures are errors of some sort
|
||||
expect(errors).to.have.length(7);
|
||||
// two of them are valid
|
||||
expect(packs).to.have.length(2);
|
||||
// three of the fixtures are errors of some sort
|
||||
expect(errors).to.have.length(3);
|
||||
// six of them are valid
|
||||
expect(packageJsons).to.have.length(6);
|
||||
});
|
||||
});
|
||||
});
|
34
src/plugin_discovery/plugin_pack/create_pack.js
Normal file
34
src/plugin_discovery/plugin_pack/create_pack.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
import { PluginPack } from './plugin_pack';
|
||||
import { createInvalidPackError } from '../errors';
|
||||
|
||||
function createPack(packageJson) {
|
||||
let provider = require(packageJson.directoryPath);
|
||||
if (provider.__esModule) {
|
||||
provider = provider.default;
|
||||
}
|
||||
if (typeof provider !== 'function') {
|
||||
throw createInvalidPackError(packageJson.directoryPath, 'must export a function');
|
||||
}
|
||||
|
||||
return new PluginPack({ path: packageJson.directoryPath, pkg: packageJson.contents, provider });
|
||||
}
|
||||
|
||||
export const createPack$ = (packageJson$) => (
|
||||
packageJson$
|
||||
.map(({ error, packageJson }) => {
|
||||
if (error) {
|
||||
return { error };
|
||||
}
|
||||
|
||||
if (!packageJson) {
|
||||
throw new Error('packageJson is required to create the pack');
|
||||
}
|
||||
|
||||
return {
|
||||
pack: createPack(packageJson)
|
||||
};
|
||||
})
|
||||
// createPack can throw errors, and we want them to be represented
|
||||
// like the errors we consume from createPackageJsonAtPath/Directory
|
||||
.catch(error => [{ error }])
|
||||
);
|
|
@ -1,3 +1,4 @@
|
|||
export { createPack$ } from './create_pack';
|
||||
export { createPackageJsonAtPath$ } from './package_json_at_path';
|
||||
export { createPackageJsonsInDirectory$ } from './package_jsons_in_directory';
|
||||
export { PluginPack } from './plugin_pack';
|
||||
export { createPackAtPath$ } from './pack_at_path';
|
||||
export { createPacksInDirectory$ } from './packs_in_directory';
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
import { Observable } from 'rxjs';
|
||||
import { resolve } from 'path';
|
||||
import { createInvalidPackError } from '../errors';
|
||||
|
||||
import { isDirectory } from './lib';
|
||||
import { PluginPack } from './plugin_pack';
|
||||
|
||||
async function createPackAtPath(path) {
|
||||
if (!await isDirectory(path)) {
|
||||
throw createInvalidPackError(path, 'must be a directory');
|
||||
}
|
||||
|
||||
let pkg;
|
||||
try {
|
||||
pkg = require(resolve(path, 'package.json'));
|
||||
} catch (error) {
|
||||
if (error.code === 'MODULE_NOT_FOUND') {
|
||||
throw createInvalidPackError(path, 'must have a package.json file');
|
||||
}
|
||||
}
|
||||
|
||||
if (!pkg || typeof pkg !== 'object') {
|
||||
throw createInvalidPackError(path, 'must have a valid package.json file');
|
||||
}
|
||||
|
||||
let provider = require(path);
|
||||
if (provider.__esModule) {
|
||||
provider = provider.default;
|
||||
}
|
||||
if (typeof provider !== 'function') {
|
||||
throw createInvalidPackError(path, 'must export a function');
|
||||
}
|
||||
|
||||
return new PluginPack({ path, pkg, provider });
|
||||
}
|
||||
|
||||
export const createPackAtPath$ = (path) => (
|
||||
Observable.defer(() => createPackAtPath(path))
|
||||
.map(pack => ({ pack }))
|
||||
.catch(error => [{ error }])
|
||||
);
|
37
src/plugin_discovery/plugin_pack/package_json_at_path.js
Normal file
37
src/plugin_discovery/plugin_pack/package_json_at_path.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
import { readFileSync } from 'fs';
|
||||
import { Observable } from 'rxjs';
|
||||
import { resolve } from 'path';
|
||||
import { createInvalidPackError } from '../errors';
|
||||
|
||||
import { isDirectory } from './lib';
|
||||
|
||||
async function createPackageJsonAtPath(path) {
|
||||
if (!await isDirectory(path)) {
|
||||
throw createInvalidPackError(path, 'must be a directory');
|
||||
}
|
||||
|
||||
let str;
|
||||
try {
|
||||
str = readFileSync(resolve(path, 'package.json'));
|
||||
} catch (err) {
|
||||
throw createInvalidPackError(path, 'must have a package.json file');
|
||||
}
|
||||
|
||||
let pkg;
|
||||
try {
|
||||
pkg = JSON.parse(str);
|
||||
} catch (err) {
|
||||
throw createInvalidPackError(path, 'must have a valid package.json file');
|
||||
}
|
||||
|
||||
return {
|
||||
directoryPath: path,
|
||||
contents: pkg,
|
||||
};
|
||||
}
|
||||
|
||||
export const createPackageJsonAtPath$ = (path) => (
|
||||
Observable.defer(() => createPackageJsonAtPath(path))
|
||||
.map(packageJson => ({ packageJson }))
|
||||
.catch(error => [{ error }])
|
||||
);
|
|
@ -1,7 +1,7 @@
|
|||
import { isInvalidDirectoryError } from '../errors';
|
||||
|
||||
import { createChildDirectory$ } from './lib';
|
||||
import { createPackAtPath$ } from './pack_at_path';
|
||||
import { createPackageJsonAtPath$ } from './package_json_at_path';
|
||||
|
||||
/**
|
||||
* Finds the plugins within a directory. Results are
|
||||
|
@ -16,9 +16,9 @@ import { createPackAtPath$ } from './pack_at_path';
|
|||
* @param {String} path
|
||||
* @return {Array<{pack}|{error}>}
|
||||
*/
|
||||
export const createPacksInDirectory$ = (path) => (
|
||||
export const createPackageJsonsInDirectory$ = (path) => (
|
||||
createChildDirectory$(path)
|
||||
.mergeMap(createPackAtPath$)
|
||||
.mergeMap(createPackageJsonAtPath$)
|
||||
.catch(error => {
|
||||
// this error is produced by createChildDirectory$() when the path
|
||||
// is invalid, we return them as an error result similar to how
|
|
@ -9,8 +9,9 @@ const schemaExts = Symbol('Schema Extensions');
|
|||
const vals = Symbol('config values');
|
||||
|
||||
export class Config {
|
||||
static withDefaultSchema(settings = {}) {
|
||||
return new Config(createDefaultSchema(), settings);
|
||||
static async withDefaultSchema(settings = {}) {
|
||||
const defaultSchema = await createDefaultSchema();
|
||||
return new Config(defaultSchema, settings);
|
||||
}
|
||||
|
||||
constructor(initialSchema, initialSettings) {
|
||||
|
|
|
@ -5,7 +5,7 @@ import os from 'os';
|
|||
import { fromRoot } from '../../utils';
|
||||
import { getData } from '../path';
|
||||
|
||||
export default () => Joi.object({
|
||||
export default async () => Joi.object({
|
||||
pkg: Joi.object({
|
||||
version: Joi.string().default(Joi.ref('$version')),
|
||||
branch: Joi.string().default(Joi.ref('$branch')),
|
||||
|
|
|
@ -4,7 +4,7 @@ import { set } from 'lodash';
|
|||
|
||||
describe('Config schema', function () {
|
||||
let schema;
|
||||
beforeEach(() => schema = schemaProvider());
|
||||
beforeEach(async () => schema = await schemaProvider());
|
||||
|
||||
function validate(data, options) {
|
||||
return Joi.validate(data, schema, options);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Config } from './config';
|
||||
import { transformDeprecations } from './transform_deprecations';
|
||||
|
||||
export default function (kbnServer) {
|
||||
export default async function (kbnServer) {
|
||||
const settings = transformDeprecations(kbnServer.settings);
|
||||
kbnServer.config = Config.withDefaultSchema(settings);
|
||||
kbnServer.config = await Config.withDefaultSchema(settings);
|
||||
}
|
||||
|
|
|
@ -140,8 +140,8 @@ export default class KbnServer {
|
|||
return await this.server.inject(opts);
|
||||
}
|
||||
|
||||
applyLoggingConfiguration(settings) {
|
||||
const config = Config.withDefaultSchema(settings);
|
||||
async applyLoggingConfiguration(settings) {
|
||||
const config = await Config.withDefaultSchema(settings);
|
||||
const loggingOptions = loggingConfiguration(config);
|
||||
const subset = {
|
||||
ops: config.get('ops'),
|
||||
|
|
|
@ -15,12 +15,12 @@ import { uiSettingsMixin } from '../ui_settings_mixin';
|
|||
describe('uiSettingsMixin()', () => {
|
||||
const sandbox = sinon.sandbox.create();
|
||||
|
||||
function setup(options = {}) {
|
||||
async function setup(options = {}) {
|
||||
const {
|
||||
enabled = true
|
||||
} = options;
|
||||
|
||||
const config = Config.withDefaultSchema({
|
||||
const config = await Config.withDefaultSchema({
|
||||
uiSettings: { enabled }
|
||||
});
|
||||
|
||||
|
@ -70,8 +70,8 @@ describe('uiSettingsMixin()', () => {
|
|||
afterEach(() => sandbox.restore());
|
||||
|
||||
describe('server.uiSettingsServiceFactory()', () => {
|
||||
it('decorates server with "uiSettingsServiceFactory"', () => {
|
||||
const { decorations } = setup();
|
||||
it('decorates server with "uiSettingsServiceFactory"', async () => {
|
||||
const { decorations } = await setup();
|
||||
expect(decorations.server).to.have.property('uiSettingsServiceFactory').a('function');
|
||||
|
||||
sandbox.stub(uiSettingsServiceFactoryNS, 'uiSettingsServiceFactory');
|
||||
|
@ -80,8 +80,8 @@ describe('uiSettingsMixin()', () => {
|
|||
sinon.assert.calledOnce(uiSettingsServiceFactory);
|
||||
});
|
||||
|
||||
it('passes `server` and `options` argument to factory', () => {
|
||||
const { decorations, server } = setup();
|
||||
it('passes `server` and `options` argument to factory', async () => {
|
||||
const { decorations, server } = await setup();
|
||||
expect(decorations.server).to.have.property('uiSettingsServiceFactory').a('function');
|
||||
|
||||
sandbox.stub(uiSettingsServiceFactoryNS, 'uiSettingsServiceFactory');
|
||||
|
@ -98,8 +98,8 @@ describe('uiSettingsMixin()', () => {
|
|||
});
|
||||
|
||||
describe('request.getUiSettingsService()', () => {
|
||||
it('exposes "getUiSettingsService" on requests', () => {
|
||||
const { decorations } = setup();
|
||||
it('exposes "getUiSettingsService" on requests', async () => {
|
||||
const { decorations } = await setup();
|
||||
expect(decorations.request).to.have.property('getUiSettingsService').a('function');
|
||||
|
||||
sandbox.stub(getUiSettingsServiceForRequestNS, 'getUiSettingsServiceForRequest');
|
||||
|
@ -108,8 +108,8 @@ describe('uiSettingsMixin()', () => {
|
|||
sinon.assert.calledOnce(getUiSettingsServiceForRequest);
|
||||
});
|
||||
|
||||
it('passes request to getUiSettingsServiceForRequest', () => {
|
||||
const { server, decorations } = setup();
|
||||
it('passes request to getUiSettingsServiceForRequest', async () => {
|
||||
const { server, decorations } = await setup();
|
||||
expect(decorations.request).to.have.property('getUiSettingsService').a('function');
|
||||
|
||||
sandbox.stub(getUiSettingsServiceForRequestNS, 'getUiSettingsServiceForRequest');
|
||||
|
@ -121,8 +121,8 @@ describe('uiSettingsMixin()', () => {
|
|||
});
|
||||
|
||||
describe('server.uiSettings()', () => {
|
||||
it('throws an error, links to pr', () => {
|
||||
const { decorations } = setup();
|
||||
it('throws an error, links to pr', async () => {
|
||||
const { decorations } = await setup();
|
||||
expect(decorations.server).to.have.property('uiSettings').a('function');
|
||||
expect(() => {
|
||||
decorations.server.uiSettings();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue