mirror of
https://github.com/balena-io/balena-cli.git
synced 2024-12-18 21:27:51 +00:00
Implement Yargs Command plugin
This commit is contained in:
parent
f1a76db5f5
commit
7610fe87cc
48
lib/yargs-command/yargs-command.coffee
Normal file
48
lib/yargs-command/yargs-command.coffee
Normal file
@ -0,0 +1,48 @@
|
||||
yargs = require('yargs')
|
||||
_ = require('lodash')
|
||||
|
||||
commandIndexBySignature = (command) ->
|
||||
query = { signature: command.signature }
|
||||
return _.findIndex(@command._commands, query)
|
||||
|
||||
isArgVariable = (word) ->
|
||||
return /^(<.*>|\[.*\])$/.test(word)
|
||||
|
||||
splitSignature = (signature) ->
|
||||
return signature.split(' ')
|
||||
|
||||
commandApplies = (command, args) ->
|
||||
args._ ?= {}
|
||||
splittedCommandSignature = splitSignature(command.signature)
|
||||
if splittedCommandSignature.length isnt args._.length
|
||||
return false
|
||||
|
||||
for word in splittedCommandSignature
|
||||
index = splittedCommandSignature.indexOf(word)
|
||||
|
||||
if not isArgVariable(word) and word isnt args._[index]
|
||||
return false
|
||||
|
||||
return true
|
||||
|
||||
run = ->
|
||||
signature = splitSignature(@command._matchedCommand.signature)
|
||||
parameters = _.difference(@argv._, signature)
|
||||
@command._matchedCommand.action.apply(this, parameters)
|
||||
|
||||
module.exports = (signature, action) ->
|
||||
command = { signature, action }
|
||||
|
||||
@command._commands ?= []
|
||||
@command.run ?= _.bind(run, this)
|
||||
|
||||
commandIndex = commandIndexBySignature.call(this, command)
|
||||
if commandIndex is -1
|
||||
@command._commands.push(command)
|
||||
else
|
||||
@command._commands.splice(commandIndex, 1, command)
|
||||
|
||||
if commandApplies(command, @argv)
|
||||
@command._matchedCommand = command
|
||||
|
||||
return this
|
110
lib/yargs-command/yargs-command.spec.coffee
Normal file
110
lib/yargs-command/yargs-command.spec.coffee
Normal file
@ -0,0 +1,110 @@
|
||||
chai = require('chai')
|
||||
sinon = require('sinon')
|
||||
chai.use(require('chai-things'))
|
||||
chai.use(require('sinon-chai'))
|
||||
expect = chai.expect
|
||||
|
||||
_ = require('lodash')
|
||||
yargs = require('yargs')
|
||||
yargs.command = require('./yargs-command')
|
||||
|
||||
COMMANDS =
|
||||
appList:
|
||||
signature: 'app list <id>'
|
||||
action: (id) -> "App List: #{id}"
|
||||
action2: (id) -> "App List: #{id}!"
|
||||
deviceList:
|
||||
signature: 'device list <id>'
|
||||
action: (id) -> "Device: #{id}"
|
||||
|
||||
ARGS =
|
||||
appList:
|
||||
_: [ 'app', 'list', '7' ]
|
||||
deviceList:
|
||||
_: [ 'device', 'list', '7' ]
|
||||
noMatch:
|
||||
_: [ 'foo', 'bar', 'baz' ]
|
||||
|
||||
# Hacky way to check that both functions are equal based
|
||||
# on what they returns, as mocha crashes when trying equal
|
||||
# or deep equal directly on the functions for some reason
|
||||
areFunctionsEqual = (fn1, fn2) ->
|
||||
return fn1.toString() is fn2.toString()
|
||||
|
||||
describe 'Yargs Command:', ->
|
||||
|
||||
cleanUpYargs = ->
|
||||
yargs.command._commands = [] if yargs.command._commands
|
||||
yargs.argv = {}
|
||||
delete yargs.command._matchedCommand
|
||||
|
||||
beforeEach ->
|
||||
cleanUpYargs()
|
||||
|
||||
afterEach ->
|
||||
cleanUpYargs()
|
||||
|
||||
it 'should expose a public command function', ->
|
||||
expect(yargs.command).to.be.an.instanceof(Function)
|
||||
|
||||
it 'should return yargs to enable chaining', ->
|
||||
result = yargs.command(COMMANDS.appList.signature, COMMANDS.appList.action)
|
||||
expect(result).to.equal(yargs)
|
||||
|
||||
it 'should contain an empty _commands array', ->
|
||||
expect(yargs.command._commands).to.deep.equal([])
|
||||
|
||||
it 'should push a command to _commands', ->
|
||||
yargs.command(COMMANDS.appList.signature, COMMANDS.appList.action)
|
||||
expect(yargs.command._commands).to.contain.something.that.deep.equals
|
||||
signature: COMMANDS.appList.signature
|
||||
action: COMMANDS.appList.action
|
||||
|
||||
describe 'if adding the same command signature twice', ->
|
||||
|
||||
beforeEach ->
|
||||
yargs.command(COMMANDS.appList.signature, COMMANDS.appList.action)
|
||||
yargs.command(COMMANDS.appList.signature, COMMANDS.appList.action2)
|
||||
|
||||
it 'should contain only one command', ->
|
||||
expect(yargs.command._commands).to.have.length(1)
|
||||
|
||||
it 'should make the last action override the first one', ->
|
||||
firstCommandAction = yargs.command._commands[0].action
|
||||
expect(areFunctionsEqual(firstCommandAction, COMMANDS.appList.action2)).to.be.true
|
||||
|
||||
describe 'given various registered commands', ->
|
||||
|
||||
registerCommands = ->
|
||||
yargs.command(COMMANDS.appList.signature, COMMANDS.appList.action)
|
||||
yargs.command(COMMANDS.deviceList.signature, COMMANDS.deviceList.action)
|
||||
|
||||
testCommand = (name) ->
|
||||
yargs.argv = ARGS[name]
|
||||
registerCommands()
|
||||
matchedCommand = yargs.command._matchedCommand
|
||||
expect(matchedCommand.signature).to.equal(COMMANDS[name].signature)
|
||||
|
||||
it 'should choose the right command', ->
|
||||
for command in [
|
||||
'appList'
|
||||
'deviceList'
|
||||
]
|
||||
testCommand(command)
|
||||
|
||||
it 'should be undefined if no match', ->
|
||||
yargs.argv = ARGS.noMatch
|
||||
registerCommands()
|
||||
expect(yargs.command._matchedCommand).to.not.exist
|
||||
|
||||
it 'should have a run public function', ->
|
||||
expect(yargs.command.run).to.be.an.instanceof(Function)
|
||||
|
||||
describe '#run()', ->
|
||||
|
||||
it 'should call the action with the correct parameters', ->
|
||||
yargs.argv = ARGS.appList
|
||||
callback = sinon.spy()
|
||||
yargs.command(COMMANDS.appList.signature, callback)
|
||||
yargs.command.run()
|
||||
expect(callback).to.have.been.calledWith(_.last(ARGS.appList._))
|
@ -23,7 +23,10 @@
|
||||
"gulp-coffeelint": "~0.4.0",
|
||||
"nock": "~0.48.2",
|
||||
"mock-fs": "~2.3.2",
|
||||
"chai-as-promised": "~4.1.1"
|
||||
"chai-as-promised": "~4.1.1",
|
||||
"chai-things": "~0.2.0",
|
||||
"sinon": "~1.12.1",
|
||||
"sinon-chai": "~2.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"request": "~2.47.0",
|
||||
@ -37,6 +40,7 @@
|
||||
"open": "0.0.5",
|
||||
"inquirer": "~0.8.0",
|
||||
"cliff": "~0.1.9",
|
||||
"underscore.string": "~2.4.0"
|
||||
"underscore.string": "~2.4.0",
|
||||
"yargs": "~1.3.3"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user