-
Notifications
You must be signed in to change notification settings - Fork 8.5k
Added .get, renamed .getAll as .getRaw, added new .getAll method #7374
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
a1be97e
[settings] Added .get, renamed .getAll as .getRaw, added new .getAll …
bevacqua 7e191b8
[fix] @spalger identified as NSA mole. Run server-side tests in src/u…
bevacqua 415e663
[settings] Added .removeMany method for convenience single-roundtrip.
bevacqua 1657c65
[test] Introduced server-side tests for UI Settings feature.
bevacqua 8ace579
[refactor] Update usage of uiSettings when pulling a single value
bevacqua 0d31bb8
[test] Simplified test cases. Single assertion.
bevacqua 11c3bf5
[test] Refactor to avoid code duplication.
bevacqua 308ee58
[test] Semantic fix to compare against Promise.
bevacqua af0d592
[chore] Use isEqual and add comments about the methods in uiSettings.
bevacqua 1673b31
[test] .to.be.ok(), ugh.
bevacqua a2d34b3
[test] Refactor according to @cjcenizal's suggestions.
bevacqua 9133c3f
[test] To equal true.
bevacqua File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,308 @@ | ||
| import { isEqual } from 'lodash'; | ||
| import sinon from 'sinon'; | ||
| import expect from 'expect.js'; | ||
| import init from '..'; | ||
| import defaultsProvider from '../defaults'; | ||
|
|
||
| describe('ui settings', function () { | ||
| describe('overview', function () { | ||
| it('has expected api surface', function () { | ||
| const { uiSettings } = instantiate(); | ||
| expect(typeof uiSettings.get).to.equal('function'); | ||
| expect(typeof uiSettings.getAll).to.equal('function'); | ||
| expect(typeof uiSettings.getDefaults).to.equal('function'); | ||
| expect(typeof uiSettings.getRaw).to.equal('function'); | ||
| expect(typeof uiSettings.getUserProvided).to.equal('function'); | ||
| expect(typeof uiSettings.remove).to.equal('function'); | ||
| expect(typeof uiSettings.removeMany).to.equal('function'); | ||
| expect(typeof uiSettings.set).to.equal('function'); | ||
| expect(typeof uiSettings.setMany).to.equal('function'); | ||
| }); | ||
| }); | ||
|
|
||
| describe('#setMany()', function () { | ||
| it('returns a promise', () => { | ||
| const { uiSettings } = instantiate(); | ||
| const result = uiSettings.setMany({ a: 'b' }); | ||
| expect(result).to.be.a(Promise); | ||
| }); | ||
|
|
||
| it('updates a single value in one operation', function () { | ||
| const { server, uiSettings, configGet } = instantiate(); | ||
| const result = uiSettings.setMany({ one: 'value' }); | ||
| expectElasticsearchUpdateQuery(server, configGet, { | ||
| one: 'value' | ||
| }); | ||
| }); | ||
|
|
||
| it('updates several values in one operation', function () { | ||
| const { server, uiSettings, configGet } = instantiate(); | ||
| const result = uiSettings.setMany({ one: 'value', another: 'val' }); | ||
| expectElasticsearchUpdateQuery(server, configGet, { | ||
| one: 'value', another: 'val' | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| describe('#set()', function () { | ||
| it('returns a promise', () => { | ||
| const { uiSettings } = instantiate(); | ||
| const result = uiSettings.set('a', 'b'); | ||
| expect(result).to.be.a(Promise); | ||
| }); | ||
|
|
||
| it('updates single values by (key, value)', function () { | ||
| const { server, uiSettings, configGet } = instantiate(); | ||
| const result = uiSettings.set('one', 'value'); | ||
| expectElasticsearchUpdateQuery(server, configGet, { | ||
| one: 'value' | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| describe('#remove()', function () { | ||
| it('returns a promise', () => { | ||
| const { uiSettings } = instantiate(); | ||
| const result = uiSettings.remove('one'); | ||
| expect(result).to.be.a(Promise); | ||
| }); | ||
|
|
||
| it('removes single values by key', function () { | ||
| const { server, uiSettings, configGet } = instantiate(); | ||
| const result = uiSettings.remove('one'); | ||
| expectElasticsearchUpdateQuery(server, configGet, { | ||
| one: null | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| describe('#removeMany()', function () { | ||
| it('returns a promise', () => { | ||
| const { uiSettings } = instantiate(); | ||
| const result = uiSettings.removeMany(['one']); | ||
| expect(result).to.be.a(Promise); | ||
| }); | ||
|
|
||
| it('removes a single value', function () { | ||
| const { server, uiSettings, configGet } = instantiate(); | ||
| const result = uiSettings.removeMany(['one']); | ||
| expectElasticsearchUpdateQuery(server, configGet, { | ||
| one: null | ||
| }); | ||
| }); | ||
|
|
||
| it('updates several values in one operation', function () { | ||
| const { server, uiSettings, configGet } = instantiate(); | ||
| const result = uiSettings.removeMany(['one', 'two', 'three']); | ||
| expectElasticsearchUpdateQuery(server, configGet, { | ||
| one: null, two: null, three: null | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| describe('#getDefaults()', function () { | ||
| it('is promised the default values', async function () { | ||
| const { server, uiSettings, configGet } = instantiate(); | ||
| const defaults = await uiSettings.getDefaults(); | ||
| expect(isEqual(defaults, defaultsProvider())).to.equal(true); | ||
| }); | ||
| }); | ||
|
|
||
| describe('#getUserProvided()', function () { | ||
| it('pulls user configuration from ES', async function () { | ||
| const getResult = { user: 'customized' }; | ||
| const { server, uiSettings, configGet } = instantiate({ getResult }); | ||
| const result = await uiSettings.getUserProvided(); | ||
| expectElasticsearchGetQuery(server, configGet); | ||
| }); | ||
|
|
||
| it('returns user configuration', async function () { | ||
| const getResult = { user: 'customized' }; | ||
| const { server, uiSettings, configGet } = instantiate({ getResult }); | ||
| const result = await uiSettings.getUserProvided(); | ||
| expect(isEqual(result, { | ||
| user: { userValue: 'customized' } | ||
| })).to.equal(true); | ||
| }); | ||
|
|
||
| it('ignores null user configuration (because default values)', async function () { | ||
| const getResult = { user: 'customized', usingDefault: null, something: 'else' }; | ||
| const { server, uiSettings, configGet } = instantiate({ getResult }); | ||
| const result = await uiSettings.getUserProvided(); | ||
| expect(isEqual(result, { | ||
| user: { userValue: 'customized' }, something: { userValue: 'else' } | ||
| })).to.equal(true); | ||
| }); | ||
| }); | ||
|
|
||
| describe('#getRaw()', function () { | ||
| it('pulls user configuration from ES', async function () { | ||
| const getResult = {}; | ||
| const { server, uiSettings, configGet } = instantiate({ getResult }); | ||
| const result = await uiSettings.getRaw(); | ||
| expectElasticsearchGetQuery(server, configGet); | ||
| }); | ||
|
|
||
| it(`without user configuration it's equal to the defaults`, async function () { | ||
| const getResult = {}; | ||
| const { server, uiSettings, configGet } = instantiate({ getResult }); | ||
| const result = await uiSettings.getRaw(); | ||
| expect(isEqual(result, defaultsProvider())).to.equal(true); | ||
| }); | ||
|
|
||
| it(`user configuration gets merged with defaults`, async function () { | ||
| const getResult = { foo: 'bar' }; | ||
| const { server, uiSettings, configGet } = instantiate({ getResult }); | ||
| const result = await uiSettings.getRaw(); | ||
| const merged = defaultsProvider(); | ||
| merged.foo = { userValue: 'bar' }; | ||
| expect(isEqual(result, merged)).to.equal(true); | ||
| }); | ||
|
|
||
| it(`user configuration gets merged into defaults`, async function () { | ||
| const getResult = { dateFormat: 'YYYY-MM-DD' }; | ||
| const { server, uiSettings, configGet } = instantiate({ getResult }); | ||
| const result = await uiSettings.getRaw(); | ||
| const merged = defaultsProvider(); | ||
| merged.dateFormat.userValue = 'YYYY-MM-DD'; | ||
| expect(isEqual(result, merged)).to.equal(true); | ||
| }); | ||
| }); | ||
|
|
||
| describe('#getAll()', function () { | ||
| it('pulls user configuration from ES', async function () { | ||
| const getResult = {}; | ||
| const { server, uiSettings, configGet } = instantiate({ getResult }); | ||
| const result = await uiSettings.getAll(); | ||
| expectElasticsearchGetQuery(server, configGet); | ||
| }); | ||
|
|
||
| it(`returns key value pairs`, async function () { | ||
| const getResult = {}; | ||
| const { server, uiSettings, configGet } = instantiate({ getResult }); | ||
| const result = await uiSettings.getAll(); | ||
| const defaults = defaultsProvider(); | ||
| const expectation = {}; | ||
| Object.keys(defaults).forEach(key => { | ||
| expectation[key] = defaults[key].value; | ||
| }); | ||
| expect(isEqual(result, expectation)).to.equal(true); | ||
| }); | ||
|
|
||
| it(`returns key value pairs including user configuration`, async function () { | ||
| const getResult = { something: 'user-provided' }; | ||
| const { server, uiSettings, configGet } = instantiate({ getResult }); | ||
| const result = await uiSettings.getAll(); | ||
| const defaults = defaultsProvider(); | ||
| const expectation = {}; | ||
| Object.keys(defaults).forEach(key => { | ||
| expectation[key] = defaults[key].value; | ||
| }); | ||
| expectation.something = 'user-provided'; | ||
| expect(isEqual(result, expectation)).to.equal(true); | ||
| }); | ||
|
|
||
| it(`returns key value pairs including user configuration for existing settings`, async function () { | ||
| const getResult = { dateFormat: 'YYYY-MM-DD' }; | ||
| const { server, uiSettings, configGet } = instantiate({ getResult }); | ||
| const result = await uiSettings.getAll(); | ||
| const defaults = defaultsProvider(); | ||
| const expectation = {}; | ||
| Object.keys(defaults).forEach(key => { | ||
| expectation[key] = defaults[key].value; | ||
| }); | ||
| expectation.dateFormat = 'YYYY-MM-DD'; | ||
| expect(isEqual(result, expectation)).to.equal(true); | ||
| }); | ||
| }); | ||
|
|
||
| describe('#get()', function () { | ||
| it('pulls user configuration from ES', async function () { | ||
| const getResult = {}; | ||
| const { server, uiSettings, configGet } = instantiate({ getResult }); | ||
| const result = await uiSettings.get(); | ||
| expectElasticsearchGetQuery(server, configGet); | ||
| }); | ||
|
|
||
| it(`returns the promised value for a key`, async function () { | ||
| const getResult = {}; | ||
| const { server, uiSettings, configGet } = instantiate({ getResult }); | ||
| const result = await uiSettings.get('dateFormat'); | ||
| const defaults = defaultsProvider(); | ||
| expect(result).to.equal(defaults.dateFormat.value); | ||
| }); | ||
|
|
||
| it(`returns the user-configured value for a custom key`, async function () { | ||
| const getResult = { custom: 'value' }; | ||
| const { server, uiSettings, configGet } = instantiate({ getResult }); | ||
| const result = await uiSettings.get('custom'); | ||
| expect(result).to.equal('value'); | ||
| }); | ||
|
|
||
| it(`returns the user-configured value for a modified key`, async function () { | ||
| const getResult = { dateFormat: 'YYYY-MM-DD' }; | ||
| const { server, uiSettings, configGet } = instantiate({ getResult }); | ||
| const result = await uiSettings.get('dateFormat'); | ||
| expect(result).to.equal('YYYY-MM-DD'); | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| function expectElasticsearchGetQuery(server, configGet) { | ||
| expect(server.plugins.elasticsearch.client.get.callCount).to.equal(1); | ||
| expect(isEqual(server.plugins.elasticsearch.client.get.firstCall.args, [{ | ||
| index: configGet('kibana.index'), | ||
| id: configGet('pkg.version'), | ||
| type: 'config' | ||
| }])).to.equal(true); | ||
| } | ||
|
|
||
| function expectElasticsearchUpdateQuery(server, configGet, doc) { | ||
| expect(server.plugins.elasticsearch.client.update.callCount).to.equal(1); | ||
| expect(isEqual(server.plugins.elasticsearch.client.update.firstCall.args, [{ | ||
| index: configGet('kibana.index'), | ||
| id: configGet('pkg.version'), | ||
| type: 'config', | ||
| body: { doc } | ||
| }])).to.equal(true); | ||
| } | ||
|
|
||
| function instantiate({ getResult } = {}) { | ||
| const esStatus = { | ||
| state: 'green', | ||
| on: sinon.spy() | ||
| }; | ||
| const settingsStatus = { | ||
| state: 'green', | ||
| red: sinon.spy(), | ||
| yellow: sinon.spy(), | ||
| green: sinon.spy() | ||
| }; | ||
| const kbnServer = { | ||
| status: { | ||
| create: sinon.stub().withArgs('ui settings').returns(settingsStatus), | ||
| getForPluginId: sinon.stub().withArgs('elasticsearch').returns(esStatus) | ||
| }, | ||
| ready: sinon.stub().returns(Promise.resolve()) | ||
| }; | ||
| const server = { | ||
| decorate: (_, key, value) => server[key] = value, | ||
| plugins: { | ||
| elasticsearch: { | ||
| client: { | ||
| get: sinon.stub().returns(Promise.resolve({ _source: getResult })), | ||
| update: sinon.stub().returns(Promise.resolve()) | ||
| } | ||
| } | ||
| } | ||
| }; | ||
| const configGet = sinon.stub(); | ||
| configGet.withArgs('kibana.index').returns('.kibana'); | ||
| configGet.withArgs('pkg.version').returns('1.2.3-test'); | ||
| const config = { | ||
| get: configGet | ||
| }; | ||
| const setupSettings = init(kbnServer, server, config); | ||
| const uiSettings = server.uiSettings(); | ||
| return { server, uiSettings, configGet }; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,18 +4,47 @@ import defaultsProvider from './defaults'; | |
| export default function setupSettings(kbnServer, server, config) { | ||
| const status = kbnServer.status.create('ui settings'); | ||
| const uiSettings = { | ||
| // returns a Promise for the value of the requested setting | ||
| get, | ||
| // returns a Promise for a hash of setting key/value pairs | ||
| getAll, | ||
| getDefaults, | ||
| getUserProvided, | ||
| // .set(key, value), returns a Promise for persisting the new value to ES | ||
| set, | ||
| // takes a key/value hash, returns a Promise for persisting the new values to ES | ||
| setMany, | ||
| remove | ||
| // returns a Promise for removing the provided key from user-specific settings | ||
| remove, | ||
| // takes an array, returns a Promise for removing every provided key from user-specific settings | ||
| removeMany, | ||
|
|
||
| // returns a Promise for the default settings, follows metadata format (see ./defaults) | ||
| getDefaults, | ||
| // returns a Promise for user-specific settings stored in ES, follows metadata format | ||
| getUserProvided, | ||
| // returns a Promise merging results of getDefaults & getUserProvided, follows metadata format | ||
| getRaw | ||
| }; | ||
|
|
||
| server.decorate('server', 'uiSettings', () => uiSettings); | ||
| kbnServer.ready().then(mirrorEsStatus); | ||
|
|
||
| function get(key) { | ||
| return getAll().then(all => all[key]); | ||
| } | ||
|
|
||
| function getAll() { | ||
| return getRaw() | ||
|
||
| .then(raw => Object.keys(raw) | ||
| .reduce((all, key) => { | ||
| const item = raw[key]; | ||
| const hasUserValue = 'userValue' in item; | ||
| all[key] = hasUserValue ? item.userValue : item.value; | ||
| return all; | ||
| }, {}) | ||
| ); | ||
| } | ||
|
|
||
| function getRaw() { | ||
| return Promise | ||
| .all([getDefaults(), getUserProvided()]) | ||
| .then(([defaults, user]) => defaultsDeep(user, defaults)); | ||
|
|
@@ -59,6 +88,14 @@ export default function setupSettings(kbnServer, server, config) { | |
| return set(key, null); | ||
| } | ||
|
|
||
| function removeMany(keys) { | ||
| const changes = {}; | ||
| keys.forEach(key => { | ||
| changes[key] = null; | ||
| }); | ||
| return setMany(changes); | ||
| } | ||
|
|
||
| function mirrorEsStatus() { | ||
| const esStatus = kbnServer.status.getForPluginId('elasticsearch'); | ||
|
|
||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think all the anonymous functions can be replaced with fat arrow functions in this file, to get more ES6ish.