2018-01-20 03:50:37 +03:00
|
|
|
describe('Config', () => {
|
2018-01-25 05:16:49 +03:00
|
|
|
let savedSettings
|
2018-01-20 03:50:37 +03:00
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
spyOn(console, 'warn')
|
|
|
|
atom.config.settingsLoaded = true
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
savedSettings = []
|
|
|
|
atom.config.saveCallback = function (settings) {
|
|
|
|
savedSettings.push(settings)
|
|
|
|
}
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-20 03:54:53 +03:00
|
|
|
describe('.get(keyPath, {scope, sources, excludeSources})', () => {
|
|
|
|
it("allows a key path's value to be read", () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
expect(atom.config.set('foo.bar.baz', 42)).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.baz')).toBe(42)
|
|
|
|
expect(atom.config.get('foo.quux')).toBeUndefined()
|
|
|
|
})
|
|
|
|
|
2018-01-20 03:54:53 +03:00
|
|
|
it("returns a deep clone of the key path's value", () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
atom.config.set('value', {array: [1, {b: 2}, 3]})
|
|
|
|
const retrievedValue = atom.config.get('value')
|
|
|
|
retrievedValue.array[0] = 4
|
|
|
|
retrievedValue.array[1].b = 2.1
|
|
|
|
expect(atom.config.get('value')).toEqual({array: [1, {b: 2}, 3]})
|
|
|
|
})
|
|
|
|
|
2018-01-20 03:54:53 +03:00
|
|
|
it('merges defaults into the returned value if both the assigned value and the default value are objects', () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
atom.config.setDefaults('foo.bar', {baz: 1, ok: 2})
|
|
|
|
atom.config.set('foo.bar', {baz: 3})
|
|
|
|
expect(atom.config.get('foo.bar')).toEqual({baz: 3, ok: 2})
|
|
|
|
|
|
|
|
atom.config.setDefaults('other', {baz: 1})
|
|
|
|
atom.config.set('other', 7)
|
|
|
|
expect(atom.config.get('other')).toBe(7)
|
|
|
|
|
|
|
|
atom.config.set('bar.baz', {a: 3})
|
|
|
|
atom.config.setDefaults('bar', {baz: 7})
|
|
|
|
expect(atom.config.get('bar.baz')).toEqual({a: 3})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe("when a 'sources' option is specified", () =>
|
2018-01-20 03:54:53 +03:00
|
|
|
it('only retrieves values from the specified sources', () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
atom.config.set('x.y', 1, {scopeSelector: '.foo', source: 'a'})
|
|
|
|
atom.config.set('x.y', 2, {scopeSelector: '.foo', source: 'b'})
|
|
|
|
atom.config.set('x.y', 3, {scopeSelector: '.foo', source: 'c'})
|
|
|
|
atom.config.setSchema('x.y', {type: 'integer', default: 4})
|
|
|
|
|
|
|
|
expect(atom.config.get('x.y', {sources: ['a'], scope: ['.foo']})).toBe(1)
|
|
|
|
expect(atom.config.get('x.y', {sources: ['b'], scope: ['.foo']})).toBe(2)
|
|
|
|
expect(atom.config.get('x.y', {sources: ['c'], scope: ['.foo']})).toBe(3)
|
|
|
|
// Schema defaults never match a specific source. We could potentially add a special "schema" source.
|
|
|
|
expect(atom.config.get('x.y', {sources: ['x'], scope: ['.foo']})).toBeUndefined()
|
|
|
|
|
|
|
|
expect(atom.config.get(null, {sources: ['a'], scope: ['.foo']}).x.y).toBe(1)
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
describe("when an 'excludeSources' option is specified", () =>
|
|
|
|
it('only retrieves values from the specified sources', () => {
|
|
|
|
atom.config.set('x.y', 0)
|
|
|
|
atom.config.set('x.y', 1, {scopeSelector: '.foo', source: 'a'})
|
|
|
|
atom.config.set('x.y', 2, {scopeSelector: '.foo', source: 'b'})
|
|
|
|
atom.config.set('x.y', 3, {scopeSelector: '.foo', source: 'c'})
|
|
|
|
atom.config.setSchema('x.y', {type: 'integer', default: 4})
|
|
|
|
|
|
|
|
expect(atom.config.get('x.y', {excludeSources: ['a'], scope: ['.foo']})).toBe(3)
|
|
|
|
expect(atom.config.get('x.y', {excludeSources: ['c'], scope: ['.foo']})).toBe(2)
|
|
|
|
expect(atom.config.get('x.y', {excludeSources: ['b', 'c'], scope: ['.foo']})).toBe(1)
|
|
|
|
expect(atom.config.get('x.y', {excludeSources: ['b', 'c', 'a'], scope: ['.foo']})).toBe(0)
|
|
|
|
expect(atom.config.get('x.y', {excludeSources: ['b', 'c', 'a', atom.config.getUserConfigPath()], scope: ['.foo']})).toBe(4)
|
|
|
|
expect(atom.config.get('x.y', {excludeSources: [atom.config.getUserConfigPath()]})).toBe(4)
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
describe("when a 'scope' option is given", () => {
|
2018-01-20 03:54:53 +03:00
|
|
|
it('returns the property with the most specific scope selector', () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
atom.config.set('foo.bar.baz', 42, {scopeSelector: '.source.coffee .string.quoted.double.coffee'})
|
|
|
|
atom.config.set('foo.bar.baz', 22, {scopeSelector: '.source .string.quoted.double'})
|
|
|
|
atom.config.set('foo.bar.baz', 11, {scopeSelector: '.source'})
|
|
|
|
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee', '.string.quoted.double.coffee']})).toBe(42)
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.js', '.string.quoted.double.js']})).toBe(22)
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.js', '.variable.assignment.js']})).toBe(11)
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.text']})).toBeUndefined()
|
|
|
|
})
|
|
|
|
|
2018-01-20 03:54:53 +03:00
|
|
|
it('favors the most recently added properties in the event of a specificity tie', () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
atom.config.set('foo.bar.baz', 42, {scopeSelector: '.source.coffee .string.quoted.single'})
|
|
|
|
atom.config.set('foo.bar.baz', 22, {scopeSelector: '.source.coffee .string.quoted.double'})
|
|
|
|
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee', '.string.quoted.single']})).toBe(42)
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee', '.string.quoted.single.double']})).toBe(22)
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('when there are global defaults', () =>
|
2018-01-20 03:54:53 +03:00
|
|
|
it('falls back to the global when there is no scoped property specified', () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
atom.config.setDefaults('foo', {hasDefault: 'ok'})
|
|
|
|
expect(atom.config.get('foo.hasDefault', {scope: ['.source.coffee', '.string.quoted.single']})).toBe('ok')
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
describe('when package settings are added after user settings', () =>
|
2018-01-20 03:54:53 +03:00
|
|
|
it("returns the user's setting because the user's setting has higher priority", () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
atom.config.set('foo.bar.baz', 100, {scopeSelector: '.source.coffee'})
|
|
|
|
atom.config.set('foo.bar.baz', 1, {scopeSelector: '.source.coffee', source: 'some-package'})
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee']})).toBe(100)
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
describe('when the first component of the scope descriptor matches a legacy scope alias', () =>
|
2018-01-20 03:54:53 +03:00
|
|
|
it('falls back to properties defined for the legacy scope if no value is found for the original scope descriptor', () => {
|
2018-02-20 21:52:16 +03:00
|
|
|
atom.config.setLegacyScopeAliasForNewScope('javascript', '.source.js')
|
2018-01-20 03:50:37 +03:00
|
|
|
atom.config.set('foo', 100, {scopeSelector: '.source.js'})
|
|
|
|
atom.config.set('foo', 200, {scopeSelector: 'javascript for_statement'})
|
|
|
|
|
|
|
|
expect(atom.config.get('foo', {scope: ['javascript', 'for_statement', 'identifier']})).toBe(200)
|
|
|
|
expect(atom.config.get('foo', {scope: ['javascript', 'function', 'identifier']})).toBe(100)
|
|
|
|
})
|
|
|
|
)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('.getAll(keyPath, {scope, sources, excludeSources})', () => {
|
|
|
|
it('reads all of the values for a given key-path', () => {
|
|
|
|
expect(atom.config.set('foo', 41)).toBe(true)
|
|
|
|
expect(atom.config.set('foo', 43, {scopeSelector: '.a .b'})).toBe(true)
|
|
|
|
expect(atom.config.set('foo', 42, {scopeSelector: '.a'})).toBe(true)
|
|
|
|
expect(atom.config.set('foo', 44, {scopeSelector: '.a .b.c'})).toBe(true)
|
|
|
|
|
|
|
|
expect(atom.config.set('foo', -44, {scopeSelector: '.d'})).toBe(true)
|
|
|
|
|
|
|
|
expect(atom.config.getAll('foo', {scope: ['.a', '.b.c']})).toEqual([
|
|
|
|
{scopeSelector: '.a .b.c', value: 44},
|
|
|
|
{scopeSelector: '.a .b', value: 43},
|
|
|
|
{scopeSelector: '.a', value: 42},
|
|
|
|
{scopeSelector: '*', value: 41}
|
|
|
|
])
|
|
|
|
})
|
|
|
|
|
|
|
|
it("includes the schema's default value", () => {
|
|
|
|
atom.config.setSchema('foo', {type: 'number', default: 40})
|
|
|
|
expect(atom.config.set('foo', 43, {scopeSelector: '.a .b'})).toBe(true)
|
|
|
|
expect(atom.config.getAll('foo', {scope: ['.a', '.b.c']})).toEqual([
|
|
|
|
{scopeSelector: '.a .b', value: 43},
|
|
|
|
{scopeSelector: '*', value: 40}
|
|
|
|
])
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('when the first component of the scope descriptor matches a legacy scope alias', () =>
|
|
|
|
it('includes the values defined for the legacy scope', () => {
|
2018-02-20 21:52:16 +03:00
|
|
|
atom.config.setLegacyScopeAliasForNewScope('javascript', '.source.js')
|
2018-01-20 03:50:37 +03:00
|
|
|
|
|
|
|
expect(atom.config.set('foo', 41)).toBe(true)
|
|
|
|
expect(atom.config.set('foo', 42, {scopeSelector: 'javascript'})).toBe(true)
|
|
|
|
expect(atom.config.set('foo', 43, {scopeSelector: '.source.js'})).toBe(true)
|
|
|
|
|
|
|
|
expect(atom.config.getAll('foo', {scope: ['javascript']})).toEqual([
|
|
|
|
{scopeSelector: 'javascript', value: 42},
|
|
|
|
{scopeSelector: '.js.source', value: 43},
|
|
|
|
{scopeSelector: '*', value: 41}
|
|
|
|
])
|
|
|
|
})
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('.set(keyPath, value, {source, scopeSelector})', () => {
|
|
|
|
it("allows a key path's value to be written", () => {
|
|
|
|
expect(atom.config.set('foo.bar.baz', 42)).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.baz')).toBe(42)
|
|
|
|
})
|
|
|
|
|
|
|
|
it("saves the user's config to disk after it stops changing", () => {
|
|
|
|
atom.config.set('foo.bar.baz', 42)
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(savedSettings.length).toBe(0)
|
2018-01-20 03:50:37 +03:00
|
|
|
atom.config.set('foo.bar.baz', 43)
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(savedSettings.length).toBe(0)
|
2018-01-20 03:50:37 +03:00
|
|
|
atom.config.set('foo.bar.baz', 44)
|
2018-01-26 22:15:35 +03:00
|
|
|
advanceClock(10)
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(savedSettings.length).toBe(1)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
it("does not save when a non-default 'source' is given", () => {
|
|
|
|
atom.config.set('foo.bar.baz', 42, {source: 'some-other-source', scopeSelector: '.a'})
|
|
|
|
advanceClock(500)
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(savedSettings.length).toBe(0)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it("does not allow a 'source' option without a 'scopeSelector'", () => {
|
|
|
|
expect(() => atom.config.set('foo', 1, {source: ['.source.ruby']})).toThrow()
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
|
|
|
describe('when the key-path is null', () =>
|
|
|
|
it('sets the root object', () => {
|
|
|
|
expect(atom.config.set(null, {editor: {tabLength: 6}})).toBe(true)
|
|
|
|
expect(atom.config.get('editor.tabLength')).toBe(6)
|
|
|
|
expect(atom.config.set(null, {editor: {tabLength: 8, scopeSelector: ['.source.js']}})).toBe(true)
|
|
|
|
expect(atom.config.get('editor.tabLength', {scope: ['.source.js']})).toBe(8)
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
describe('when the value equals the default value', () =>
|
|
|
|
it("does not store the value in the user's config", () => {
|
|
|
|
atom.config.setSchema('foo', {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
same: {
|
|
|
|
type: 'number',
|
|
|
|
default: 1
|
|
|
|
},
|
|
|
|
changes: {
|
|
|
|
type: 'number',
|
|
|
|
default: 1
|
|
|
|
},
|
|
|
|
sameArray: {
|
|
|
|
type: 'array',
|
|
|
|
default: [1, 2, 3]
|
|
|
|
},
|
|
|
|
sameObject: {
|
|
|
|
type: 'object',
|
|
|
|
default: {a: 1, b: 2}
|
|
|
|
},
|
|
|
|
null: {
|
|
|
|
type: '*',
|
|
|
|
default: null
|
|
|
|
},
|
|
|
|
undefined: {
|
|
|
|
type: '*',
|
|
|
|
default: undefined
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
expect(atom.config.settings.foo).toBeUndefined()
|
|
|
|
|
|
|
|
atom.config.set('foo.same', 1)
|
|
|
|
atom.config.set('foo.changes', 2)
|
|
|
|
atom.config.set('foo.sameArray', [1, 2, 3])
|
|
|
|
atom.config.set('foo.null', undefined)
|
|
|
|
atom.config.set('foo.undefined', null)
|
|
|
|
atom.config.set('foo.sameObject', {b: 2, a: 1})
|
|
|
|
|
|
|
|
const userConfigPath = atom.config.getUserConfigPath()
|
|
|
|
|
|
|
|
expect(atom.config.get('foo.same', {sources: [userConfigPath]})).toBeUndefined()
|
|
|
|
|
|
|
|
expect(atom.config.get('foo.changes')).toBe(2)
|
|
|
|
expect(atom.config.get('foo.changes', {sources: [userConfigPath]})).toBe(2)
|
|
|
|
|
|
|
|
atom.config.set('foo.changes', 1)
|
|
|
|
expect(atom.config.get('foo.changes', {sources: [userConfigPath]})).toBeUndefined()
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
describe("when a 'scopeSelector' is given", () =>
|
|
|
|
it('sets the value and overrides the others', () => {
|
|
|
|
atom.config.set('foo.bar.baz', 42, {scopeSelector: '.source.coffee .string.quoted.double.coffee'})
|
|
|
|
atom.config.set('foo.bar.baz', 22, {scopeSelector: '.source .string.quoted.double'})
|
|
|
|
atom.config.set('foo.bar.baz', 11, {scopeSelector: '.source'})
|
|
|
|
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee', '.string.quoted.double.coffee']})).toBe(42)
|
|
|
|
|
|
|
|
expect(atom.config.set('foo.bar.baz', 100, {scopeSelector: '.source.coffee .string.quoted.double.coffee'})).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee', '.string.quoted.double.coffee']})).toBe(100)
|
|
|
|
})
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('.unset(keyPath, {source, scopeSelector})', () => {
|
|
|
|
beforeEach(() =>
|
|
|
|
atom.config.setSchema('foo', {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
bar: {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
baz: {
|
|
|
|
type: 'integer',
|
|
|
|
default: 0
|
|
|
|
},
|
|
|
|
ok: {
|
|
|
|
type: 'integer',
|
|
|
|
default: 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
quux: {
|
|
|
|
type: 'integer',
|
|
|
|
default: 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
it('sets the value of the key path to its default', () => {
|
|
|
|
atom.config.setDefaults('a', {b: 3})
|
|
|
|
atom.config.set('a.b', 4)
|
|
|
|
expect(atom.config.get('a.b')).toBe(4)
|
|
|
|
atom.config.unset('a.b')
|
|
|
|
expect(atom.config.get('a.b')).toBe(3)
|
|
|
|
|
|
|
|
atom.config.set('a.c', 5)
|
|
|
|
expect(atom.config.get('a.c')).toBe(5)
|
|
|
|
atom.config.unset('a.c')
|
|
|
|
expect(atom.config.get('a.c')).toBeUndefined()
|
|
|
|
})
|
|
|
|
|
|
|
|
it('calls ::save()', () => {
|
|
|
|
atom.config.setDefaults('a', {b: 3})
|
|
|
|
atom.config.set('a.b', 4)
|
2018-01-25 05:16:49 +03:00
|
|
|
savedSettings.length = 0
|
2018-01-20 03:50:37 +03:00
|
|
|
|
|
|
|
atom.config.unset('a.c')
|
|
|
|
advanceClock(500)
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(savedSettings.length).toBe(1)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
describe("when no 'scopeSelector' is given", () => {
|
|
|
|
describe("when a 'source' but no key-path is given", () =>
|
|
|
|
it('removes all scoped settings with the given source', () => {
|
|
|
|
atom.config.set('foo.bar.baz', 1, {scopeSelector: '.a', source: 'source-a'})
|
|
|
|
atom.config.set('foo.bar.quux', 2, {scopeSelector: '.b', source: 'source-a'})
|
|
|
|
expect(atom.config.get('foo.bar', {scope: ['.a.b']})).toEqual({baz: 1, quux: 2})
|
|
|
|
|
|
|
|
atom.config.unset(null, {source: 'source-a'})
|
|
|
|
expect(atom.config.get('foo.bar', {scope: ['.a']})).toEqual({baz: 0, ok: 0})
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
describe("when a 'source' and a key-path is given", () =>
|
|
|
|
it('removes all scoped settings with the given source and key-path', () => {
|
|
|
|
atom.config.set('foo.bar.baz', 1)
|
|
|
|
atom.config.set('foo.bar.baz', 2, {scopeSelector: '.a', source: 'source-a'})
|
|
|
|
atom.config.set('foo.bar.baz', 3, {scopeSelector: '.a.b', source: 'source-b'})
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.a.b']})).toEqual(3)
|
|
|
|
|
|
|
|
atom.config.unset('foo.bar.baz', {source: 'source-b'})
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.a.b']})).toEqual(2)
|
|
|
|
expect(atom.config.get('foo.bar.baz')).toEqual(1)
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
describe("when no 'source' is given", () =>
|
|
|
|
it('removes all scoped and unscoped properties for that key-path', () => {
|
|
|
|
atom.config.setDefaults('foo.bar', {baz: 100})
|
|
|
|
|
|
|
|
atom.config.set('foo.bar', {baz: 1, ok: 2}, {scopeSelector: '.a'})
|
|
|
|
atom.config.set('foo.bar', {baz: 11, ok: 12}, {scopeSelector: '.b'})
|
|
|
|
atom.config.set('foo.bar', {baz: 21, ok: 22})
|
|
|
|
|
|
|
|
atom.config.unset('foo.bar.baz')
|
|
|
|
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.a']})).toBe(100)
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.b']})).toBe(100)
|
|
|
|
expect(atom.config.get('foo.bar.baz')).toBe(100)
|
|
|
|
|
|
|
|
expect(atom.config.get('foo.bar.ok', {scope: ['.a']})).toBe(2)
|
|
|
|
expect(atom.config.get('foo.bar.ok', {scope: ['.b']})).toBe(12)
|
|
|
|
expect(atom.config.get('foo.bar.ok')).toBe(22)
|
|
|
|
})
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
describe("when a 'scopeSelector' is given", () => {
|
|
|
|
it('restores the global default when no scoped default set', () => {
|
|
|
|
atom.config.setDefaults('foo', {bar: {baz: 10}})
|
|
|
|
atom.config.set('foo.bar.baz', 55, {scopeSelector: '.source.coffee'})
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee']})).toBe(55)
|
|
|
|
|
|
|
|
atom.config.unset('foo.bar.baz', {scopeSelector: '.source.coffee'})
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee']})).toBe(10)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('restores the scoped default when a scoped default is set', () => {
|
|
|
|
atom.config.setDefaults('foo', {bar: {baz: 10}})
|
|
|
|
atom.config.set('foo.bar.baz', 42, {scopeSelector: '.source.coffee', source: 'some-source'})
|
|
|
|
atom.config.set('foo.bar.baz', 55, {scopeSelector: '.source.coffee'})
|
|
|
|
atom.config.set('foo.bar.ok', 100, {scopeSelector: '.source.coffee'})
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee']})).toBe(55)
|
|
|
|
|
|
|
|
atom.config.unset('foo.bar.baz', {scopeSelector: '.source.coffee'})
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee']})).toBe(42)
|
|
|
|
expect(atom.config.get('foo.bar.ok', {scope: ['.source.coffee']})).toBe(100)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('calls ::save()', () => {
|
|
|
|
atom.config.setDefaults('foo', {bar: {baz: 10}})
|
|
|
|
atom.config.set('foo.bar.baz', 55, {scopeSelector: '.source.coffee'})
|
2018-01-25 05:16:49 +03:00
|
|
|
savedSettings.length = 0
|
2018-01-20 03:50:37 +03:00
|
|
|
|
|
|
|
atom.config.unset('foo.bar.baz', {scopeSelector: '.source.coffee'})
|
|
|
|
advanceClock(150)
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(savedSettings.length).toBe(1)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
it('allows removing settings for a specific source and scope selector', () => {
|
|
|
|
atom.config.set('foo.bar.baz', 55, {scopeSelector: '.source.coffee', source: 'source-a'})
|
|
|
|
atom.config.set('foo.bar.baz', 65, {scopeSelector: '.source.coffee', source: 'source-b'})
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee']})).toBe(65)
|
|
|
|
|
|
|
|
atom.config.unset('foo.bar.baz', {source: 'source-b', scopeSelector: '.source.coffee'})
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee', '.string']})).toBe(55)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('allows removing all settings for a specific source', () => {
|
|
|
|
atom.config.set('foo.bar.baz', 55, {scopeSelector: '.source.coffee', source: 'source-a'})
|
|
|
|
atom.config.set('foo.bar.baz', 65, {scopeSelector: '.source.coffee', source: 'source-b'})
|
|
|
|
atom.config.set('foo.bar.ok', 65, {scopeSelector: '.source.coffee', source: 'source-b'})
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee']})).toBe(65)
|
|
|
|
|
|
|
|
atom.config.unset(null, {source: 'source-b', scopeSelector: '.source.coffee'})
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee', '.string']})).toBe(55)
|
|
|
|
expect(atom.config.get('foo.bar.ok', {scope: ['.source.coffee', '.string']})).toBe(0)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('does not call ::save or add a scoped property when no value has been set', () => {
|
|
|
|
// see https://github.com/atom/atom/issues/4175
|
|
|
|
atom.config.setDefaults('foo', {bar: {baz: 10}})
|
|
|
|
atom.config.unset('foo.bar.baz', {scopeSelector: '.source.coffee'})
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee']})).toBe(10)
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(savedSettings.length).toBe(0)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
|
|
|
const scopedProperties = atom.config.scopedSettingsStore.propertiesForSource('user-config')
|
|
|
|
expect(scopedProperties['.coffee.source']).toBeUndefined()
|
|
|
|
})
|
|
|
|
|
|
|
|
it('removes the scoped value when it was the only set value on the object', () => {
|
|
|
|
atom.config.setDefaults('foo', {bar: {baz: 10}})
|
|
|
|
atom.config.set('foo.bar.baz', 55, {scopeSelector: '.source.coffee'})
|
|
|
|
atom.config.set('foo.bar.ok', 20, {scopeSelector: '.source.coffee'})
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee']})).toBe(55)
|
|
|
|
|
|
|
|
advanceClock(150)
|
2018-01-25 05:16:49 +03:00
|
|
|
savedSettings.length = 0
|
2018-01-20 03:50:37 +03:00
|
|
|
|
|
|
|
atom.config.unset('foo.bar.baz', {scopeSelector: '.source.coffee'})
|
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee']})).toBe(10)
|
|
|
|
expect(atom.config.get('foo.bar.ok', {scope: ['.source.coffee']})).toBe(20)
|
|
|
|
|
|
|
|
advanceClock(150)
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(savedSettings[0]['.coffee.source']).toEqual({
|
2018-01-20 03:50:37 +03:00
|
|
|
foo: {
|
|
|
|
bar: {
|
|
|
|
ok: 20
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
atom.config.unset('foo.bar.ok', {scopeSelector: '.source.coffee'})
|
|
|
|
|
|
|
|
advanceClock(150)
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(savedSettings.length).toBe(2)
|
|
|
|
expect(savedSettings[1]['.coffee.source']).toBeUndefined()
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
it('does not call ::save when the value is already at the default', () => {
|
|
|
|
atom.config.setDefaults('foo', {bar: {baz: 10}})
|
|
|
|
atom.config.set('foo.bar.baz', 55)
|
2018-01-25 05:16:49 +03:00
|
|
|
advanceClock(150)
|
|
|
|
savedSettings.length = 0
|
2018-01-20 03:50:37 +03:00
|
|
|
|
|
|
|
atom.config.unset('foo.bar.ok', {scopeSelector: '.source.coffee'})
|
2018-01-25 05:16:49 +03:00
|
|
|
advanceClock(150)
|
|
|
|
expect(savedSettings.length).toBe(0)
|
2018-01-20 03:50:37 +03:00
|
|
|
expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee']})).toBe(55)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('.onDidChange(keyPath, {scope})', () => {
|
2018-01-20 04:08:16 +03:00
|
|
|
let observeHandler = []
|
2018-01-20 03:50:37 +03:00
|
|
|
|
|
|
|
describe('when a keyPath is specified', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
observeHandler = jasmine.createSpy('observeHandler')
|
|
|
|
atom.config.set('foo.bar.baz', 'value 1')
|
2018-01-20 04:08:16 +03:00
|
|
|
atom.config.onDidChange('foo.bar.baz', observeHandler)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
it('does not fire the given callback with the current value at the keypath', () => expect(observeHandler).not.toHaveBeenCalled())
|
|
|
|
|
|
|
|
it('fires the callback every time the observed value changes', () => {
|
|
|
|
atom.config.set('foo.bar.baz', 'value 2')
|
|
|
|
expect(observeHandler).toHaveBeenCalledWith({newValue: 'value 2', oldValue: 'value 1'})
|
|
|
|
observeHandler.reset()
|
|
|
|
observeHandler.andCallFake(() => { throw new Error('oops') })
|
|
|
|
expect(() => atom.config.set('foo.bar.baz', 'value 1')).toThrow('oops')
|
|
|
|
expect(observeHandler).toHaveBeenCalledWith({newValue: 'value 1', oldValue: 'value 2'})
|
|
|
|
observeHandler.reset()
|
|
|
|
|
|
|
|
// Regression: exception in earlier handler shouldn't put observer
|
|
|
|
// into a bad state.
|
|
|
|
atom.config.set('something.else', 'new value')
|
|
|
|
expect(observeHandler).not.toHaveBeenCalled()
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('when a keyPath is not specified', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
observeHandler = jasmine.createSpy('observeHandler')
|
|
|
|
atom.config.set('foo.bar.baz', 'value 1')
|
2018-01-20 04:08:16 +03:00
|
|
|
atom.config.onDidChange(observeHandler)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
it('does not fire the given callback initially', () => expect(observeHandler).not.toHaveBeenCalled())
|
|
|
|
|
|
|
|
it('fires the callback every time any value changes', () => {
|
|
|
|
observeHandler.reset() // clear the initial call
|
|
|
|
atom.config.set('foo.bar.baz', 'value 2')
|
|
|
|
expect(observeHandler).toHaveBeenCalled()
|
|
|
|
expect(observeHandler.mostRecentCall.args[0].newValue.foo.bar.baz).toBe('value 2')
|
|
|
|
expect(observeHandler.mostRecentCall.args[0].oldValue.foo.bar.baz).toBe('value 1')
|
|
|
|
|
|
|
|
observeHandler.reset()
|
|
|
|
atom.config.set('foo.bar.baz', 'value 1')
|
|
|
|
expect(observeHandler).toHaveBeenCalled()
|
|
|
|
expect(observeHandler.mostRecentCall.args[0].newValue.foo.bar.baz).toBe('value 1')
|
|
|
|
expect(observeHandler.mostRecentCall.args[0].oldValue.foo.bar.baz).toBe('value 2')
|
|
|
|
|
|
|
|
observeHandler.reset()
|
|
|
|
atom.config.set('foo.bar.int', 1)
|
|
|
|
expect(observeHandler).toHaveBeenCalled()
|
|
|
|
expect(observeHandler.mostRecentCall.args[0].newValue.foo.bar.int).toBe(1)
|
|
|
|
expect(observeHandler.mostRecentCall.args[0].oldValue.foo.bar.int).toBe(undefined)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe("when a 'scope' is given", () =>
|
|
|
|
it('calls the supplied callback when the value at the descriptor/keypath changes', () => {
|
|
|
|
const changeSpy = jasmine.createSpy('onDidChange callback')
|
|
|
|
atom.config.onDidChange('foo.bar.baz', {scope: ['.source.coffee', '.string.quoted.double.coffee']}, changeSpy)
|
|
|
|
|
|
|
|
atom.config.set('foo.bar.baz', 12)
|
|
|
|
expect(changeSpy).toHaveBeenCalledWith({oldValue: undefined, newValue: 12})
|
|
|
|
changeSpy.reset()
|
|
|
|
|
|
|
|
atom.config.set('foo.bar.baz', 22, {scopeSelector: '.source .string.quoted.double', source: 'a'})
|
|
|
|
expect(changeSpy).toHaveBeenCalledWith({oldValue: 12, newValue: 22})
|
|
|
|
changeSpy.reset()
|
|
|
|
|
|
|
|
atom.config.set('foo.bar.baz', 42, {scopeSelector: '.source.coffee .string.quoted.double.coffee', source: 'b'})
|
|
|
|
expect(changeSpy).toHaveBeenCalledWith({oldValue: 22, newValue: 42})
|
|
|
|
changeSpy.reset()
|
|
|
|
|
|
|
|
atom.config.unset(null, {scopeSelector: '.source.coffee .string.quoted.double.coffee', source: 'b'})
|
|
|
|
expect(changeSpy).toHaveBeenCalledWith({oldValue: 42, newValue: 22})
|
|
|
|
changeSpy.reset()
|
|
|
|
|
|
|
|
atom.config.unset(null, {scopeSelector: '.source .string.quoted.double', source: 'a'})
|
|
|
|
expect(changeSpy).toHaveBeenCalledWith({oldValue: 22, newValue: 12})
|
|
|
|
changeSpy.reset()
|
|
|
|
|
|
|
|
atom.config.set('foo.bar.baz', undefined)
|
|
|
|
expect(changeSpy).toHaveBeenCalledWith({oldValue: 12, newValue: undefined})
|
|
|
|
changeSpy.reset()
|
|
|
|
})
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('.observe(keyPath, {scope})', () => {
|
2018-01-20 04:08:16 +03:00
|
|
|
let [observeHandler, observeSubscription] = []
|
2018-01-20 03:50:37 +03:00
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
observeHandler = jasmine.createSpy('observeHandler')
|
|
|
|
atom.config.set('foo.bar.baz', 'value 1')
|
|
|
|
observeSubscription = atom.config.observe('foo.bar.baz', observeHandler)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('fires the given callback with the current value at the keypath', () => expect(observeHandler).toHaveBeenCalledWith('value 1'))
|
|
|
|
|
|
|
|
it('fires the callback every time the observed value changes', () => {
|
|
|
|
observeHandler.reset() // clear the initial call
|
|
|
|
atom.config.set('foo.bar.baz', 'value 2')
|
|
|
|
expect(observeHandler).toHaveBeenCalledWith('value 2')
|
|
|
|
|
|
|
|
observeHandler.reset()
|
|
|
|
atom.config.set('foo.bar.baz', 'value 1')
|
|
|
|
expect(observeHandler).toHaveBeenCalledWith('value 1')
|
|
|
|
advanceClock(100) // complete pending save that was requested in ::set
|
|
|
|
|
|
|
|
observeHandler.reset()
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.resetUserSettings({foo: {}})
|
2018-01-20 03:50:37 +03:00
|
|
|
expect(observeHandler).toHaveBeenCalledWith(undefined)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('fires the callback when the observed value is deleted', () => {
|
|
|
|
observeHandler.reset() // clear the initial call
|
|
|
|
atom.config.set('foo.bar.baz', undefined)
|
|
|
|
expect(observeHandler).toHaveBeenCalledWith(undefined)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('fires the callback when the full key path goes into and out of existence', () => {
|
|
|
|
observeHandler.reset() // clear the initial call
|
|
|
|
atom.config.set('foo.bar', undefined)
|
|
|
|
expect(observeHandler).toHaveBeenCalledWith(undefined)
|
|
|
|
|
|
|
|
observeHandler.reset()
|
|
|
|
atom.config.set('foo.bar.baz', "i'm back")
|
|
|
|
expect(observeHandler).toHaveBeenCalledWith("i'm back")
|
|
|
|
})
|
|
|
|
|
|
|
|
it('does not fire the callback once the subscription is disposed', () => {
|
|
|
|
observeHandler.reset() // clear the initial call
|
|
|
|
observeSubscription.dispose()
|
|
|
|
atom.config.set('foo.bar.baz', 'value 2')
|
|
|
|
expect(observeHandler).not.toHaveBeenCalled()
|
|
|
|
})
|
|
|
|
|
|
|
|
it('does not fire the callback for a similarly named keyPath', () => {
|
|
|
|
const bazCatHandler = jasmine.createSpy('bazCatHandler')
|
|
|
|
observeSubscription = atom.config.observe('foo.bar.bazCat', bazCatHandler)
|
|
|
|
|
|
|
|
bazCatHandler.reset()
|
|
|
|
atom.config.set('foo.bar.baz', 'value 10')
|
|
|
|
expect(bazCatHandler).not.toHaveBeenCalled()
|
|
|
|
})
|
|
|
|
|
2018-01-20 03:54:53 +03:00
|
|
|
describe("when a 'scope' is given", () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
let otherHandler = null
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
observeSubscription.dispose()
|
|
|
|
otherHandler = jasmine.createSpy('otherHandler')
|
|
|
|
})
|
|
|
|
|
|
|
|
it('allows settings to be observed in a specific scope', () => {
|
|
|
|
atom.config.observe('foo.bar.baz', {scope: ['.some.scope']}, observeHandler)
|
|
|
|
atom.config.observe('foo.bar.baz', {scope: ['.another.scope']}, otherHandler)
|
|
|
|
|
|
|
|
atom.config.set('foo.bar.baz', 'value 2', {scopeSelector: '.some'})
|
|
|
|
expect(observeHandler).toHaveBeenCalledWith('value 2')
|
|
|
|
expect(otherHandler).not.toHaveBeenCalledWith('value 2')
|
|
|
|
})
|
|
|
|
|
|
|
|
it('calls the callback when properties with more specific selectors are removed', () => {
|
|
|
|
const changeSpy = jasmine.createSpy()
|
|
|
|
atom.config.observe('foo.bar.baz', {scope: ['.source.coffee', '.string.quoted.double.coffee']}, changeSpy)
|
|
|
|
expect(changeSpy).toHaveBeenCalledWith('value 1')
|
|
|
|
changeSpy.reset()
|
|
|
|
|
|
|
|
atom.config.set('foo.bar.baz', 12)
|
|
|
|
expect(changeSpy).toHaveBeenCalledWith(12)
|
|
|
|
changeSpy.reset()
|
|
|
|
|
|
|
|
atom.config.set('foo.bar.baz', 22, {scopeSelector: '.source .string.quoted.double', source: 'a'})
|
|
|
|
expect(changeSpy).toHaveBeenCalledWith(22)
|
|
|
|
changeSpy.reset()
|
|
|
|
|
|
|
|
atom.config.set('foo.bar.baz', 42, {scopeSelector: '.source.coffee .string.quoted.double.coffee', source: 'b'})
|
|
|
|
expect(changeSpy).toHaveBeenCalledWith(42)
|
|
|
|
changeSpy.reset()
|
|
|
|
|
|
|
|
atom.config.unset(null, {scopeSelector: '.source.coffee .string.quoted.double.coffee', source: 'b'})
|
|
|
|
expect(changeSpy).toHaveBeenCalledWith(22)
|
|
|
|
changeSpy.reset()
|
|
|
|
|
|
|
|
atom.config.unset(null, {scopeSelector: '.source .string.quoted.double', source: 'a'})
|
|
|
|
expect(changeSpy).toHaveBeenCalledWith(12)
|
|
|
|
changeSpy.reset()
|
|
|
|
|
|
|
|
atom.config.set('foo.bar.baz', undefined)
|
|
|
|
expect(changeSpy).toHaveBeenCalledWith(undefined)
|
|
|
|
changeSpy.reset()
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('.transact(callback)', () => {
|
|
|
|
let changeSpy = null
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
changeSpy = jasmine.createSpy('onDidChange callback')
|
|
|
|
atom.config.onDidChange('foo.bar.baz', changeSpy)
|
|
|
|
})
|
|
|
|
|
2018-01-20 03:54:53 +03:00
|
|
|
it('allows only one change event for the duration of the given callback', () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
atom.config.transact(() => {
|
|
|
|
atom.config.set('foo.bar.baz', 1)
|
|
|
|
atom.config.set('foo.bar.baz', 2)
|
|
|
|
atom.config.set('foo.bar.baz', 3)
|
|
|
|
})
|
|
|
|
|
|
|
|
expect(changeSpy.callCount).toBe(1)
|
|
|
|
expect(changeSpy.argsForCall[0][0]).toEqual({newValue: 3, oldValue: undefined})
|
|
|
|
})
|
|
|
|
|
|
|
|
it('does not emit an event if no changes occur while paused', () => {
|
|
|
|
atom.config.transact(() => {})
|
|
|
|
expect(changeSpy).not.toHaveBeenCalled()
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('.transactAsync(callback)', () => {
|
|
|
|
let changeSpy = null
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
changeSpy = jasmine.createSpy('onDidChange callback')
|
|
|
|
atom.config.onDidChange('foo.bar.baz', changeSpy)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('allows only one change event for the duration of the given promise if it gets resolved', () => {
|
|
|
|
let promiseResult = null
|
|
|
|
const transactionPromise = atom.config.transactAsync(() => {
|
|
|
|
atom.config.set('foo.bar.baz', 1)
|
|
|
|
atom.config.set('foo.bar.baz', 2)
|
|
|
|
atom.config.set('foo.bar.baz', 3)
|
|
|
|
return Promise.resolve('a result')
|
|
|
|
})
|
|
|
|
|
2018-01-20 04:08:16 +03:00
|
|
|
waitsForPromise(() => transactionPromise.then(result => {
|
|
|
|
promiseResult = result
|
|
|
|
}))
|
2018-01-20 03:50:37 +03:00
|
|
|
|
|
|
|
runs(() => {
|
|
|
|
expect(promiseResult).toBe('a result')
|
|
|
|
expect(changeSpy.callCount).toBe(1)
|
|
|
|
expect(changeSpy.argsForCall[0][0]).toEqual({newValue: 3, oldValue: undefined})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2018-01-20 03:54:53 +03:00
|
|
|
it('allows only one change event for the duration of the given promise if it gets rejected', () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
let promiseError = null
|
2018-01-20 03:54:53 +03:00
|
|
|
const transactionPromise = atom.config.transactAsync(() => {
|
2018-01-20 03:50:37 +03:00
|
|
|
atom.config.set('foo.bar.baz', 1)
|
|
|
|
atom.config.set('foo.bar.baz', 2)
|
|
|
|
atom.config.set('foo.bar.baz', 3)
|
2018-01-20 04:08:16 +03:00
|
|
|
return Promise.reject(new Error('an error'))
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-20 04:08:16 +03:00
|
|
|
waitsForPromise(() => transactionPromise.catch(error => {
|
|
|
|
promiseError = error
|
|
|
|
}))
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-20 03:54:53 +03:00
|
|
|
runs(() => {
|
2018-01-20 04:08:16 +03:00
|
|
|
expect(promiseError.message).toBe('an error')
|
2018-01-20 03:50:37 +03:00
|
|
|
expect(changeSpy.callCount).toBe(1)
|
|
|
|
expect(changeSpy.argsForCall[0][0]).toEqual({newValue: 3, oldValue: undefined})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
it('allows only one change event even when the given callback throws', () => {
|
|
|
|
const error = new Error('Oops!')
|
|
|
|
let promiseError = null
|
|
|
|
const transactionPromise = atom.config.transactAsync(() => {
|
|
|
|
atom.config.set('foo.bar.baz', 1)
|
|
|
|
atom.config.set('foo.bar.baz', 2)
|
|
|
|
atom.config.set('foo.bar.baz', 3)
|
|
|
|
throw error
|
|
|
|
})
|
|
|
|
|
2018-01-20 04:08:16 +03:00
|
|
|
waitsForPromise(() => transactionPromise.catch(e => {
|
|
|
|
promiseError = e
|
|
|
|
}))
|
2018-01-20 03:50:37 +03:00
|
|
|
|
|
|
|
runs(() => {
|
|
|
|
expect(promiseError).toBe(error)
|
|
|
|
expect(changeSpy.callCount).toBe(1)
|
|
|
|
expect(changeSpy.argsForCall[0][0]).toEqual({newValue: 3, oldValue: undefined})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('.getSources()', () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
it("returns an array of all of the config's source names", () => {
|
|
|
|
expect(atom.config.getSources()).toEqual([])
|
|
|
|
|
|
|
|
atom.config.set('a.b', 1, {scopeSelector: '.x1', source: 'source-1'})
|
|
|
|
atom.config.set('a.c', 1, {scopeSelector: '.x1', source: 'source-1'})
|
|
|
|
atom.config.set('a.b', 2, {scopeSelector: '.x2', source: 'source-2'})
|
|
|
|
atom.config.set('a.b', 1, {scopeSelector: '.x3', source: 'source-3'})
|
|
|
|
|
|
|
|
expect(atom.config.getSources()).toEqual([
|
|
|
|
'source-1',
|
|
|
|
'source-2',
|
|
|
|
'source-3'
|
|
|
|
])
|
|
|
|
})
|
2018-01-25 05:16:49 +03:00
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('.save()', () => {
|
|
|
|
it('calls the save callback with any non-default properties', () => {
|
|
|
|
atom.config.set('a.b.c', 1)
|
|
|
|
atom.config.set('a.b.d', 2)
|
|
|
|
atom.config.set('x.y.z', 3)
|
|
|
|
atom.config.setDefaults('a.b', {e: 4, f: 5})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.save()
|
|
|
|
expect(savedSettings).toEqual([{'*': atom.config.settings}])
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('serializes properties in alphabetical order', () => {
|
|
|
|
atom.config.set('foo', 1)
|
|
|
|
atom.config.set('bar', 2)
|
|
|
|
atom.config.set('baz.foo', 3)
|
|
|
|
atom.config.set('baz.bar', 4)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
savedSettings.length = 0
|
|
|
|
atom.config.save()
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
const writtenConfig = savedSettings[0]
|
|
|
|
expect(writtenConfig).toEqual({'*': atom.config.settings})
|
|
|
|
|
|
|
|
let expectedKeys = ['bar', 'baz', 'foo']
|
|
|
|
let foundKeys = []
|
|
|
|
for (const key in writtenConfig['*']) {
|
|
|
|
if ((expectedKeys).includes(key)) {
|
|
|
|
foundKeys.push(key)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
expect(foundKeys).toEqual(expectedKeys)
|
|
|
|
expectedKeys = ['bar', 'foo']
|
|
|
|
foundKeys = []
|
|
|
|
for (const key in writtenConfig['*']['baz']) {
|
|
|
|
if ((expectedKeys).includes(key)) {
|
|
|
|
foundKeys.push(key)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
expect(foundKeys).toEqual(expectedKeys)
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when scoped settings are defined', () => {
|
|
|
|
it('serializes any explicitly set config settings', () => {
|
|
|
|
atom.config.set('foo.bar', 'ruby', {scopeSelector: '.source.ruby'})
|
|
|
|
atom.config.set('foo.omg', 'wow', {scopeSelector: '.source.ruby'})
|
|
|
|
atom.config.set('foo.bar', 'coffee', {scopeSelector: '.source.coffee'})
|
|
|
|
|
|
|
|
savedSettings.length = 0
|
|
|
|
atom.config.save()
|
|
|
|
|
|
|
|
const writtenConfig = savedSettings[0]
|
|
|
|
expect(writtenConfig).toEqualJson({
|
|
|
|
'*':
|
|
|
|
atom.config.settings,
|
|
|
|
'.ruby.source': {
|
|
|
|
foo: {
|
|
|
|
bar: 'ruby',
|
|
|
|
omg: 'wow'
|
2018-01-20 03:50:37 +03:00
|
|
|
}
|
2018-01-25 05:16:49 +03:00
|
|
|
},
|
|
|
|
'.coffee.source': {
|
|
|
|
foo: {
|
|
|
|
bar: 'coffee'
|
2018-01-20 03:50:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
2018-01-25 05:16:49 +03:00
|
|
|
})
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('.resetUserSettings()', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
atom.config.setSchema('foo', {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
bar: {
|
|
|
|
type: 'string',
|
|
|
|
default: 'def'
|
|
|
|
},
|
|
|
|
int: {
|
|
|
|
type: 'integer',
|
|
|
|
default: 12
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when the config file contains scoped settings', () => {
|
|
|
|
it('updates the config data based on the file contents', () => {
|
|
|
|
atom.config.resetUserSettings({
|
|
|
|
'*': {
|
|
|
|
foo: {
|
|
|
|
bar: 'baz'
|
2018-01-20 03:50:37 +03:00
|
|
|
}
|
2018-01-25 05:16:49 +03:00
|
|
|
},
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
'.source.ruby': {
|
|
|
|
foo: {
|
|
|
|
bar: 'more-specific'
|
|
|
|
}
|
|
|
|
}
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.get('foo.bar')).toBe('baz')
|
|
|
|
expect(atom.config.get('foo.bar', {scope: ['.source.ruby']})).toBe('more-specific')
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when the config file does not conform to the schema', () => {
|
|
|
|
it('validates and does not load the incorrect values', () => {
|
|
|
|
atom.config.resetUserSettings({
|
|
|
|
'*': {
|
|
|
|
foo: {
|
|
|
|
bar: 'omg',
|
|
|
|
int: 'baz'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
'.source.ruby': {
|
|
|
|
foo: {
|
|
|
|
bar: 'scoped',
|
|
|
|
int: 'nope'
|
2018-01-20 03:50:37 +03:00
|
|
|
}
|
|
|
|
}
|
2018-01-25 05:16:49 +03:00
|
|
|
})
|
|
|
|
expect(atom.config.get('foo.int')).toBe(12)
|
|
|
|
expect(atom.config.get('foo.bar')).toBe('omg')
|
|
|
|
expect(atom.config.get('foo.int', {scope: ['.source.ruby']})).toBe(12)
|
|
|
|
expect(atom.config.get('foo.bar', {scope: ['.source.ruby']})).toBe('scoped')
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
2018-01-25 05:16:49 +03:00
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('updates the config data based on the file contents', () => {
|
|
|
|
atom.config.resetUserSettings({foo: {bar: 'baz'}})
|
|
|
|
expect(atom.config.get('foo.bar')).toBe('baz')
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('notifies observers for updated keypaths on load', () => {
|
|
|
|
const observeHandler = jasmine.createSpy('observeHandler')
|
|
|
|
atom.config.observe('foo.bar', observeHandler)
|
|
|
|
atom.config.resetUserSettings({foo: {bar: 'baz'}})
|
|
|
|
expect(observeHandler).toHaveBeenCalledWith('baz')
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when the config file contains values that do not adhere to the schema', () => {
|
|
|
|
it('updates the only the settings that have values matching the schema', () => {
|
|
|
|
atom.config.resetUserSettings({
|
|
|
|
foo: {
|
|
|
|
bar: 'baz',
|
|
|
|
int: 'bad value'
|
|
|
|
}
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.get('foo.bar')).toBe('baz')
|
|
|
|
expect(atom.config.get('foo.int')).toBe(12)
|
|
|
|
expect(console.warn).toHaveBeenCalled()
|
|
|
|
expect(console.warn.mostRecentCall.args[0]).toContain('foo.int')
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
2018-01-25 05:16:49 +03:00
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('does not fire a change event for paths that did not change', () => {
|
|
|
|
atom.config.resetUserSettings({
|
|
|
|
foo: {bar: 'baz', int: 3}
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
const noChangeSpy = jasmine.createSpy('unchanged')
|
|
|
|
atom.config.onDidChange('foo.bar', (noChangeSpy))
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.resetUserSettings({
|
|
|
|
foo: {bar: 'baz', int: 4}
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(noChangeSpy).not.toHaveBeenCalled()
|
|
|
|
expect(atom.config.get('foo.bar')).toBe('baz')
|
|
|
|
expect(atom.config.get('foo.int')).toBe(4)
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('does not fire a change event for paths whose non-primitive values did not change', () => {
|
|
|
|
atom.config.setSchema('foo.bar', {
|
|
|
|
type: 'array',
|
|
|
|
items: {
|
|
|
|
type: 'string'
|
|
|
|
}
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.resetUserSettings({
|
|
|
|
foo: {bar: ['baz', 'quux'], int: 2}
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
const noChangeSpy = jasmine.createSpy('unchanged')
|
|
|
|
atom.config.onDidChange('foo.bar', (noChangeSpy))
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.resetUserSettings({
|
|
|
|
foo: {bar: ['baz', 'quux'], int: 2}
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(noChangeSpy).not.toHaveBeenCalled()
|
|
|
|
expect(atom.config.get('foo.bar')).toEqual(['baz', 'quux'])
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when a setting with a default is removed', () => {
|
|
|
|
it('resets the setting back to the default', () => {
|
|
|
|
atom.config.resetUserSettings({
|
|
|
|
foo: {bar: ['baz', 'quux'], int: 2}
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
const events = []
|
|
|
|
atom.config.onDidChange('foo.int', event => events.push(event))
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.resetUserSettings({
|
|
|
|
foo: {bar: ['baz', 'quux']}
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(events.length).toBe(1)
|
|
|
|
expect(events[0]).toEqual({oldValue: 2, newValue: 12})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('.pushAtKeyPath(keyPath, value)', () => {
|
|
|
|
it('pushes the given value to the array at the key path and updates observers', () => {
|
|
|
|
atom.config.set('foo.bar.baz', ['a'])
|
|
|
|
const observeHandler = jasmine.createSpy('observeHandler')
|
|
|
|
atom.config.observe('foo.bar.baz', observeHandler)
|
|
|
|
observeHandler.reset()
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.pushAtKeyPath('foo.bar.baz', 'b')).toBe(2)
|
|
|
|
expect(atom.config.get('foo.bar.baz')).toEqual(['a', 'b'])
|
|
|
|
expect(observeHandler).toHaveBeenCalledWith(atom.config.get('foo.bar.baz'))
|
|
|
|
})
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('.unshiftAtKeyPath(keyPath, value)', () => {
|
|
|
|
it('unshifts the given value to the array at the key path and updates observers', () => {
|
|
|
|
atom.config.set('foo.bar.baz', ['b'])
|
|
|
|
const observeHandler = jasmine.createSpy('observeHandler')
|
|
|
|
atom.config.observe('foo.bar.baz', observeHandler)
|
|
|
|
observeHandler.reset()
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.unshiftAtKeyPath('foo.bar.baz', 'a')).toBe(2)
|
|
|
|
expect(atom.config.get('foo.bar.baz')).toEqual(['a', 'b'])
|
|
|
|
expect(observeHandler).toHaveBeenCalledWith(atom.config.get('foo.bar.baz'))
|
|
|
|
})
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('.removeAtKeyPath(keyPath, value)', () => {
|
|
|
|
it('removes the given value from the array at the key path and updates observers', () => {
|
|
|
|
atom.config.set('foo.bar.baz', ['a', 'b', 'c'])
|
|
|
|
const observeHandler = jasmine.createSpy('observeHandler')
|
|
|
|
atom.config.observe('foo.bar.baz', observeHandler)
|
|
|
|
observeHandler.reset()
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.removeAtKeyPath('foo.bar.baz', 'b')).toEqual(['a', 'c'])
|
|
|
|
expect(atom.config.get('foo.bar.baz')).toEqual(['a', 'c'])
|
|
|
|
expect(observeHandler).toHaveBeenCalledWith(atom.config.get('foo.bar.baz'))
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
2018-01-25 05:16:49 +03:00
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('.setDefaults(keyPath, defaults)', () => {
|
|
|
|
it('assigns any previously-unassigned keys to the object at the key path', () => {
|
|
|
|
atom.config.set('foo.bar.baz', {a: 1})
|
|
|
|
atom.config.setDefaults('foo.bar.baz', {a: 2, b: 3, c: 4})
|
|
|
|
expect(atom.config.get('foo.bar.baz.a')).toBe(1)
|
|
|
|
expect(atom.config.get('foo.bar.baz.b')).toBe(3)
|
|
|
|
expect(atom.config.get('foo.bar.baz.c')).toBe(4)
|
|
|
|
|
|
|
|
atom.config.setDefaults('foo.quux', {x: 0, y: 1})
|
|
|
|
expect(atom.config.get('foo.quux.x')).toBe(0)
|
|
|
|
expect(atom.config.get('foo.quux.y')).toBe(1)
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('emits an updated event', () => {
|
|
|
|
const updatedCallback = jasmine.createSpy('updated')
|
|
|
|
atom.config.onDidChange('foo.bar.baz.a', updatedCallback)
|
|
|
|
expect(updatedCallback.callCount).toBe(0)
|
|
|
|
atom.config.setDefaults('foo.bar.baz', {a: 2})
|
|
|
|
expect(updatedCallback.callCount).toBe(1)
|
|
|
|
})
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('.setSchema(keyPath, schema)', () => {
|
|
|
|
it('creates a properly nested schema', () => {
|
|
|
|
const schema = {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
anInt: {
|
|
|
|
type: 'integer',
|
|
|
|
default: 12
|
|
|
|
}
|
|
|
|
}
|
2018-01-20 03:50:37 +03:00
|
|
|
}
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.setSchema('foo.bar', schema)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.getSchema('foo')).toEqual({
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
bar: {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
anInt: {
|
|
|
|
type: 'integer',
|
|
|
|
default: 12
|
|
|
|
}
|
2018-01-20 03:50:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-01-25 05:16:49 +03:00
|
|
|
})
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('sets defaults specified by the schema', () => {
|
|
|
|
const schema = {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
anInt: {
|
|
|
|
type: 'integer',
|
|
|
|
default: 12
|
|
|
|
},
|
|
|
|
anObject: {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
nestedInt: {
|
|
|
|
type: 'integer',
|
|
|
|
default: 24
|
|
|
|
},
|
|
|
|
nestedObject: {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
superNestedInt: {
|
|
|
|
type: 'integer',
|
|
|
|
default: 36
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.setSchema('foo.bar', schema)
|
|
|
|
expect(atom.config.get('foo.bar.anInt')).toBe(12)
|
|
|
|
expect(atom.config.get('foo.bar.anObject')).toEqual({
|
|
|
|
nestedInt: 24,
|
|
|
|
nestedObject: {
|
|
|
|
superNestedInt: 36
|
|
|
|
}
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.get('foo')).toEqual({
|
|
|
|
bar: {
|
|
|
|
anInt: 12,
|
|
|
|
anObject: {
|
|
|
|
nestedInt: 24,
|
|
|
|
nestedObject: {
|
|
|
|
superNestedInt: 36
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.set('foo.bar.anObject.nestedObject.superNestedInt', 37)
|
|
|
|
expect(atom.config.get('foo')).toEqual({
|
|
|
|
bar: {
|
|
|
|
anInt: 12,
|
|
|
|
anObject: {
|
|
|
|
nestedInt: 24,
|
|
|
|
nestedObject: {
|
|
|
|
superNestedInt: 37
|
2018-01-20 03:50:37 +03:00
|
|
|
}
|
2018-01-25 05:16:49 +03:00
|
|
|
}
|
|
|
|
}
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
2018-01-25 05:16:49 +03:00
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('can set a non-object schema', () => {
|
|
|
|
const schema = {
|
|
|
|
type: 'integer',
|
|
|
|
default: 12
|
|
|
|
}
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.setSchema('foo.bar.anInt', schema)
|
|
|
|
expect(atom.config.get('foo.bar.anInt')).toBe(12)
|
|
|
|
expect(atom.config.getSchema('foo.bar.anInt')).toEqual({
|
|
|
|
type: 'integer',
|
|
|
|
default: 12
|
|
|
|
})
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('allows the schema to be retrieved via ::getSchema', () => {
|
|
|
|
const schema = {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
anInt: {
|
|
|
|
type: 'integer',
|
|
|
|
default: 12
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.setSchema('foo.bar', schema)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.getSchema('foo.bar')).toEqual({
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
anInt: {
|
|
|
|
type: 'integer',
|
|
|
|
default: 12
|
|
|
|
}
|
|
|
|
}
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.getSchema('foo.bar.anInt')).toEqual({
|
|
|
|
type: 'integer',
|
|
|
|
default: 12
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.getSchema('foo.baz')).toEqual({type: 'any'})
|
|
|
|
expect(atom.config.getSchema('foo.bar.anInt.baz')).toBe(null)
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('respects the schema for scoped settings', () => {
|
|
|
|
const schema = {
|
|
|
|
type: 'string',
|
|
|
|
default: 'ok',
|
|
|
|
scopes: {
|
|
|
|
'.source.js': {
|
|
|
|
default: 'omg'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
atom.config.setSchema('foo.bar.str', schema)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.get('foo.bar.str')).toBe('ok')
|
|
|
|
expect(atom.config.get('foo.bar.str', {scope: ['.source.js']})).toBe('omg')
|
|
|
|
expect(atom.config.get('foo.bar.str', {scope: ['.source.coffee']})).toBe('ok')
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when a schema is added after config values have been set', () => {
|
|
|
|
let schema = null
|
2018-01-20 03:50:37 +03:00
|
|
|
beforeEach(() => {
|
2018-01-25 05:16:49 +03:00
|
|
|
schema = {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
int: {
|
|
|
|
type: 'integer',
|
|
|
|
default: 2
|
|
|
|
},
|
|
|
|
str: {
|
|
|
|
type: 'string',
|
|
|
|
default: 'def'
|
|
|
|
}
|
|
|
|
}
|
2018-01-20 03:50:37 +03:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('respects the new schema when values are set', () => {
|
|
|
|
expect(atom.config.set('foo.bar.str', 'global')).toBe(true)
|
|
|
|
expect(atom.config.set('foo.bar.str', 'scoped', {scopeSelector: '.source.js'})).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.str')).toBe('global')
|
|
|
|
expect(atom.config.get('foo.bar.str', {scope: ['.source.js']})).toBe('scoped')
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.set('foo.bar.noschema', 'nsGlobal')).toBe(true)
|
|
|
|
expect(atom.config.set('foo.bar.noschema', 'nsScoped', {scopeSelector: '.source.js'})).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.noschema')).toBe('nsGlobal')
|
|
|
|
expect(atom.config.get('foo.bar.noschema', {scope: ['.source.js']})).toBe('nsScoped')
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.set('foo.bar.int', 'nope')).toBe(true)
|
|
|
|
expect(atom.config.set('foo.bar.int', 'notanint', {scopeSelector: '.source.js'})).toBe(true)
|
|
|
|
expect(atom.config.set('foo.bar.int', 23, {scopeSelector: '.source.coffee'})).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.int')).toBe('nope')
|
|
|
|
expect(atom.config.get('foo.bar.int', {scope: ['.source.js']})).toBe('notanint')
|
|
|
|
expect(atom.config.get('foo.bar.int', {scope: ['.source.coffee']})).toBe(23)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.setSchema('foo.bar', schema)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.get('foo.bar.str')).toBe('global')
|
|
|
|
expect(atom.config.get('foo.bar.str', {scope: ['.source.js']})).toBe('scoped')
|
|
|
|
expect(atom.config.get('foo.bar.noschema')).toBe('nsGlobal')
|
|
|
|
expect(atom.config.get('foo.bar.noschema', {scope: ['.source.js']})).toBe('nsScoped')
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.get('foo.bar.int')).toBe(2)
|
|
|
|
expect(atom.config.get('foo.bar.int', {scope: ['.source.js']})).toBe(2)
|
|
|
|
expect(atom.config.get('foo.bar.int', {scope: ['.source.coffee']})).toBe(23)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('sets all values that adhere to the schema', () => {
|
|
|
|
expect(atom.config.set('foo.bar.int', 10)).toBe(true)
|
|
|
|
expect(atom.config.set('foo.bar.int', 15, {scopeSelector: '.source.js'})).toBe(true)
|
|
|
|
expect(atom.config.set('foo.bar.int', 23, {scopeSelector: '.source.coffee'})).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.int')).toBe(10)
|
|
|
|
expect(atom.config.get('foo.bar.int', {scope: ['.source.js']})).toBe(15)
|
|
|
|
expect(atom.config.get('foo.bar.int', {scope: ['.source.coffee']})).toBe(23)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.setSchema('foo.bar', schema)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.get('foo.bar.int')).toBe(10)
|
|
|
|
expect(atom.config.get('foo.bar.int', {scope: ['.source.js']})).toBe(15)
|
|
|
|
expect(atom.config.get('foo.bar.int', {scope: ['.source.coffee']})).toBe(23)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
2018-01-25 05:16:49 +03:00
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when the value has an "integer" type', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
const schema = {
|
|
|
|
type: 'integer',
|
|
|
|
default: 12
|
|
|
|
}
|
|
|
|
atom.config.setSchema('foo.bar.anInt', schema)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('coerces a string to an int', () => {
|
|
|
|
atom.config.set('foo.bar.anInt', '123')
|
|
|
|
expect(atom.config.get('foo.bar.anInt')).toBe(123)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('does not allow infinity', () => {
|
|
|
|
atom.config.set('foo.bar.anInt', Infinity)
|
2018-01-20 03:50:37 +03:00
|
|
|
expect(atom.config.get('foo.bar.anInt')).toBe(12)
|
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('coerces a float to an int', () => {
|
|
|
|
atom.config.set('foo.bar.anInt', 12.3)
|
2018-01-20 03:50:37 +03:00
|
|
|
expect(atom.config.get('foo.bar.anInt')).toBe(12)
|
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('will not set non-integers', () => {
|
|
|
|
atom.config.set('foo.bar.anInt', null)
|
|
|
|
expect(atom.config.get('foo.bar.anInt')).toBe(12)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.set('foo.bar.anInt', 'nope')
|
|
|
|
expect(atom.config.get('foo.bar.anInt')).toBe(12)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when the minimum and maximum keys are used', () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
beforeEach(() => {
|
|
|
|
const schema = {
|
|
|
|
type: 'integer',
|
2018-01-25 05:16:49 +03:00
|
|
|
minimum: 10,
|
|
|
|
maximum: 20,
|
2018-01-20 03:50:37 +03:00
|
|
|
default: 12
|
|
|
|
}
|
|
|
|
atom.config.setSchema('foo.bar.anInt', schema)
|
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('keeps the specified value within the specified range', () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
atom.config.set('foo.bar.anInt', '123')
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.get('foo.bar.anInt')).toBe(20)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.set('foo.bar.anInt', '1')
|
|
|
|
expect(atom.config.get('foo.bar.anInt')).toBe(10)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
2018-01-25 05:16:49 +03:00
|
|
|
})
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when the value has an "integer" and "string" type', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
const schema = {
|
|
|
|
type: ['integer', 'string'],
|
|
|
|
default: 12
|
|
|
|
}
|
|
|
|
atom.config.setSchema('foo.bar.anInt', schema)
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('can coerce an int, and fallback to a string', () => {
|
|
|
|
atom.config.set('foo.bar.anInt', '123')
|
|
|
|
expect(atom.config.get('foo.bar.anInt')).toBe(123)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.set('foo.bar.anInt', 'cats')
|
|
|
|
expect(atom.config.get('foo.bar.anInt')).toBe('cats')
|
|
|
|
})
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when the value has an "string" and "boolean" type', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
const schema = {
|
|
|
|
type: ['string', 'boolean'],
|
|
|
|
default: 'def'
|
|
|
|
}
|
|
|
|
atom.config.setSchema('foo.bar', schema)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('can set a string, a boolean, and revert back to the default', () => {
|
|
|
|
atom.config.set('foo.bar', 'ok')
|
|
|
|
expect(atom.config.get('foo.bar')).toBe('ok')
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.set('foo.bar', false)
|
|
|
|
expect(atom.config.get('foo.bar')).toBe(false)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.set('foo.bar', undefined)
|
|
|
|
expect(atom.config.get('foo.bar')).toBe('def')
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
2018-01-25 05:16:49 +03:00
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when the value has a "number" type', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
const schema = {
|
|
|
|
type: 'number',
|
|
|
|
default: 12.1
|
|
|
|
}
|
|
|
|
atom.config.setSchema('foo.bar.aFloat', schema)
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('coerces a string to a float', () => {
|
|
|
|
atom.config.set('foo.bar.aFloat', '12.23')
|
|
|
|
expect(atom.config.get('foo.bar.aFloat')).toBe(12.23)
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('will not set non-numbers', () => {
|
|
|
|
atom.config.set('foo.bar.aFloat', null)
|
|
|
|
expect(atom.config.get('foo.bar.aFloat')).toBe(12.1)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.set('foo.bar.aFloat', 'nope')
|
|
|
|
expect(atom.config.get('foo.bar.aFloat')).toBe(12.1)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when the minimum and maximum keys are used', () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
beforeEach(() => {
|
|
|
|
const schema = {
|
|
|
|
type: 'number',
|
2018-01-25 05:16:49 +03:00
|
|
|
minimum: 11.2,
|
|
|
|
maximum: 25.4,
|
2018-01-20 03:50:37 +03:00
|
|
|
default: 12.1
|
|
|
|
}
|
|
|
|
atom.config.setSchema('foo.bar.aFloat', schema)
|
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('keeps the specified value within the specified range', () => {
|
|
|
|
atom.config.set('foo.bar.aFloat', '123.2')
|
|
|
|
expect(atom.config.get('foo.bar.aFloat')).toBe(25.4)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.set('foo.bar.aFloat', '1.0')
|
|
|
|
expect(atom.config.get('foo.bar.aFloat')).toBe(11.2)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
2018-01-25 05:16:49 +03:00
|
|
|
})
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when the value has a "boolean" type', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
const schema = {
|
|
|
|
type: 'boolean',
|
|
|
|
default: true
|
|
|
|
}
|
|
|
|
atom.config.setSchema('foo.bar.aBool', schema)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('coerces various types to a boolean', () => {
|
|
|
|
atom.config.set('foo.bar.aBool', 'true')
|
|
|
|
expect(atom.config.get('foo.bar.aBool')).toBe(true)
|
|
|
|
atom.config.set('foo.bar.aBool', 'false')
|
|
|
|
expect(atom.config.get('foo.bar.aBool')).toBe(false)
|
|
|
|
atom.config.set('foo.bar.aBool', 'TRUE')
|
|
|
|
expect(atom.config.get('foo.bar.aBool')).toBe(true)
|
|
|
|
atom.config.set('foo.bar.aBool', 'FALSE')
|
|
|
|
expect(atom.config.get('foo.bar.aBool')).toBe(false)
|
|
|
|
atom.config.set('foo.bar.aBool', 1)
|
|
|
|
expect(atom.config.get('foo.bar.aBool')).toBe(false)
|
|
|
|
atom.config.set('foo.bar.aBool', 0)
|
|
|
|
expect(atom.config.get('foo.bar.aBool')).toBe(false)
|
|
|
|
atom.config.set('foo.bar.aBool', {})
|
|
|
|
expect(atom.config.get('foo.bar.aBool')).toBe(false)
|
|
|
|
atom.config.set('foo.bar.aBool', null)
|
|
|
|
expect(atom.config.get('foo.bar.aBool')).toBe(false)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('reverts back to the default value when undefined is passed to set', () => {
|
|
|
|
atom.config.set('foo.bar.aBool', 'false')
|
|
|
|
expect(atom.config.get('foo.bar.aBool')).toBe(false)
|
|
|
|
|
|
|
|
atom.config.set('foo.bar.aBool', undefined)
|
|
|
|
expect(atom.config.get('foo.bar.aBool')).toBe(true)
|
|
|
|
})
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when the value has an "string" type', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
const schema = {
|
|
|
|
type: 'string',
|
|
|
|
default: 'ok'
|
|
|
|
}
|
|
|
|
atom.config.setSchema('foo.bar.aString', schema)
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('allows strings', () => {
|
|
|
|
atom.config.set('foo.bar.aString', 'yep')
|
|
|
|
expect(atom.config.get('foo.bar.aString')).toBe('yep')
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('will only set strings', () => {
|
|
|
|
expect(atom.config.set('foo.bar.aString', 123)).toBe(false)
|
|
|
|
expect(atom.config.get('foo.bar.aString')).toBe('ok')
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.set('foo.bar.aString', true)).toBe(false)
|
|
|
|
expect(atom.config.get('foo.bar.aString')).toBe('ok')
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.set('foo.bar.aString', null)).toBe(false)
|
|
|
|
expect(atom.config.get('foo.bar.aString')).toBe('ok')
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.set('foo.bar.aString', [])).toBe(false)
|
|
|
|
expect(atom.config.get('foo.bar.aString')).toBe('ok')
|
|
|
|
|
|
|
|
expect(atom.config.set('foo.bar.aString', {nope: 'nope'})).toBe(false)
|
|
|
|
expect(atom.config.get('foo.bar.aString')).toBe('ok')
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('does not allow setting children of that key-path', () => {
|
|
|
|
expect(atom.config.set('foo.bar.aString.something', 123)).toBe(false)
|
|
|
|
expect(atom.config.get('foo.bar.aString')).toBe('ok')
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('when the schema has a "maximumLength" key', () =>
|
|
|
|
it('trims the string to be no longer than the specified maximum', () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
const schema = {
|
|
|
|
type: 'string',
|
2018-01-25 05:16:49 +03:00
|
|
|
default: 'ok',
|
|
|
|
maximumLength: 3
|
2018-01-20 03:50:37 +03:00
|
|
|
}
|
|
|
|
atom.config.setSchema('foo.bar.aString', schema)
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.set('foo.bar.aString', 'abcdefg')
|
|
|
|
expect(atom.config.get('foo.bar.aString')).toBe('abc')
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
2018-01-25 05:16:49 +03:00
|
|
|
)
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when the value has an "object" type', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
const schema = {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
anInt: {
|
|
|
|
type: 'integer',
|
|
|
|
default: 12
|
|
|
|
},
|
|
|
|
nestedObject: {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
nestedBool: {
|
|
|
|
type: 'boolean',
|
|
|
|
default: false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
atom.config.setSchema('foo.bar', schema)
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('converts and validates all the children', () => {
|
|
|
|
atom.config.set('foo.bar', {
|
|
|
|
anInt: '23',
|
|
|
|
nestedObject: {
|
|
|
|
nestedBool: 'true'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
expect(atom.config.get('foo.bar')).toEqual({
|
|
|
|
anInt: 23,
|
|
|
|
nestedObject: {
|
|
|
|
nestedBool: true
|
|
|
|
}
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
2018-01-25 05:16:49 +03:00
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('will set only the values that adhere to the schema', () => {
|
|
|
|
expect(atom.config.set('foo.bar', {
|
|
|
|
anInt: 'nope',
|
|
|
|
nestedObject: {
|
|
|
|
nestedBool: true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.anInt')).toEqual(12)
|
|
|
|
expect(atom.config.get('foo.bar.nestedObject.nestedBool')).toEqual(true)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when the value has additionalProperties set to false', () =>
|
|
|
|
it('does not allow other properties to be set on the object', () => {
|
|
|
|
atom.config.setSchema('foo.bar', {
|
2018-01-20 03:50:37 +03:00
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
anInt: {
|
|
|
|
type: 'integer',
|
|
|
|
default: 12
|
|
|
|
}
|
2018-01-25 05:16:49 +03:00
|
|
|
},
|
|
|
|
additionalProperties: false
|
2018-01-20 03:50:37 +03:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.set('foo.bar', {anInt: 5, somethingElse: 'ok'})).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.anInt')).toBe(5)
|
|
|
|
expect(atom.config.get('foo.bar.somethingElse')).toBeUndefined()
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.set('foo.bar.somethingElse', {anInt: 5})).toBe(false)
|
|
|
|
expect(atom.config.get('foo.bar.somethingElse')).toBeUndefined()
|
|
|
|
})
|
|
|
|
)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when the value has an additionalProperties schema', () =>
|
|
|
|
it('validates properties of the object against that schema', () => {
|
|
|
|
atom.config.setSchema('foo.bar', {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
anInt: {
|
|
|
|
type: 'integer',
|
|
|
|
default: 12
|
2018-01-20 03:50:37 +03:00
|
|
|
}
|
2018-01-25 05:16:49 +03:00
|
|
|
},
|
|
|
|
additionalProperties: {
|
|
|
|
type: 'string'
|
2018-01-20 03:50:37 +03:00
|
|
|
}
|
|
|
|
}
|
2018-01-25 05:16:49 +03:00
|
|
|
)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.set('foo.bar', {anInt: 5, somethingElse: 'ok'})).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.anInt')).toBe(5)
|
|
|
|
expect(atom.config.get('foo.bar.somethingElse')).toBe('ok')
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.set('foo.bar.somethingElse', 7)).toBe(false)
|
|
|
|
expect(atom.config.get('foo.bar.somethingElse')).toBe('ok')
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.set('foo.bar', {anInt: 6, somethingElse: 7})).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.anInt')).toBe(6)
|
|
|
|
expect(atom.config.get('foo.bar.somethingElse')).toBe(undefined)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
2018-01-25 05:16:49 +03:00
|
|
|
)
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when the value has an "array" type', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
const schema = {
|
|
|
|
type: 'array',
|
|
|
|
default: [1, 2, 3],
|
|
|
|
items: {
|
|
|
|
type: 'integer'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
atom.config.setSchema('foo.bar', schema)
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('converts an array of strings to an array of ints', () => {
|
|
|
|
atom.config.set('foo.bar', ['2', '3', '4'])
|
|
|
|
expect(atom.config.get('foo.bar')).toEqual([2, 3, 4])
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('does not allow setting children of that key-path', () => {
|
|
|
|
expect(atom.config.set('foo.bar.child', 123)).toBe(false)
|
|
|
|
expect(atom.config.set('foo.bar.child.grandchild', 123)).toBe(false)
|
|
|
|
expect(atom.config.get('foo.bar')).toEqual([1, 2, 3])
|
|
|
|
})
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when the value has a "color" type', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
const schema = {
|
|
|
|
type: 'color',
|
|
|
|
default: 'white'
|
|
|
|
}
|
|
|
|
atom.config.setSchema('foo.bar.aColor', schema)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('returns a Color object', () => {
|
|
|
|
let color = atom.config.get('foo.bar.aColor')
|
|
|
|
expect(color.toHexString()).toBe('#ffffff')
|
|
|
|
expect(color.toRGBAString()).toBe('rgba(255, 255, 255, 1)')
|
|
|
|
|
|
|
|
color.red = 0
|
|
|
|
color.green = 0
|
|
|
|
color.blue = 0
|
|
|
|
color.alpha = 0
|
|
|
|
atom.config.set('foo.bar.aColor', color)
|
|
|
|
|
|
|
|
color = atom.config.get('foo.bar.aColor')
|
|
|
|
expect(color.toHexString()).toBe('#000000')
|
|
|
|
expect(color.toRGBAString()).toBe('rgba(0, 0, 0, 0)')
|
|
|
|
|
|
|
|
color.red = 300
|
|
|
|
color.green = -200
|
|
|
|
color.blue = -1
|
|
|
|
color.alpha = 'not see through'
|
|
|
|
atom.config.set('foo.bar.aColor', color)
|
|
|
|
|
|
|
|
color = atom.config.get('foo.bar.aColor')
|
|
|
|
expect(color.toHexString()).toBe('#ff0000')
|
|
|
|
expect(color.toRGBAString()).toBe('rgba(255, 0, 0, 1)')
|
|
|
|
|
|
|
|
color.red = 11
|
|
|
|
color.green = 11
|
|
|
|
color.blue = 124
|
|
|
|
color.alpha = 1
|
|
|
|
atom.config.set('foo.bar.aColor', color)
|
|
|
|
|
|
|
|
color = atom.config.get('foo.bar.aColor')
|
|
|
|
expect(color.toHexString()).toBe('#0b0b7c')
|
|
|
|
expect(color.toRGBAString()).toBe('rgba(11, 11, 124, 1)')
|
|
|
|
})
|
|
|
|
|
|
|
|
it('coerces various types to a color object', () => {
|
|
|
|
atom.config.set('foo.bar.aColor', 'red')
|
|
|
|
expect(atom.config.get('foo.bar.aColor')).toEqual({red: 255, green: 0, blue: 0, alpha: 1})
|
|
|
|
atom.config.set('foo.bar.aColor', '#020')
|
|
|
|
expect(atom.config.get('foo.bar.aColor')).toEqual({red: 0, green: 34, blue: 0, alpha: 1})
|
|
|
|
atom.config.set('foo.bar.aColor', '#abcdef')
|
|
|
|
expect(atom.config.get('foo.bar.aColor')).toEqual({red: 171, green: 205, blue: 239, alpha: 1})
|
|
|
|
atom.config.set('foo.bar.aColor', 'rgb(1,2,3)')
|
|
|
|
expect(atom.config.get('foo.bar.aColor')).toEqual({red: 1, green: 2, blue: 3, alpha: 1})
|
|
|
|
atom.config.set('foo.bar.aColor', 'rgba(4,5,6,.7)')
|
|
|
|
expect(atom.config.get('foo.bar.aColor')).toEqual({red: 4, green: 5, blue: 6, alpha: 0.7})
|
|
|
|
atom.config.set('foo.bar.aColor', 'hsl(120,100%,50%)')
|
|
|
|
expect(atom.config.get('foo.bar.aColor')).toEqual({red: 0, green: 255, blue: 0, alpha: 1})
|
|
|
|
atom.config.set('foo.bar.aColor', 'hsla(120,100%,50%,0.3)')
|
|
|
|
expect(atom.config.get('foo.bar.aColor')).toEqual({red: 0, green: 255, blue: 0, alpha: 0.3})
|
|
|
|
atom.config.set('foo.bar.aColor', {red: 100, green: 255, blue: 2, alpha: 0.5})
|
|
|
|
expect(atom.config.get('foo.bar.aColor')).toEqual({red: 100, green: 255, blue: 2, alpha: 0.5})
|
|
|
|
atom.config.set('foo.bar.aColor', {red: 255})
|
|
|
|
expect(atom.config.get('foo.bar.aColor')).toEqual({red: 255, green: 0, blue: 0, alpha: 1})
|
|
|
|
atom.config.set('foo.bar.aColor', {red: 1000})
|
|
|
|
expect(atom.config.get('foo.bar.aColor')).toEqual({red: 255, green: 0, blue: 0, alpha: 1})
|
|
|
|
atom.config.set('foo.bar.aColor', {red: 'dark'})
|
|
|
|
expect(atom.config.get('foo.bar.aColor')).toEqual({red: 0, green: 0, blue: 0, alpha: 1})
|
|
|
|
})
|
|
|
|
|
|
|
|
it('reverts back to the default value when undefined is passed to set', () => {
|
|
|
|
atom.config.set('foo.bar.aColor', undefined)
|
|
|
|
expect(atom.config.get('foo.bar.aColor')).toEqual({red: 255, green: 255, blue: 255, alpha: 1})
|
|
|
|
})
|
|
|
|
|
|
|
|
it('will not set non-colors', () => {
|
|
|
|
atom.config.set('foo.bar.aColor', null)
|
|
|
|
expect(atom.config.get('foo.bar.aColor')).toEqual({red: 255, green: 255, blue: 255, alpha: 1})
|
|
|
|
|
|
|
|
atom.config.set('foo.bar.aColor', 'nope')
|
|
|
|
expect(atom.config.get('foo.bar.aColor')).toEqual({red: 255, green: 255, blue: 255, alpha: 1})
|
|
|
|
|
|
|
|
atom.config.set('foo.bar.aColor', 30)
|
|
|
|
expect(atom.config.get('foo.bar.aColor')).toEqual({red: 255, green: 255, blue: 255, alpha: 1})
|
|
|
|
|
|
|
|
atom.config.set('foo.bar.aColor', false)
|
|
|
|
expect(atom.config.get('foo.bar.aColor')).toEqual({red: 255, green: 255, blue: 255, alpha: 1})
|
|
|
|
})
|
|
|
|
|
|
|
|
it('returns a clone of the Color when returned in a parent object', () => {
|
|
|
|
const color1 = atom.config.get('foo.bar').aColor
|
|
|
|
const color2 = atom.config.get('foo.bar').aColor
|
|
|
|
expect(color1.toRGBAString()).toBe('rgba(255, 255, 255, 1)')
|
|
|
|
expect(color2.toRGBAString()).toBe('rgba(255, 255, 255, 1)')
|
|
|
|
expect(color1).not.toBe(color2)
|
|
|
|
expect(color1).toEqual(color2)
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
2018-01-25 05:16:49 +03:00
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when the `enum` key is used', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
const schema = {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
str: {
|
|
|
|
type: 'string',
|
|
|
|
default: 'ok',
|
|
|
|
enum: ['ok', 'one', 'two']
|
|
|
|
},
|
|
|
|
int: {
|
|
|
|
type: 'integer',
|
|
|
|
default: 2,
|
|
|
|
enum: [2, 3, 5]
|
|
|
|
},
|
|
|
|
arr: {
|
|
|
|
type: 'array',
|
|
|
|
default: ['one', 'two'],
|
|
|
|
items: {
|
2018-01-20 03:50:37 +03:00
|
|
|
type: 'string',
|
2018-01-25 05:16:49 +03:00
|
|
|
enum: ['one', 'two', 'three']
|
2018-01-20 03:50:37 +03:00
|
|
|
}
|
2018-01-25 05:16:49 +03:00
|
|
|
},
|
|
|
|
str_options: {
|
|
|
|
type: 'string',
|
|
|
|
default: 'one',
|
|
|
|
enum: [
|
|
|
|
{value: 'one', description: 'One'},
|
|
|
|
'two',
|
|
|
|
{value: 'three', description: 'Three'}
|
|
|
|
]
|
2018-01-20 03:50:37 +03:00
|
|
|
}
|
|
|
|
}
|
2018-01-25 05:16:49 +03:00
|
|
|
}
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.setSchema('foo.bar', schema)
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('will only set a string when the string is in the enum values', () => {
|
|
|
|
expect(atom.config.set('foo.bar.str', 'nope')).toBe(false)
|
|
|
|
expect(atom.config.get('foo.bar.str')).toBe('ok')
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.set('foo.bar.str', 'one')).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.str')).toBe('one')
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('will only set an integer when the integer is in the enum values', () => {
|
|
|
|
expect(atom.config.set('foo.bar.int', '400')).toBe(false)
|
|
|
|
expect(atom.config.get('foo.bar.int')).toBe(2)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.set('foo.bar.int', '3')).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.int')).toBe(3)
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('will only set an array when the array values are in the enum values', () => {
|
|
|
|
expect(atom.config.set('foo.bar.arr', ['one', 'five'])).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.arr')).toEqual(['one'])
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.set('foo.bar.arr', ['two', 'three'])).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.arr')).toEqual(['two', 'three'])
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
it('will honor the enum when specified as an array', () => {
|
|
|
|
expect(atom.config.set('foo.bar.str_options', 'one')).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.str_options')).toEqual('one')
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.set('foo.bar.str_options', 'two')).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.str_options')).toEqual('two')
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(atom.config.set('foo.bar.str_options', 'One')).toBe(false)
|
|
|
|
expect(atom.config.get('foo.bar.str_options')).toEqual('two')
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
describe('when .set/.unset is called prior to .resetUserSettings', () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
beforeEach(() => {
|
|
|
|
atom.config.settingsLoaded = false
|
|
|
|
})
|
|
|
|
|
2018-01-20 03:54:53 +03:00
|
|
|
it('ensures that early set and unset calls are replayed after the config is loaded from disk', () => {
|
2018-01-20 03:50:37 +03:00
|
|
|
atom.config.unset('foo.bar')
|
|
|
|
atom.config.set('foo.qux', 'boo')
|
|
|
|
|
|
|
|
expect(atom.config.get('foo.bar')).toBeUndefined()
|
|
|
|
expect(atom.config.get('foo.qux')).toBe('boo')
|
|
|
|
expect(atom.config.get('do.ray')).toBeUndefined()
|
|
|
|
|
|
|
|
advanceClock(100)
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(savedSettings.length).toBe(0)
|
2018-01-20 03:50:37 +03:00
|
|
|
|
2018-01-25 05:16:49 +03:00
|
|
|
atom.config.resetUserSettings({
|
|
|
|
'*': {
|
|
|
|
foo: {
|
|
|
|
bar: 'baz'
|
|
|
|
},
|
|
|
|
do: {
|
|
|
|
ray: 'me'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
|
|
|
|
advanceClock(100)
|
2018-01-25 05:16:49 +03:00
|
|
|
expect(savedSettings.length).toBe(1)
|
|
|
|
expect(atom.config.get('foo.bar')).toBeUndefined()
|
|
|
|
expect(atom.config.get('foo.qux')).toBe('boo')
|
|
|
|
expect(atom.config.get('do.ray')).toBe('me')
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|
|
|
|
})
|
2018-02-19 02:03:00 +03:00
|
|
|
|
|
|
|
describe('project specific configs', () => {
|
|
|
|
describe('config.resetProjectSettings', () => {
|
|
|
|
it('gracefully handles invalid config objects', () => {
|
|
|
|
atom.config.resetProjectSettings({})
|
|
|
|
expect(atom.config.get('foo.bar')).toBeUndefined()
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('config.get', () => {
|
2018-03-02 06:09:22 +03:00
|
|
|
const dummyPath = '/Users/dummy/path.json'
|
2018-02-19 02:03:00 +03:00
|
|
|
describe('project configs', () => {
|
|
|
|
it('returns a deep clone of the property value', () => {
|
2018-03-02 06:09:22 +03:00
|
|
|
atom.config.resetProjectSettings({'*': {'value': {array: [1, {b: 2}, 3]}}}, dummyPath)
|
2018-02-19 02:03:00 +03:00
|
|
|
const retrievedValue = atom.config.get('value')
|
|
|
|
retrievedValue.array[0] = 4
|
|
|
|
retrievedValue.array[1].b = 2.1
|
|
|
|
expect(atom.config.get('value')).toEqual({array: [1, {b: 2}, 3]})
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should properly get project configs', () => {
|
2018-03-02 06:09:22 +03:00
|
|
|
atom.config.resetProjectSettings({'*': {'foo': 'wei'}}, dummyPath)
|
2018-02-19 02:03:00 +03:00
|
|
|
expect(atom.config.get('foo')).toBe('wei')
|
2018-03-02 06:09:22 +03:00
|
|
|
atom.config.resetProjectSettings({'*': {'foo': {'bar': 'baz'}}}, dummyPath)
|
2018-02-19 02:03:00 +03:00
|
|
|
expect(atom.config.get('foo.bar')).toBe('baz')
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should get project settings with higher priority than regular settings', () => {
|
|
|
|
atom.config.set('foo', 'bar')
|
2018-03-02 06:09:22 +03:00
|
|
|
atom.config.resetProjectSettings({'*': {'foo': 'baz'}}, dummyPath)
|
2018-02-19 02:03:00 +03:00
|
|
|
expect(atom.config.get('foo')).toBe('baz')
|
|
|
|
})
|
|
|
|
|
|
|
|
it('correctly gets nested and scoped properties for project configs', () => {
|
|
|
|
expect(atom.config.set('foo.bar.str', 'global')).toBe(true)
|
|
|
|
expect(atom.config.set('foo.bar.str', 'scoped', {scopeSelector: '.source.js'})).toBe(true)
|
|
|
|
expect(atom.config.get('foo.bar.str')).toBe('global')
|
|
|
|
expect(atom.config.get('foo.bar.str', {scope: ['.source.js']})).toBe('scoped')
|
|
|
|
})
|
|
|
|
|
|
|
|
it('returns a deep clone of the property value', () => {
|
|
|
|
atom.config.set('value', {array: [1, {b: 2}, 3]})
|
|
|
|
const retrievedValue = atom.config.get('value')
|
|
|
|
retrievedValue.array[0] = 4
|
|
|
|
retrievedValue.array[1].b = 2.1
|
|
|
|
expect(atom.config.get('value')).toEqual({array: [1, {b: 2}, 3]})
|
|
|
|
})
|
|
|
|
|
2018-03-02 06:12:53 +03:00
|
|
|
it('gets scoped values correctly', () => {
|
|
|
|
atom.config.set('foo', 'bam', {scope: ['second']})
|
|
|
|
expect(atom.config.get('foo', {'scopeSelector': 'second'})).toBe('bam')
|
|
|
|
atom.config.resetProjectSettings({'*': {'foo': 'baz'}, 'second': {'foo': 'bar'}}, dummyPath)
|
|
|
|
expect(atom.config.get('foo', {'scopeSelector': 'second'})).toBe('baz')
|
|
|
|
atom.config.clearProjectSettings()
|
|
|
|
expect(atom.config.get('foo', {'scopeSelector': 'second'})).toBe('bam')
|
|
|
|
})
|
|
|
|
|
2018-02-19 02:03:00 +03:00
|
|
|
it('clears project settings correctly', () => {
|
|
|
|
atom.config.set('foo', 'bar')
|
|
|
|
expect(atom.config.get('foo')).toBe('bar')
|
2018-03-02 06:09:22 +03:00
|
|
|
atom.config.resetProjectSettings({'*': {'foo': 'baz'}, 'second': {'foo': 'bar'}}, dummyPath)
|
2018-02-19 02:03:00 +03:00
|
|
|
expect(atom.config.get('foo')).toBe('baz')
|
|
|
|
expect(atom.config.getSources().length).toBe(1)
|
2018-02-27 01:38:50 +03:00
|
|
|
atom.config.clearProjectSettings()
|
2018-02-19 02:03:00 +03:00
|
|
|
expect(atom.config.get('foo')).toBe('bar')
|
|
|
|
expect(atom.config.getSources().length).toBe(0)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('config.getAll', () => {
|
2018-03-02 06:09:22 +03:00
|
|
|
const dummyPath = '/Users/dummy/path.json'
|
2018-02-19 02:03:00 +03:00
|
|
|
it('should get settings in the same way .get would return them', () => {
|
2018-03-02 06:09:22 +03:00
|
|
|
atom.config.resetProjectSettings({'*': {'a': 'b'}}, dummyPath)
|
2018-02-19 02:03:00 +03:00
|
|
|
atom.config.set('a', 'f')
|
|
|
|
expect(atom.config.getAll('a')).toEqual([{
|
|
|
|
scopeSelector: '*',
|
|
|
|
value: 'b'
|
|
|
|
}])
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
2018-01-20 03:50:37 +03:00
|
|
|
})
|