balena-cli/lib/cli-conf/cli-conf.spec.coffee
2014-12-05 11:09:31 -04:00

320 lines
8.0 KiB
CoffeeScript

_ = require('lodash')
path = require('path')
sinon = require('sinon')
chai = require('chai')
expect = chai.expect
CliConf = require('./cli-conf')
mock = require('../../tests/utils/mock')
describe 'CliConf:', ->
describe 'given an empty conf', ->
beforeEach ->
@conf = new CliConf()
describe '#set()', ->
it 'should be able to set values', ->
key = 'foo'
value = 'bar'
expect(@conf.get(key)).to.not.exist
@conf.set(key, value)
expect(@conf.get(key)).to.exist
describe '#get()', ->
it 'should be able to get values', ->
key = 'foo'
value = 'bar'
@conf.set(key, value)
expect(@conf.get(key)).to.equal(value)
it 'should be able to get nested values', ->
@conf._data.nested =
value: 'ok'
expect(@conf.get('nested.value')).to.equal('ok')
it 'should return undefined if not nested value', ->
expect(@conf.get('unexistent.nested.value')).to.be.undefined
it 'should return undefined if value does not exist', ->
expect(@conf.get('unknownKey')).to.be.undefined
it 'should return undefined if no key', ->
expect(@conf.get()).to.be.undefined
describe '#has()', ->
it 'should return check if data has key', ->
key = 'foo'
value = 'bar'
expect(@conf.has(key)).to.be.false
@conf.set(key, value)
expect(@conf.has(key)).to.be.true
describe '#extendWithFile()', ->
filesystem =
userConfig:
name: '/userConfig'
contents: JSON.stringify
remoteUrl: 'https://alpha.resin.io'
notJSONUserConfig:
name: '/notJSONUserConfig'
contents: 'Just a plain file'
beforeEach ->
mock.fs.init(filesystem)
afterEach ->
mock.fs.restore()
describe 'if no file is passed', ->
it 'should return undefined', ->
expect(@conf.extendWithFile()).to.be.undefined
it 'should keep the content unmodified', ->
data = _.cloneDeep(@conf._data)
@conf.extendWithFile()
expect(@conf._data).to.deep.equal(data)
describe 'if file does not exist', ->
it 'should return undefined', ->
expect(@conf.extendWithFile('/unexistent_file')).to.be.undefined
it 'should keep the content unmodified', ->
data = _.cloneDeep(@conf._data)
@conf.extendWithFile('/unexistent_file')
expect(@conf._data).to.deep.equal(data)
it 'should throw an error if file is not a json file', ->
func = _.partial(@conf.extendWithFile, filesystem.notJSONUserConfig.name)
expect(func).to.throw(Error)
it 'should extend data with a file', ->
expect(@conf.isEmpty()).to.be.true
@conf.extendWithFile(filesystem.userConfig.name)
expectedContent = JSON.parse(filesystem.userConfig.contents)
expect(@conf._data).to.deep.equal(expectedContent)
describe '#isEmpty()', ->
it 'should return true', ->
expect(@conf.isEmpty()).to.be.true
describe 'given a conf with default values', ->
object =
one: 'first'
two: 'second'
beforeEach ->
@conf = new CliConf(default: object)
it 'should have the data', ->
expect(@conf._data).to.deep.equal(object)
describe '#isEmpty()', ->
it 'should return false', ->
expect(@conf.isEmpty()).to.be.false
describe '#extend()', ->
beforeEach ->
@conf = new CliConf
default:
greeting: 'Hi'
it 'should override data values', ->
object =
greeting: 'Hola'
name: 'John Doe'
@conf.extend(object)
expect(@conf._data).to.deep.equal(object)
it 'should handle multiple overrides', ->
@conf.extend {
greeting: 'Hola'
name: 'John Doe'
}, {
greeting: 'Pronto'
}
expect(@conf._data).to.deep.equal
greeting: 'Pronto'
name: 'John Doe'
describe 'given a supplied user config default', ->
options =
keys:
userConfig: 'config.user'
default:
remoteUrl: 'https://staging.resin.io'
config:
user: '/Users/jviotti/.resin/config'
filesystem =
userConfig:
name: options.default.config.user
contents: JSON.stringify
remoteUrl: 'https://alpha.resin.io'
beforeEach ->
mock.fs.init(filesystem)
@conf = new CliConf(options)
afterEach ->
mock.fs.restore()
it 'should load that file and extend _data', ->
parsedUserConfig = JSON.parse(filesystem.userConfig.contents)
expectedResult = _.extend(_.cloneDeep(options.default), parsedUserConfig)
expect(@conf._data).to.deep.equal(expectedResult)
describe 'given a supplied user and local config', ->
options =
keys:
userConfig: 'config.user'
localConfig: 'config.local'
default:
remoteUrl: 'https://staging.resin.io'
config:
user: '/Users/jviotti/.resin/config'
local: '.resinconfig'
filesystem =
localConfig:
name: path.join(process.cwd(), options.default.config.local)
contents: JSON.stringify
remoteUrl: 'https://localhost.resin.io'
userConfig:
name: options.default.config.user
contents: JSON.stringify
remoteUrl: 'https://alpha.resin.io'
beforeEach ->
mock.fs.init(filesystem)
@conf = new CliConf(options)
afterEach ->
mock.fs.restore()
it 'local config should have precedence', ->
parsedUserConfig = JSON.parse(filesystem.userConfig.contents)
parsedLocalConfig = JSON.parse(filesystem.localConfig.contents)
defaultsCopy = _.cloneDeep(options.default)
expectedResult = _.extend(defaultsCopy, parsedUserConfig, parsedLocalConfig)
expect(@conf._data).to.deep.equal(expectedResult)
describe 'given supplied keys', ->
keys =
userConfig: 'config.user'
localConfig: 'config.local'
beforeEach ->
@conf = new CliConf({ keys })
describe '#_getOptionKey()', ->
it 'should be able to get a key', ->
result = @conf._getOptionKey('userConfig')
expect(result).to.equal(keys.userConfig)
it 'should return undefined if no input', ->
result = @conf._getOptionKey()
expect(result).to.be.undefined
it 'should return undefined if key does not exist', ->
result = @conf._getOptionKey('nonexistentkey')
expect(result).to.be.undefined
describe 'given a user config that changes the local config file name', ->
options =
keys:
userConfig: 'config.user'
localConfig: 'config.local'
default:
remoteUrl: 'https://staging.resin.io'
config:
user: '/Users/jviotti/.resin/config'
local: '.resinconfig'
newLocalConfig = '.resinrc'
filesystem =
userConfig:
name: options.default.config.user
contents: JSON.stringify
config:
local: newLocalConfig
localConfig:
name: path.join(process.cwd(), newLocalConfig)
contents: JSON.stringify
remoteUrl: 'https://alpha.resin.io'
beforeEach ->
mock.fs.init(filesystem)
@conf = new CliConf(options)
afterEach ->
mock.fs.restore()
it 'should make use of the renamed config file name', ->
parsedUserConfig = JSON.parse(filesystem.userConfig.contents)
parsedLocalConfig = JSON.parse(filesystem.localConfig.contents)
defaultsCopy = _.cloneDeep(options.default)
expect(@conf._getLocalConfigPath()).to.equal(filesystem.localConfig.name)
expectedResult = _.extend(defaultsCopy, parsedUserConfig, parsedLocalConfig)
expect(@conf._data).to.deep.equal(expectedResult)
describe '#parse()', ->
beforeEach ->
@conf = new CliConf()
it 'should use parse JSON by default', ->
input = '{ "hello": 123 }'
result = @conf.parse(input)
parsedInput = JSON.parse(input)
expect(result).to.deep.equal(parsedInput)
it 'should be able to replace parse function with options', ->
parseFunction = _.identity
@conf = new CliConf(configFileParse: parseFunction)
expect(@conf._options.configFileParse).to.equal(parseFunction)
input = 'Hello'
result = @conf.parse(input)
expect(result).to.equal(input)
describe '#_getLocalConfigPath()', ->
it 'should contruct the path correctly', ->
filename = 'resin'
@conf = new CliConf
keys:
localConfig: 'config.local'
default:
config:
local: filename
expectedPath = path.join(process.cwd(), filename)
expect(@conf._getLocalConfigPath()).to.equal(expectedPath)
it 'should return undefined if no local path', ->
@conf = new CliConf()
expect(@conf._getLocalConfigPath()).to.be.undefined