ggem 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +153 -9
- data/bin/ggem +1 -1
- data/ggem.gemspec +6 -3
- data/lib/ggem/cli.rb +40 -83
- data/lib/ggem/cli/clirb.rb +59 -0
- data/lib/ggem/cli/commands.rb +402 -0
- data/lib/ggem/gem.rb +9 -3
- data/lib/ggem/gemspec.rb +85 -0
- data/lib/ggem/git_repo.rb +60 -0
- data/lib/ggem/template.rb +2 -8
- data/lib/ggem/template_file/Gemfile.erb +1 -2
- data/lib/ggem/template_file/gemspec.erb +5 -5
- data/lib/ggem/version.rb +1 -1
- data/test/helper.rb +5 -44
- data/test/support/cmd_tests_helpers.rb +53 -0
- data/test/support/gem1/gem1.gemspec +16 -0
- data/test/support/gem2/gem2.gemspec +18 -0
- data/test/support/name_set.rb +0 -1
- data/test/system/ggem_tests.rb +45 -17
- data/test/unit/cli_tests.rb +1012 -0
- data/test/unit/gem_tests.rb +21 -4
- data/test/unit/gemspec_tests.rb +154 -0
- data/test/unit/git_repo_tests.rb +162 -0
- metadata +50 -33
- data/lib/ggem/template_file/Rakefile.erb +0 -1
@@ -0,0 +1,1012 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'ggem/cli'
|
3
|
+
|
4
|
+
require 'ggem/cli/clirb'
|
5
|
+
require 'ggem/cli/commands'
|
6
|
+
require 'ggem/gem'
|
7
|
+
require 'ggem/gemspec'
|
8
|
+
require 'ggem/git_repo'
|
9
|
+
require 'much-plugin'
|
10
|
+
|
11
|
+
class GGem::CLI
|
12
|
+
|
13
|
+
class UnitTests < Assert::Context
|
14
|
+
desc "GGem::CLI"
|
15
|
+
setup do
|
16
|
+
@cli_class = GGem::CLI
|
17
|
+
end
|
18
|
+
subject{ @cli_class }
|
19
|
+
|
20
|
+
should have_imeths :run
|
21
|
+
|
22
|
+
should "build and run an instance of itself using `run`" do
|
23
|
+
cli_spy = CLISpy.new
|
24
|
+
Assert.stub(subject, :new).with{ cli_spy }
|
25
|
+
|
26
|
+
args = [Factory.string]
|
27
|
+
subject.run(args)
|
28
|
+
assert_equal args, cli_spy.run_called_with
|
29
|
+
end
|
30
|
+
|
31
|
+
should "know its commands" do
|
32
|
+
assert_equal 6, COMMANDS.size
|
33
|
+
|
34
|
+
assert_instance_of InvalidCommand, COMMANDS[Factory.string]
|
35
|
+
|
36
|
+
assert_instance_of GenerateCommand, COMMANDS['generate']
|
37
|
+
assert_instance_of BuildCommand, COMMANDS['build']
|
38
|
+
assert_instance_of InstallCommand, COMMANDS['install']
|
39
|
+
assert_instance_of PushCommand, COMMANDS['push']
|
40
|
+
assert_instance_of TagCommand, COMMANDS['tag']
|
41
|
+
assert_instance_of ReleaseCommand, COMMANDS['release']
|
42
|
+
|
43
|
+
assert_same COMMANDS['generate'], COMMANDS['g']
|
44
|
+
assert_same COMMANDS['build'], COMMANDS['b']
|
45
|
+
assert_same COMMANDS['install'], COMMANDS['i']
|
46
|
+
assert_same COMMANDS['push'], COMMANDS['p']
|
47
|
+
assert_same COMMANDS['tag'], COMMANDS['t']
|
48
|
+
assert_same COMMANDS['release'], COMMANDS['r']
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
class InitTests < UnitTests
|
54
|
+
desc "when init"
|
55
|
+
setup do
|
56
|
+
@kernel_spy = KernelSpy.new
|
57
|
+
@stdout = IOSpy.new
|
58
|
+
@stderr = IOSpy.new
|
59
|
+
|
60
|
+
@cli = @cli_class.new(@kernel_spy, @stdout, @stderr)
|
61
|
+
end
|
62
|
+
subject{ @cli }
|
63
|
+
|
64
|
+
should have_imeths :run
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
class RunSetupTests < InitTests
|
69
|
+
setup do
|
70
|
+
@command_name = Factory.string
|
71
|
+
@argv = [@command_name, Factory.string]
|
72
|
+
|
73
|
+
@command_class = Class.new
|
74
|
+
@command_spy = CommandSpy.new
|
75
|
+
Assert.stub(@command_class, :new){ @command_spy }
|
76
|
+
COMMANDS.add(@command_class, @command_name)
|
77
|
+
|
78
|
+
@invalid_command = InvalidCommand.new(@command_name)
|
79
|
+
end
|
80
|
+
teardown do
|
81
|
+
COMMANDS.remove(@command_name)
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
class RunTests < RunSetupTests
|
87
|
+
desc "and run"
|
88
|
+
setup do
|
89
|
+
@cli.run(@argv)
|
90
|
+
end
|
91
|
+
|
92
|
+
should "have run the command" do
|
93
|
+
assert_true @command_spy.run_called
|
94
|
+
end
|
95
|
+
|
96
|
+
should "have successfully exited" do
|
97
|
+
assert_equal 0, @kernel_spy.exit_status
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
class RunWithNoArgsTests < RunSetupTests
|
103
|
+
desc "and run with no args"
|
104
|
+
setup do
|
105
|
+
@cli.run([])
|
106
|
+
end
|
107
|
+
|
108
|
+
should "output the invalid command's help" do
|
109
|
+
assert_equal @invalid_command.help, @stdout.read
|
110
|
+
assert_empty @stderr.read
|
111
|
+
end
|
112
|
+
|
113
|
+
should "have successfully exited" do
|
114
|
+
assert_equal 0, @kernel_spy.exit_status
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
class RunWithInvalidCommandTests < RunSetupTests
|
120
|
+
desc "and run with an invalid command"
|
121
|
+
setup do
|
122
|
+
@name = Factory.string
|
123
|
+
@argv.unshift(@name)
|
124
|
+
@cli.run(@argv)
|
125
|
+
end
|
126
|
+
|
127
|
+
should "output that it is invalid and output the invalid command's help" do
|
128
|
+
exp = "'#{@name}' is not a command.\n\n"
|
129
|
+
assert_equal exp, @stderr.read
|
130
|
+
assert_equal @invalid_command.help, @stdout.read
|
131
|
+
end
|
132
|
+
|
133
|
+
should "have unsuccessfully exited" do
|
134
|
+
assert_equal 1, @kernel_spy.exit_status
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
class RunWithCommandExitErrorTests < RunSetupTests
|
140
|
+
desc "and run with a command that error exits"
|
141
|
+
setup do
|
142
|
+
Assert.stub(@command_spy, :run){ raise CommandExitError }
|
143
|
+
@cli.run(@argv)
|
144
|
+
end
|
145
|
+
|
146
|
+
should "have unsuccessfully exited with no stderr output" do
|
147
|
+
assert_equal 1, @kernel_spy.exit_status
|
148
|
+
assert_empty @stderr.read
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
class RunWithHelpTests < RunSetupTests
|
154
|
+
desc "and run with the help switch"
|
155
|
+
setup do
|
156
|
+
@cli.run([ '--help' ])
|
157
|
+
end
|
158
|
+
|
159
|
+
should "output the invalid command's help" do
|
160
|
+
assert_equal @invalid_command.help, @stdout.read
|
161
|
+
assert_empty @stderr.read
|
162
|
+
end
|
163
|
+
|
164
|
+
should "have successfully exited" do
|
165
|
+
assert_equal 0, @kernel_spy.exit_status
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
class RunWithVersionTests < RunSetupTests
|
171
|
+
desc "and run with the version switch"
|
172
|
+
setup do
|
173
|
+
@cli.run([ '--version' ])
|
174
|
+
end
|
175
|
+
|
176
|
+
should "have output its version" do
|
177
|
+
assert_equal "#{GGem::VERSION}\n", @stdout.read
|
178
|
+
assert_empty @stderr.read
|
179
|
+
end
|
180
|
+
|
181
|
+
should "have successfully exited" do
|
182
|
+
assert_equal 0, @kernel_spy.exit_status
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
class RunWithErrorTests < RunSetupTests
|
188
|
+
setup do
|
189
|
+
@exception = RuntimeError.new(Factory.string)
|
190
|
+
Assert.stub(@command_spy, :run){ raise @exception }
|
191
|
+
@cli.run(@argv)
|
192
|
+
end
|
193
|
+
|
194
|
+
should "have output an error message" do
|
195
|
+
exp = "#{@exception.class}: #{@exception.message}\n" \
|
196
|
+
"#{@exception.backtrace.join("\n")}\n"
|
197
|
+
assert_equal exp, @stderr.read
|
198
|
+
assert_empty @stdout.read
|
199
|
+
end
|
200
|
+
|
201
|
+
should "have unsuccessfully exited" do
|
202
|
+
assert_equal 1, @kernel_spy.exit_status
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
class InvalidCommandTests < UnitTests
|
208
|
+
desc "InvalidCommand"
|
209
|
+
setup do
|
210
|
+
@name = Factory.string
|
211
|
+
@command_class = InvalidCommand
|
212
|
+
@cmd = @command_class.new(@name)
|
213
|
+
end
|
214
|
+
subject{ @cmd }
|
215
|
+
|
216
|
+
should have_readers :name, :clirb
|
217
|
+
should have_imeths :new, :run, :help
|
218
|
+
|
219
|
+
should "know its attrs" do
|
220
|
+
assert_equal @name, subject.name
|
221
|
+
assert_instance_of CLIRB, subject.clirb
|
222
|
+
end
|
223
|
+
|
224
|
+
should "set its argv and return itself using `new`" do
|
225
|
+
assert_same subject, subject.new
|
226
|
+
end
|
227
|
+
|
228
|
+
should "parse its argv on run" do
|
229
|
+
assert_raises(CLIRB::HelpExit){ subject.new.run([ '--help' ]) }
|
230
|
+
assert_raises(CLIRB::VersionExit){ subject.new.run([ '--version' ]) }
|
231
|
+
end
|
232
|
+
|
233
|
+
should "raise a help exit if its name is empty" do
|
234
|
+
cmd = @command_class.new([nil, ''].choice)
|
235
|
+
argv = [Factory.string, Factory.string]
|
236
|
+
assert_raises(CLIRB::HelpExit){ cmd.new.run(argv) }
|
237
|
+
end
|
238
|
+
|
239
|
+
should "raise an invalid command error when run" do
|
240
|
+
assert_raises(InvalidCommandError){ subject.new.run([Factory.string]) }
|
241
|
+
end
|
242
|
+
|
243
|
+
should "know its help" do
|
244
|
+
exp = "Usage: ggem [COMMAND] [options]\n\n" \
|
245
|
+
"Options: #{subject.clirb}\n" \
|
246
|
+
"Commands:\n" \
|
247
|
+
"#{COMMANDS.to_s.split("\n").map{ |l| " #{l}" }.join("\n")}\n"
|
248
|
+
assert_equal exp, subject.help
|
249
|
+
end
|
250
|
+
|
251
|
+
end
|
252
|
+
|
253
|
+
class IOCommandTests < UnitTests
|
254
|
+
setup do
|
255
|
+
@stdout, @stderr = IOSpy.new, IOSpy.new
|
256
|
+
end
|
257
|
+
subject{ @cmd }
|
258
|
+
|
259
|
+
end
|
260
|
+
|
261
|
+
class ValidCommandTests < IOCommandTests
|
262
|
+
desc "ValidCommand"
|
263
|
+
setup do
|
264
|
+
@command_class = Class.new{ include ValidCommand }
|
265
|
+
@cmd = @command_class.new
|
266
|
+
end
|
267
|
+
|
268
|
+
should have_imeths :clirb, :run, :summary
|
269
|
+
|
270
|
+
should "know its CLI.RB" do
|
271
|
+
assert_instance_of CLIRB, subject.clirb
|
272
|
+
end
|
273
|
+
|
274
|
+
should "parse its args when run" do
|
275
|
+
argv = Factory.integer(3).times.map{ Factory.string }
|
276
|
+
subject.run(argv, @stdout, @stderr)
|
277
|
+
assert_equal argv, subject.clirb.args
|
278
|
+
end
|
279
|
+
|
280
|
+
should "default its summary" do
|
281
|
+
assert_equal '', subject.summary
|
282
|
+
end
|
283
|
+
|
284
|
+
end
|
285
|
+
|
286
|
+
class GitRepoCommandTests < IOCommandTests
|
287
|
+
desc "GitRepoCommand"
|
288
|
+
setup do
|
289
|
+
@gem1_root_path = TEST_SUPPORT_PATH.join('gem1')
|
290
|
+
Assert.stub(Dir, :pwd){ @gem1_root_path}
|
291
|
+
|
292
|
+
@command_class = Class.new{ include GitRepoCommand }
|
293
|
+
@cmd = @command_class.new
|
294
|
+
end
|
295
|
+
|
296
|
+
should "be a valid, notify cmd command" do
|
297
|
+
assert_kind_of ValidCommand, subject
|
298
|
+
assert_kind_of NotifyCmdCommand, subject
|
299
|
+
end
|
300
|
+
|
301
|
+
should "build a new git repo at the current pwd root" do
|
302
|
+
gitrepo_new_called_with = nil
|
303
|
+
Assert.stub(GGem::GitRepo, :new){ |*args| gitrepo_new_called_with = args }
|
304
|
+
|
305
|
+
@command_class.new
|
306
|
+
assert_equal [Dir.pwd], gitrepo_new_called_with
|
307
|
+
end
|
308
|
+
|
309
|
+
end
|
310
|
+
|
311
|
+
module RootPathTests
|
312
|
+
include MuchPlugin
|
313
|
+
|
314
|
+
plugin_included do
|
315
|
+
setup do
|
316
|
+
@root_path = Factory.path
|
317
|
+
Assert.stub(Dir, :pwd){ @root_path }
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
end
|
322
|
+
|
323
|
+
module GitRepoSpyTests
|
324
|
+
include MuchPlugin
|
325
|
+
|
326
|
+
plugin_included do
|
327
|
+
include RootPathTests
|
328
|
+
|
329
|
+
setup do
|
330
|
+
@repo_spy = nil
|
331
|
+
Assert.stub(GGem::GitRepo, :new){ |*args| @repo_spy = GitRepoSpy.new(*args) }
|
332
|
+
end
|
333
|
+
|
334
|
+
end
|
335
|
+
|
336
|
+
end
|
337
|
+
|
338
|
+
class GenerateCommandTests < IOCommandTests
|
339
|
+
include GitRepoSpyTests
|
340
|
+
|
341
|
+
desc "GenerateCommand"
|
342
|
+
setup do
|
343
|
+
@name = Factory.string
|
344
|
+
|
345
|
+
@path = Factory.dir_path
|
346
|
+
Assert.stub(Dir, :pwd){ @path }
|
347
|
+
|
348
|
+
@gem_new_called_with = []
|
349
|
+
@gem_spy = GemSpy.new
|
350
|
+
@gem_class = GGem::Gem
|
351
|
+
Assert.stub(@gem_class, :new) do |*args|
|
352
|
+
@gem_new_called_with = args
|
353
|
+
@gem_spy
|
354
|
+
end
|
355
|
+
|
356
|
+
@command_class = GenerateCommand
|
357
|
+
@cmd = @command_class.new
|
358
|
+
end
|
359
|
+
|
360
|
+
should "be a valid command" do
|
361
|
+
assert_kind_of ValidCommand, subject
|
362
|
+
end
|
363
|
+
|
364
|
+
should "know its summary" do
|
365
|
+
exp = "Create a gem given a GEM-NAME"
|
366
|
+
assert_equal exp, subject.summary
|
367
|
+
end
|
368
|
+
|
369
|
+
should "know its help" do
|
370
|
+
exp = "Usage: ggem generate [options] GEM-NAME\n\n" \
|
371
|
+
"Options: #{subject.clirb}\n" \
|
372
|
+
"Description:\n" \
|
373
|
+
" #{subject.summary}"
|
374
|
+
assert_equal exp, subject.help
|
375
|
+
end
|
376
|
+
|
377
|
+
should "save a gem and initialize a git repo for it when run" do
|
378
|
+
subject.run([@name], @stdout, @stderr)
|
379
|
+
|
380
|
+
assert_equal [@path, @name], @gem_new_called_with
|
381
|
+
assert_true @gem_spy.save_called
|
382
|
+
|
383
|
+
assert_equal @gem_spy.path, @repo_spy.path
|
384
|
+
assert_true @repo_spy.run_init_cmd_called
|
385
|
+
|
386
|
+
exp = "created gem in #{@gem_spy.path}\n" \
|
387
|
+
"initialized gem git repo\n"
|
388
|
+
assert_equal exp, @stdout.read
|
389
|
+
end
|
390
|
+
|
391
|
+
should "re-raise a specific argument error on gem 'no name' errors" do
|
392
|
+
Assert.stub(@gem_class, :new){ raise GGem::Gem::NoNameError }
|
393
|
+
err = nil
|
394
|
+
begin
|
395
|
+
cmd = @command_class.new
|
396
|
+
cmd.run([])
|
397
|
+
rescue ArgumentError => err
|
398
|
+
end
|
399
|
+
|
400
|
+
assert_not_nil err
|
401
|
+
exp = "GEM-NAME must be provided"
|
402
|
+
assert_equal exp, err.message
|
403
|
+
assert_not_empty err.backtrace
|
404
|
+
end
|
405
|
+
|
406
|
+
end
|
407
|
+
|
408
|
+
class GemspecCommandTests < IOCommandTests
|
409
|
+
desc "GemspecCommand"
|
410
|
+
setup do
|
411
|
+
@gem1_root_path = TEST_SUPPORT_PATH.join('gem1')
|
412
|
+
Assert.stub(Dir, :pwd){ @gem1_root_path}
|
413
|
+
|
414
|
+
@command_class = Class.new{ include GemspecCommand }
|
415
|
+
@cmd = @command_class.new
|
416
|
+
end
|
417
|
+
|
418
|
+
should "be a valid, notify cmd command" do
|
419
|
+
assert_kind_of ValidCommand, subject
|
420
|
+
assert_kind_of NotifyCmdCommand, subject
|
421
|
+
end
|
422
|
+
|
423
|
+
should "build a new gemspec at the current pwd root" do
|
424
|
+
gemspec_new_called_with = nil
|
425
|
+
Assert.stub(GGem::Gemspec, :new){ |*args| gemspec_new_called_with = args }
|
426
|
+
|
427
|
+
@command_class.new
|
428
|
+
assert_equal [Dir.pwd], gemspec_new_called_with
|
429
|
+
end
|
430
|
+
|
431
|
+
should "complain if no gemspec file can be found at the current pwd" do
|
432
|
+
root = Factory.path
|
433
|
+
Assert.stub(Dir, :pwd){ root }
|
434
|
+
|
435
|
+
begin
|
436
|
+
cmd = @command_class.new
|
437
|
+
rescue ArgumentError => err
|
438
|
+
end
|
439
|
+
assert_not_nil err
|
440
|
+
exp = "There are no gemspecs at #{Dir.pwd}"
|
441
|
+
assert_equal exp, err.message
|
442
|
+
end
|
443
|
+
|
444
|
+
end
|
445
|
+
|
446
|
+
module GemspecSpyTests
|
447
|
+
include MuchPlugin
|
448
|
+
|
449
|
+
plugin_included do
|
450
|
+
include RootPathTests
|
451
|
+
|
452
|
+
setup do
|
453
|
+
@spec_spy = nil
|
454
|
+
Assert.stub(GGem::Gemspec, :new){ |*args| @spec_spy = GemspecSpy.new(*args) }
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
end
|
459
|
+
|
460
|
+
class BuildCommandTests < IOCommandTests
|
461
|
+
include GemspecSpyTests
|
462
|
+
|
463
|
+
desc "BuildCommand"
|
464
|
+
setup do
|
465
|
+
@command_class = BuildCommand
|
466
|
+
@cmd = @command_class.new
|
467
|
+
end
|
468
|
+
|
469
|
+
should "be a gemspec command" do
|
470
|
+
assert_kind_of GemspecCommand, subject
|
471
|
+
end
|
472
|
+
|
473
|
+
should "know its summary" do
|
474
|
+
exp = "Build #{@spec_spy.gem_file_name} into the " \
|
475
|
+
"#{GGem::Gemspec::BUILD_TO_DIRNAME} directory"
|
476
|
+
assert_equal exp, subject.summary
|
477
|
+
end
|
478
|
+
|
479
|
+
should "know its help" do
|
480
|
+
exp = "Usage: ggem build [options]\n\n" \
|
481
|
+
"Options: #{subject.clirb}\n" \
|
482
|
+
"Description:\n" \
|
483
|
+
" #{subject.summary}"
|
484
|
+
assert_equal exp, subject.help
|
485
|
+
end
|
486
|
+
|
487
|
+
should "call the spec's run build cmd when run" do
|
488
|
+
ENV['DEBUG'] = [nil, '1'].choice
|
489
|
+
subject.run([], @stdout, @stderr)
|
490
|
+
|
491
|
+
assert_true @spec_spy.run_build_cmd_called
|
492
|
+
|
493
|
+
exp = ENV['DEBUG'] == '1' ? "build\nbuild cmd was run\n" : ''
|
494
|
+
exp += "#{@spec_spy.name} #{@spec_spy.version} built to #{@spec_spy.gem_file}\n"
|
495
|
+
assert_equal exp, @stdout.read
|
496
|
+
|
497
|
+
ENV['DEBUG'] = nil
|
498
|
+
end
|
499
|
+
|
500
|
+
should "handle cmd errors when run" do
|
501
|
+
err_msg = Factory.string
|
502
|
+
Assert.stub(@spec_spy, :run_build_cmd){ raise GGem::Gemspec::CmdError, err_msg }
|
503
|
+
|
504
|
+
assert_raises(CommandExitError){ subject.run([], @stdout, @stderr) }
|
505
|
+
assert_equal "#{err_msg}\n", @stderr.read
|
506
|
+
end
|
507
|
+
|
508
|
+
end
|
509
|
+
|
510
|
+
class InstallCommandTests < IOCommandTests
|
511
|
+
include GemspecSpyTests
|
512
|
+
|
513
|
+
desc "InstallCommand"
|
514
|
+
setup do
|
515
|
+
@build_spy = nil
|
516
|
+
Assert.stub(BuildCommand, :new){ |*args| @build_spy = CommandSpy.new(*args) }
|
517
|
+
|
518
|
+
@command_class = InstallCommand
|
519
|
+
@argv = []
|
520
|
+
@cmd = @command_class.new
|
521
|
+
end
|
522
|
+
|
523
|
+
should "be a gemspec command" do
|
524
|
+
assert_kind_of GemspecCommand, subject
|
525
|
+
end
|
526
|
+
|
527
|
+
should "know its summary" do
|
528
|
+
exp = "Build and install #{@spec_spy.gem_file_name} into system gems"
|
529
|
+
assert_equal exp, subject.summary
|
530
|
+
end
|
531
|
+
|
532
|
+
should "know its help" do
|
533
|
+
exp = "Usage: ggem install [options]\n\n" \
|
534
|
+
"Options: #{subject.clirb}\n" \
|
535
|
+
"Description:\n" \
|
536
|
+
" #{subject.summary}"
|
537
|
+
assert_equal exp, subject.help
|
538
|
+
end
|
539
|
+
|
540
|
+
should "build a build command using its argv" do
|
541
|
+
assert @build_spy
|
542
|
+
end
|
543
|
+
|
544
|
+
should "run the build command and call the spec's run install cmds when run" do
|
545
|
+
ENV['DEBUG'] = [nil, '1'].choice
|
546
|
+
subject.run(@argv, @stdout, @stderr)
|
547
|
+
|
548
|
+
assert_true @build_spy.run_called
|
549
|
+
assert_equal @argv, @build_spy.argv
|
550
|
+
assert_true @spec_spy.run_install_cmd_called
|
551
|
+
|
552
|
+
exp = ENV['DEBUG'] == '1' ? "install\ninstall cmd was run\n" : ''
|
553
|
+
exp += "#{@spec_spy.name} #{@spec_spy.version} installed to system gems\n"
|
554
|
+
assert_includes exp, @stdout.read
|
555
|
+
|
556
|
+
ENV['DEBUG'] = nil
|
557
|
+
end
|
558
|
+
|
559
|
+
should "handle cmd errors when run" do
|
560
|
+
err_msg = Factory.string
|
561
|
+
Assert.stub(@spec_spy, :run_install_cmd){ raise GGem::Gemspec::CmdError, err_msg }
|
562
|
+
|
563
|
+
assert_raises(CommandExitError){ subject.run(@argv, @stdout, @stderr) }
|
564
|
+
assert_equal "#{err_msg}\n", @stderr.read
|
565
|
+
end
|
566
|
+
|
567
|
+
end
|
568
|
+
|
569
|
+
class PushCommandTests < IOCommandTests
|
570
|
+
include GemspecSpyTests
|
571
|
+
|
572
|
+
desc "PushCommand"
|
573
|
+
setup do
|
574
|
+
@build_spy = nil
|
575
|
+
Assert.stub(BuildCommand, :new){ |*args| @build_spy = CommandSpy.new(*args) }
|
576
|
+
|
577
|
+
@command_class = PushCommand
|
578
|
+
@argv = []
|
579
|
+
@cmd = @command_class.new
|
580
|
+
end
|
581
|
+
|
582
|
+
should "be a gemspec command" do
|
583
|
+
assert_kind_of GemspecCommand, subject
|
584
|
+
end
|
585
|
+
|
586
|
+
should "know its summary" do
|
587
|
+
exp = "Push built #{@spec_spy.gem_file_name} to #{@spec_spy.push_host}"
|
588
|
+
assert_equal exp, subject.summary
|
589
|
+
end
|
590
|
+
|
591
|
+
should "know its help" do
|
592
|
+
exp = "Usage: ggem push [options]\n\n" \
|
593
|
+
"Options: #{subject.clirb}\n" \
|
594
|
+
"Description:\n" \
|
595
|
+
" #{subject.summary}"
|
596
|
+
assert_equal exp, subject.help
|
597
|
+
end
|
598
|
+
|
599
|
+
should "build a build command using its argv" do
|
600
|
+
assert @build_spy
|
601
|
+
end
|
602
|
+
|
603
|
+
should "run the build command and call the spec's run push cmds when run" do
|
604
|
+
ENV['DEBUG'] = [nil, '1'].choice
|
605
|
+
subject.run(@argv, @stdout, @stderr)
|
606
|
+
|
607
|
+
assert_true @build_spy.run_called
|
608
|
+
assert_equal @argv, @build_spy.argv
|
609
|
+
assert_true @spec_spy.run_push_cmd_called
|
610
|
+
|
611
|
+
exp = "Pushing #{@spec_spy.gem_file_name} to #{@spec_spy.push_host}...\n"
|
612
|
+
exp += ENV['DEBUG'] == '1' ? "push\npush cmd was run\n" : ''
|
613
|
+
exp += "#{@spec_spy.gem_file_name} received.\n"
|
614
|
+
assert_equal exp, @stdout.read
|
615
|
+
|
616
|
+
ENV['DEBUG'] = nil
|
617
|
+
end
|
618
|
+
|
619
|
+
should "handle cmd errors when run" do
|
620
|
+
err_msg = Factory.string
|
621
|
+
Assert.stub(@spec_spy, :run_push_cmd){ raise GGem::Gemspec::CmdError, err_msg }
|
622
|
+
|
623
|
+
assert_raises(CommandExitError){ subject.run(@argv, @stdout, @stderr) }
|
624
|
+
assert_equal "#{err_msg}\n", @stderr.read
|
625
|
+
end
|
626
|
+
|
627
|
+
end
|
628
|
+
|
629
|
+
class TagCommandTests < IOCommandTests
|
630
|
+
include GitRepoSpyTests
|
631
|
+
include GemspecSpyTests
|
632
|
+
|
633
|
+
desc "TagCommand"
|
634
|
+
setup do
|
635
|
+
@command_class = TagCommand
|
636
|
+
@cmd = @command_class.new
|
637
|
+
end
|
638
|
+
|
639
|
+
should "be a gemspec command" do
|
640
|
+
assert_kind_of GemspecCommand, subject
|
641
|
+
end
|
642
|
+
|
643
|
+
should "know its summary" do
|
644
|
+
exp = "Tag #{@spec_spy.version_tag} and push git commits/tags"
|
645
|
+
assert_equal exp, subject.summary
|
646
|
+
end
|
647
|
+
|
648
|
+
should "know its help" do
|
649
|
+
exp = "Usage: ggem tag [options]\n\n" \
|
650
|
+
"Options: #{subject.clirb}\n" \
|
651
|
+
"Description:\n" \
|
652
|
+
" #{subject.summary}"
|
653
|
+
assert_equal exp, subject.help
|
654
|
+
end
|
655
|
+
|
656
|
+
should "call the repo's run build/push cmds when run" do
|
657
|
+
ENV['DEBUG'] = [nil, '1'].choice
|
658
|
+
subject.run([], @stdout, @stderr)
|
659
|
+
|
660
|
+
assert_true @repo_spy.run_validate_clean_cmd_called
|
661
|
+
assert_true @repo_spy.run_validate_committed_cmd_called
|
662
|
+
|
663
|
+
exp = [@spec_spy.version, @spec_spy.version_tag]
|
664
|
+
assert_equal exp, @repo_spy.run_add_version_tag_cmd_called_with
|
665
|
+
|
666
|
+
assert_true @repo_spy.run_push_cmd_called
|
667
|
+
assert_nil @repo_spy.run_rm_tag_cmd_called_with
|
668
|
+
|
669
|
+
exp = if ENV['DEBUG'] == '1'
|
670
|
+
"validate clean\nvalidate clean cmd was run\n" \
|
671
|
+
"validate committed\nvalidate committed cmd was run\n" \
|
672
|
+
"add tag\nadd tag cmd was run\n"
|
673
|
+
else
|
674
|
+
''
|
675
|
+
end
|
676
|
+
exp += "Tagged #{@spec_spy.version_tag}.\n"
|
677
|
+
exp += ENV['DEBUG'] == '1' ? "push\npush cmd was run\n" : ''
|
678
|
+
exp += "Pushed git commits and tags.\n"
|
679
|
+
assert_equal exp, @stdout.read
|
680
|
+
|
681
|
+
ENV['DEBUG'] = nil
|
682
|
+
end
|
683
|
+
|
684
|
+
should "handle validation cmd errors when run" do
|
685
|
+
err_msg = Factory.string
|
686
|
+
err_on = [:run_validate_clean_cmd, :run_validate_committed_cmd].choice
|
687
|
+
Assert.stub(@repo_spy, err_on){ raise GGem::GitRepo::CmdError, err_msg }
|
688
|
+
|
689
|
+
assert_raises(CommandExitError){ subject.run([], @stdout, @stderr) }
|
690
|
+
exp = "There are files that need to be committed first.\n"
|
691
|
+
assert_equal exp, @stderr.read
|
692
|
+
end
|
693
|
+
|
694
|
+
should "handle non-validation cmd errors when run" do
|
695
|
+
err_msg = Factory.string
|
696
|
+
err_on = [:run_add_version_tag_cmd, :run_push_cmd].choice
|
697
|
+
Assert.stub(@repo_spy, err_on){ raise GGem::GitRepo::CmdError, err_msg }
|
698
|
+
|
699
|
+
assert_raises(CommandExitError){ subject.run([], @stdout, @stderr) }
|
700
|
+
assert_equal "#{err_msg}\n", @stderr.read
|
701
|
+
end
|
702
|
+
|
703
|
+
should "remove the version tag on push errors" do
|
704
|
+
err_msg = Factory.string
|
705
|
+
Assert.stub(@repo_spy, :run_push_cmd){ raise GGem::GitRepo::CmdError, err_msg }
|
706
|
+
|
707
|
+
assert_raises(CommandExitError){ subject.run([], @stdout, @stderr) }
|
708
|
+
assert_equal "#{err_msg}\n", @stderr.read
|
709
|
+
|
710
|
+
exp = [@spec_spy.version_tag]
|
711
|
+
assert_equal exp, @repo_spy.run_rm_tag_cmd_called_with
|
712
|
+
end
|
713
|
+
|
714
|
+
should "handle tag removal cmd errors when run" do
|
715
|
+
Assert.stub(@repo_spy, :run_push_cmd){ raise GGem::GitRepo::CmdError, Factory.string }
|
716
|
+
err_msg = Factory.string
|
717
|
+
Assert.stub(@repo_spy, :run_rm_tag_cmd){ raise GGem::GitRepo::CmdError, err_msg }
|
718
|
+
|
719
|
+
assert_raises(CommandExitError){ subject.run([], @stdout, @stderr) }
|
720
|
+
assert_equal "#{err_msg}\n", @stderr.read
|
721
|
+
end
|
722
|
+
|
723
|
+
end
|
724
|
+
|
725
|
+
class ReleaseCommandTests < IOCommandTests
|
726
|
+
include GemspecSpyTests
|
727
|
+
|
728
|
+
desc "ReleaseCommand"
|
729
|
+
setup do
|
730
|
+
@tag_spy = nil
|
731
|
+
Assert.stub(TagCommand, :new){ |*args| @tag_spy = CommandSpy.new(*args) }
|
732
|
+
|
733
|
+
@push_spy = nil
|
734
|
+
Assert.stub(PushCommand, :new){ |*args| @push_spy = CommandSpy.new(*args) }
|
735
|
+
|
736
|
+
@command_class = ReleaseCommand
|
737
|
+
@argv = []
|
738
|
+
@cmd = @command_class.new
|
739
|
+
end
|
740
|
+
|
741
|
+
should "be a gemspec command" do
|
742
|
+
assert_kind_of GemspecCommand, subject
|
743
|
+
end
|
744
|
+
|
745
|
+
should "know its summary" do
|
746
|
+
exp = "Tag #{@spec_spy.version_tag} and push built #{@spec_spy.gem_file_name} to " \
|
747
|
+
"#{@spec_spy.push_host}"
|
748
|
+
assert_equal exp, subject.summary
|
749
|
+
end
|
750
|
+
|
751
|
+
should "know its help" do
|
752
|
+
exp = "Usage: ggem release [options]\n\n" \
|
753
|
+
"Options: #{subject.clirb}\n" \
|
754
|
+
"Description:\n" \
|
755
|
+
" #{subject.summary}\n" \
|
756
|
+
" (macro for running `ggem tag && ggem push`)"
|
757
|
+
assert_equal exp, subject.help
|
758
|
+
end
|
759
|
+
|
760
|
+
should "build a tag and push command using its argv" do
|
761
|
+
[@tag_spy, @push_spy].each do |spy|
|
762
|
+
assert spy
|
763
|
+
end
|
764
|
+
end
|
765
|
+
|
766
|
+
should "run the tag and push command when run" do
|
767
|
+
subject.run(@argv, @stdout, @stderr)
|
768
|
+
|
769
|
+
[@tag_spy, @push_spy].each do |spy|
|
770
|
+
assert_true spy.run_called
|
771
|
+
assert_equal @argv, spy.argv
|
772
|
+
end
|
773
|
+
end
|
774
|
+
|
775
|
+
end
|
776
|
+
|
777
|
+
class CommandSetTests < UnitTests
|
778
|
+
desc "CommandSet"
|
779
|
+
setup do
|
780
|
+
@unknown_cmd_block_called_with = nil
|
781
|
+
@set = CommandSet.new{ |*args| @unknown_cmd_block_called_with = args }
|
782
|
+
end
|
783
|
+
subject{ @set }
|
784
|
+
|
785
|
+
should have_imeths :add, :remove, :[], :size
|
786
|
+
|
787
|
+
should "add/rm commands, be able to look them up and know its size" do
|
788
|
+
assert_equal 0, subject.size
|
789
|
+
assert_equal '', subject.to_s
|
790
|
+
|
791
|
+
subject.add(CommandSpy, 'test', 't', 'tst')
|
792
|
+
assert_equal 1, subject.size
|
793
|
+
|
794
|
+
assert_instance_of CommandSpy, subject['test']
|
795
|
+
assert_same subject['test'], subject['t']
|
796
|
+
assert_same subject['test'], subject['tst']
|
797
|
+
|
798
|
+
exp_strs = ["test (t, tst) # #{subject['test'].summary}"]
|
799
|
+
assert_equal exp_strs.join("\n"), subject.to_s
|
800
|
+
|
801
|
+
subject.add(CommandSpy, 'add1')
|
802
|
+
exp_strs << "add1 # #{subject['add1'].summary}"
|
803
|
+
|
804
|
+
@cmd_spy = CommandSpy.new
|
805
|
+
Assert.stub(@cmd_spy, :summary){ [nil, ''].choice }
|
806
|
+
Assert.stub(CommandSpy, :new){ @cmd_spy }
|
807
|
+
|
808
|
+
subject.add(CommandSpy, 'add2', 'add')
|
809
|
+
exp_strs << "add2 (add) "
|
810
|
+
|
811
|
+
subject.add(CommandSpy, 'add3')
|
812
|
+
Assert.stub(subject['add3'], :summary){ [nil, ''].choice }
|
813
|
+
exp_strs << "add3 "
|
814
|
+
|
815
|
+
assert_equal exp_strs.join("\n"), subject.to_s
|
816
|
+
|
817
|
+
subject.remove('test')
|
818
|
+
subject.remove('add1')
|
819
|
+
subject.remove('add2')
|
820
|
+
subject.remove('add3')
|
821
|
+
|
822
|
+
assert_equal 0, subject.size
|
823
|
+
assert_equal '', subject.to_s
|
824
|
+
end
|
825
|
+
|
826
|
+
should "call the given block when looking up unknown command names" do
|
827
|
+
unknown_cmd_name = Factory.string
|
828
|
+
subject[unknown_cmd_name]
|
829
|
+
assert_equal [unknown_cmd_name], @unknown_cmd_block_called_with
|
830
|
+
end
|
831
|
+
|
832
|
+
end
|
833
|
+
|
834
|
+
class CLISpy
|
835
|
+
attr_reader :run_called_with
|
836
|
+
|
837
|
+
def initialize
|
838
|
+
@run_called_with = nil
|
839
|
+
end
|
840
|
+
|
841
|
+
def run(args)
|
842
|
+
@run_called_with = args
|
843
|
+
end
|
844
|
+
end
|
845
|
+
|
846
|
+
class CommandSpy
|
847
|
+
attr_reader :argv, :stdout, :stderr, :run_called
|
848
|
+
|
849
|
+
def initialize
|
850
|
+
@argv = nil
|
851
|
+
@stdout, @stderr = nil, nil
|
852
|
+
@run_called = false
|
853
|
+
end
|
854
|
+
|
855
|
+
def run(argv, stdout = nil, stderr = nil)
|
856
|
+
@argv = argv
|
857
|
+
@stdout, @stderr = stdout, stderr
|
858
|
+
@run_called = true
|
859
|
+
end
|
860
|
+
|
861
|
+
def summary
|
862
|
+
@summary ||= Factory.string
|
863
|
+
end
|
864
|
+
|
865
|
+
def help
|
866
|
+
@help ||= Factory.text
|
867
|
+
end
|
868
|
+
end
|
869
|
+
|
870
|
+
class KernelSpy
|
871
|
+
attr_reader :exit_status
|
872
|
+
|
873
|
+
def initialize
|
874
|
+
@exit_status = nil
|
875
|
+
end
|
876
|
+
|
877
|
+
def exit(code)
|
878
|
+
@exit_status ||= code
|
879
|
+
end
|
880
|
+
end
|
881
|
+
|
882
|
+
class IOSpy
|
883
|
+
def initialize
|
884
|
+
@io = StringIO.new
|
885
|
+
end
|
886
|
+
|
887
|
+
def puts(message)
|
888
|
+
@io.puts message
|
889
|
+
end
|
890
|
+
|
891
|
+
def read
|
892
|
+
@io.rewind
|
893
|
+
@io.read
|
894
|
+
end
|
895
|
+
end
|
896
|
+
|
897
|
+
class GemSpy
|
898
|
+
attr_reader :save_called
|
899
|
+
|
900
|
+
def initialize
|
901
|
+
@save_called = false
|
902
|
+
end
|
903
|
+
|
904
|
+
def save!
|
905
|
+
@save_called = true
|
906
|
+
self
|
907
|
+
end
|
908
|
+
|
909
|
+
def path
|
910
|
+
@path ||= Factory.path
|
911
|
+
end
|
912
|
+
end
|
913
|
+
|
914
|
+
class GemspecSpy
|
915
|
+
attr_reader :name, :version, :version_tag, :push_host
|
916
|
+
attr_reader :run_build_cmd_called, :run_install_cmd_called, :run_push_cmd_called
|
917
|
+
|
918
|
+
def initialize(root_path)
|
919
|
+
@root = Pathname.new(File.expand_path(root_path))
|
920
|
+
@name = Factory.string
|
921
|
+
@version = Factory.string
|
922
|
+
@version_tag = Factory.string
|
923
|
+
@push_host = Factory.url
|
924
|
+
|
925
|
+
@run_build_cmd_called = false
|
926
|
+
@run_install_cmd_called = false
|
927
|
+
@run_push_cmd_called = false
|
928
|
+
end
|
929
|
+
|
930
|
+
def path
|
931
|
+
@root.join("#{self.name}.gemspec")
|
932
|
+
end
|
933
|
+
|
934
|
+
def gem_file_name
|
935
|
+
"#{self.name}-#{self.version}.gem"
|
936
|
+
end
|
937
|
+
|
938
|
+
def gem_file
|
939
|
+
File.join(GGem::Gemspec::BUILD_TO_DIRNAME, self.gem_file_name)
|
940
|
+
end
|
941
|
+
|
942
|
+
def run_build_cmd
|
943
|
+
@run_build_cmd_called = true
|
944
|
+
['build', 0, 'build cmd was run']
|
945
|
+
end
|
946
|
+
|
947
|
+
def run_install_cmd
|
948
|
+
@run_install_cmd_called = true
|
949
|
+
['install', 0, 'install cmd was run']
|
950
|
+
end
|
951
|
+
|
952
|
+
def run_push_cmd
|
953
|
+
@run_push_cmd_called = true
|
954
|
+
['push', 0, 'push cmd was run']
|
955
|
+
end
|
956
|
+
|
957
|
+
end
|
958
|
+
|
959
|
+
class GitRepoSpy
|
960
|
+
attr_reader :path
|
961
|
+
attr_reader :run_init_cmd_called
|
962
|
+
attr_reader :run_validate_clean_cmd_called, :run_validate_committed_cmd_called
|
963
|
+
attr_reader :run_add_version_tag_cmd_called_with, :run_rm_tag_cmd_called_with
|
964
|
+
attr_reader :run_push_cmd_called
|
965
|
+
|
966
|
+
def initialize(path)
|
967
|
+
@path = path
|
968
|
+
|
969
|
+
@run_init_cmd_called = false
|
970
|
+
|
971
|
+
@run_validate_clean_cmd_called = false
|
972
|
+
@run_validate_committed_cmd_called = false
|
973
|
+
|
974
|
+
@run_add_version_tag_cmd_called_with = nil
|
975
|
+
@run_rm_tag_cmd_called_with = nil
|
976
|
+
|
977
|
+
@run_push_cmd_called = false
|
978
|
+
end
|
979
|
+
|
980
|
+
def run_init_cmd
|
981
|
+
@run_init_cmd_called = true
|
982
|
+
['init', 0, 'init cmd was run']
|
983
|
+
end
|
984
|
+
|
985
|
+
def run_validate_clean_cmd
|
986
|
+
@run_validate_clean_cmd_called = true
|
987
|
+
['validate clean', 0, 'validate clean cmd was run']
|
988
|
+
end
|
989
|
+
|
990
|
+
def run_validate_committed_cmd
|
991
|
+
@run_validate_committed_cmd_called = true
|
992
|
+
['validate committed', 0, 'validate committed cmd was run']
|
993
|
+
end
|
994
|
+
|
995
|
+
def run_add_version_tag_cmd(*args)
|
996
|
+
@run_add_version_tag_cmd_called_with = args
|
997
|
+
['add tag', 0, 'add tag cmd was run']
|
998
|
+
end
|
999
|
+
|
1000
|
+
def run_rm_tag_cmd(*args)
|
1001
|
+
@run_rm_tag_cmd_called_with = args
|
1002
|
+
['rm tag', 0, 'rm tag cmd was run']
|
1003
|
+
end
|
1004
|
+
|
1005
|
+
def run_push_cmd
|
1006
|
+
@run_push_cmd_called = true
|
1007
|
+
['push', 0, 'push cmd was run']
|
1008
|
+
end
|
1009
|
+
|
1010
|
+
end
|
1011
|
+
|
1012
|
+
end
|