UNPKG

12.8 kBtext/coffeescriptView Raw
1_ = require('lodash')
2_.str = require('underscore.string')
3chai = require('chai')
4expect = chai.expect
5parse = require('../lib/parse')
6state = require('../lib/state')
7Option = require('../lib/option')
8Signature = require('../lib/signature')
9settings = require('../lib/settings')
10
11describe 'Parse:', ->
12
13 describe '#normalizeInput()', ->
14
15 it 'should handle strings', ->
16 result = parse.normalizeInput('-x 3 -y 4')
17 expect(result).to.deep.equal([ '-x', '3', '-y', '4' ])
18
19 it 'should handle arrays', ->
20 result = parse.normalizeInput([ '-x', '3', '-y', '4' ])
21 expect(result).to.deep.equal([ '-x', '3', '-y', '4' ])
22
23 it 'should discard first arguments if process.argv', ->
24 result = parse.normalizeInput(process.argv)
25 expect(result).to.deep.equal(process.argv.slice(2))
26
27 it 'should throw an error if invalid input', ->
28 expect ->
29 parse.normalizeInput({ hello: 'world' })
30 .to.throw(Error)
31
32 describe '#parse()', ->
33
34 describe 'options', ->
35
36 beforeEach ->
37 state.globalOptions = []
38
39 it 'should be able to parse options', ->
40 argv = parse.split('-x 3 -y 4')
41 result = parse.parse(argv)
42 expect(result).to.deep.equal
43 global: {}
44 options:
45 x: 3
46 y: 4
47
48 it 'should be able to parse boolean options', ->
49 argv = parse.split('-x --foo')
50 result = parse.parse(argv)
51 expect(result).to.deep.equal
52 global: {}
53 options:
54 x: true
55 foo: true
56
57 it 'should be able to compile global options', ->
58 state.globalOptions.push new Option
59 signature: new Signature('quiet')
60 boolean: true
61
62 argv = parse.split('foo --quiet')
63 result = parse.parse(argv)
64 expect(result).to.deep.equal
65 global:
66 quiet: true
67 options:
68 quiet: true
69 command: 'foo'
70
71 it 'should be able to compile global options with aliases', ->
72 state.globalOptions.push new Option
73 signature: new Signature('quiet')
74 boolean: true
75 alias: 'q'
76
77 argv = parse.split('foo -q')
78 result = parse.parse(argv)
79 expect(result).to.deep.equal
80 global:
81 quiet: true
82 options:
83 q: true
84 command: 'foo'
85
86 describe 'commands', ->
87
88 it 'should be able to parse commands', ->
89 argv = parse.split('auth login')
90 result = parse.parse(argv)
91 expect(result).to.deep.equal
92 command: 'auth login'
93 options: {}
94 global: {}
95
96 it 'should be able to parse commands with suffix options', ->
97 argv = parse.split('auth login -f -n 10')
98 result = parse.parse(argv)
99 expect(result).to.deep.equal
100 command: 'auth login'
101 global: {}
102 options:
103 f: true
104 n: 10
105
106 it 'should be able to parse commands with prefix options', ->
107 argv = parse.split('-f -n 10 auth login')
108 result = parse.parse(argv)
109 expect(result).to.deep.equal
110 command: 'auth login'
111 global: {}
112 options:
113 f: true
114 n: 10
115
116 it 'should be able to parse commands with infix options', ->
117 argv = parse.split('auth -f -n 10 login')
118 result = parse.parse(argv)
119 expect(result).to.deep.equal
120 command: 'auth login'
121 global: {}
122 options:
123 f: true
124 n: 10
125
126 it 'should be able to parse commands with arguments', ->
127 argv = parse.split('auth login <credentials>')
128 result = parse.parse(argv)
129 expect(result).to.deep.equal
130 command: 'auth login <credentials>'
131 global: {}
132 options: {}
133
134 it 'should be able to parse commands with multiple arguments', ->
135 argv = parse.split('auth login <credentials> <foo>')
136 result = parse.parse(argv)
137 expect(result).to.deep.equal
138 command: 'auth login <credentials> <foo>'
139 global: {}
140 options: {}
141
142 it 'should be able to parse commands with optional arguments', ->
143 argv = parse.split('auth login [foo]')
144 result = parse.parse(argv)
145 expect(result).to.deep.equal
146 command: 'auth login [foo]'
147 global: {}
148 options: {}
149
150 it 'should be able to parse commands with multiple arguments', ->
151 argv = parse.split('transfer <from name> <to name>')
152 result = parse.parse(argv)
153 expect(result).to.deep.equal
154 command: 'transfer <from name> <to name>'
155 global: {}
156 options: {}
157
158 it 'should be able to parse commands with optional arguments', ->
159 argv = parse.split('greet [their name]')
160 result = parse.parse(argv)
161 expect(result).to.deep.equal
162 command: 'greet [their name]'
163 global: {}
164 options: {}
165
166 it 'should not discard single quotes when parsing the command', ->
167 argv = parse.split('hello \'John Doe\'')
168 result = parse.parse(argv)
169 expect(result).to.deep.equal
170 command: 'hello "John Doe"'
171 global: {}
172 options: {}
173
174 it 'should not discard double quotes when parsing the command', ->
175 argv = parse.split('hello "John Doe"')
176 result = parse.parse(argv)
177 expect(result).to.deep.equal
178 command: 'hello "John Doe"'
179 global: {}
180 options: {}
181
182 describe '#split()', ->
183
184 it 'should return an empty array if no signature', ->
185 signature = undefined
186 result = []
187 expect(parse.split(signature)).to.deep.equal(result)
188
189 it 'should split a wildcard signature correctly', ->
190 signature = settings.signatures.wildcard
191 result = [ settings.signatures.wildcard ]
192 expect(parse.split(signature)).to.deep.equal(result)
193
194 it 'should split signatures correctly', ->
195 signature = 'foo <bar>'
196 result = [ 'foo', '<bar>' ]
197 expect(parse.split(signature)).to.deep.equal(result)
198
199 it 'should split multi word required parameters', ->
200 signature = '<hello world> <foo bar baz>'
201 result = [ '<hello world>', '<foo bar baz>' ]
202 expect(parse.split(signature)).to.deep.equal(result)
203
204 it 'should split multi word optional parameters', ->
205 signature = '[hello world] [foo bar baz]'
206 result = [ '[hello world]', '[foo bar baz]' ]
207 expect(parse.split(signature)).to.deep.equal(result)
208
209 it 'should split multi word variadic required parameters', ->
210 signature = '<hello world...> <foo bar baz...>'
211 result = [ '<hello world...>', '<foo bar baz...>' ]
212 expect(parse.split(signature)).to.deep.equal(result)
213
214 it 'should split multi word optional parameters', ->
215 signature = '[hello world...] [foo bar baz...]'
216 result = [ '[hello world...]', '[foo bar baz...]' ]
217 expect(parse.split(signature)).to.deep.equal(result)
218
219 it 'should split absolute paths parameters correctly', ->
220 signature = 'foo /Users/me/foo/bar'
221 result = [ 'foo', '/Users/me/foo/bar' ]
222 expect(parse.split(signature)).to.deep.equal(result)
223
224 it 'should split absolute paths (win32) parameters correctly', ->
225 signature = 'foo C:\\Users\\me\\foo\\bar'
226 result = [ 'foo', 'C:\\Users\\me\\foo\\bar' ]
227 expect(parse.split(signature)).to.deep.equal(result)
228
229 it 'should split relative paths parameters correctly', ->
230 signature = 'foo ../hello/world'
231 result = [ 'foo', '../hello/world' ]
232 expect(parse.split(signature)).to.deep.equal(result)
233
234 it 'should split home relative paths parameters correctly', ->
235 signature = 'foo ~/.ssh/id_rsa.pub'
236 result = [ 'foo', '~/.ssh/id_rsa.pub' ]
237 expect(parse.split(signature)).to.deep.equal(result)
238
239 it 'should split words surrounded by quotes correctly', ->
240 signature = 'foo \'hello world\''
241 result = [ 'foo', 'hello world' ]
242 expect(parse.split(signature)).to.deep.equal(result)
243
244 it 'should split words surrounded by double quotes correctly', ->
245 signature = 'foo "hello world"'
246 result = [ 'foo', 'hello world' ]
247 expect(parse.split(signature)).to.deep.equal(result)
248
249 describe '#parseOptions()', ->
250
251 it 'should not throw if options is undefined', ->
252 definedOptions = []
253 definedOptions.push new Option
254 signature: new Signature('foo')
255 boolean: true
256
257 expect ->
258 parse.parseOptions(definedOptions, undefined)
259 .to.not.throw(Error)
260
261 it 'should return an empty object if defined options is empty', ->
262 options =
263 hello: 'world'
264 quiet: true
265 expect(parse.parseOptions([], options)).to.deep.equal({})
266
267 it 'should return an empty object if options is empty', ->
268 definedOptions = []
269 definedOptions.push new Option
270 signature: new Signature('foo')
271 parameter: 'bar'
272 expect(parse.parseOptions(definedOptions, [])).to.deep.equal({})
273
274 it 'should parse simple options (without aliases)', ->
275 definedOptions = []
276 definedOptions.push new Option
277 signature: new Signature('foo')
278 parameter: 'bar'
279
280 definedOptions.push new Option
281 signature: new Signature('quiet')
282 boolean: true
283
284 options =
285 foo: 'baz'
286 quiet: true
287
288 result = parse.parseOptions(definedOptions, options)
289 expect(result).to.deep.equal
290 foo: 'baz'
291 quiet: true
292
293 it 'should parse options starting with a number correctly', ->
294 definedOptions = []
295 definedOptions.push new Option
296 signature: new Signature('foo')
297 parameter: 'bar'
298
299 options =
300 foo: '10foobar'
301
302 result = parse.parseOptions(definedOptions, options)
303 expect(result).to.deep.equal
304 foo: '10foobar'
305
306 it 'should parse options containing integers as numbers', ->
307 definedOptions = []
308 definedOptions.push new Option
309 signature: new Signature('foo')
310 parameter: 'bar'
311
312 options =
313 foo: '10'
314
315 result = parse.parseOptions(definedOptions, options)
316 expect(result).to.deep.equal
317 foo: 10
318
319 it 'should discard non matched options', ->
320 definedOptions = []
321 definedOptions.push new Option
322 signature: new Signature('foo')
323 parameter: 'bar'
324
325 definedOptions.push new Option
326 signature: new Signature('hello')
327 parameter: 'world'
328
329 definedOptions.push new Option
330 signature: new Signature('quiet')
331 boolean: true
332
333 options =
334 foo: 'baz'
335 quiet: 'hello'
336 hello: true
337
338 result = parse.parseOptions(definedOptions, options)
339 expect(result).to.deep.equal
340 foo: 'baz'
341
342 it 'shoud omit extra defined options', ->
343 definedOptions = []
344 definedOptions.push new Option
345 signature: new Signature('foo')
346 parameter: 'bar'
347
348 definedOptions.push new Option
349 signature: new Signature('quiet')
350 boolean: true
351
352 options =
353 foo: 'baz'
354
355 result = parse.parseOptions(definedOptions, options)
356 expect(result).to.deep.equal
357 foo: 'baz'
358
359 it 'should handle string aliases', ->
360 definedOptions = []
361 definedOptions.push new Option
362 signature: new Signature('foo')
363 parameter: 'bar'
364 alias: 'f'
365
366 options =
367 f: 'baz'
368
369 result = parse.parseOptions(definedOptions, options)
370 expect(result).to.deep.equal
371 foo: 'baz'
372
373 it 'should handle array aliases', ->
374 definedOptions = []
375 definedOptions.push new Option
376 signature: new Signature('foo')
377 parameter: 'bar'
378 alias: [ 'a', 'b', 'c' ]
379
380 options =
381 b: 'baz'
382
383 result = parse.parseOptions(definedOptions, options)
384 expect(result).to.deep.equal
385 foo: 'baz'
386
387 it 'should handle multiletter aliases', ->
388 definedOptions = []
389 definedOptions.push new Option
390 signature: new Signature('foo')
391 parameter: 'bar'
392 alias: 'hello'
393
394 options =
395 hello: 'world'
396
397 result = parse.parseOptions(definedOptions, options)
398 expect(result).to.deep.equal
399 foo: 'world'
400
401 it 'should give precedence to long names', ->
402 definedOptions = []
403 definedOptions.push new Option
404 signature: new Signature('foo')
405 parameter: 'bar'
406 alias: [ 'a', 'b', 'c' ]
407
408 options =
409 foo: 'bar'
410 b: 'baz'
411
412 result = parse.parseOptions(definedOptions, options)
413 expect(result).to.deep.equal
414 foo: 'bar'
415
416 it 'should parse numbers automatically', ->
417 definedOptions = []
418 definedOptions.push new Option
419 signature: new Signature('foo')
420 parameter: 'bar'
421
422 options =
423 foo: '25'
424
425 result = parse.parseOptions(definedOptions, options)
426 expect(result).to.deep.equal
427 foo: 25
428
429 describe 'given an option required key', ->
430
431 it 'should throw a generic error if true', ->
432 definedOptions = []
433 definedOptions.push new Option
434 signature: new Signature('foo')
435 parameter: 'bar'
436 required: true
437
438 options =
439 hello: 'world'
440
441 expect ->
442 parse.parseOptions(definedOptions, options)
443 .to.throw('Option foo is required')
444
445 it 'should not throw if false', ->
446 definedOptions = []
447 definedOptions.push new Option
448 signature: new Signature('foo')
449 parameter: 'bar'
450 required: false
451
452 options =
453 hello: 'world'
454
455 expect ->
456 parse.parseOptions(definedOptions, options)
457 .to.not.throw('Option foo is required')
458
459 it 'should throw a custom error if required is a string', ->
460 definedOptions = []
461 definedOptions.push new Option
462 signature: new Signature('foo')
463 parameter: 'bar'
464 required: 'Custom error!'
465
466 options =
467 hello: 'world'
468
469 expect ->
470 parse.parseOptions(definedOptions, options)
471 .to.throw('Custom error!')