topfunky-github 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/spec/ui_spec.rb ADDED
@@ -0,0 +1,506 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "github" do
4
+ # -- home --
5
+ specify "home should open the project home page" do
6
+ running :home do
7
+ setup_url_for
8
+ @helper.should_receive(:open).once.with("https://github.com/user/project/tree/master")
9
+ end
10
+ end
11
+
12
+ specify "home defunkt should open the home page of defunkt's fork" do
13
+ running :home, "defunkt" do
14
+ setup_url_for
15
+ @helper.should_receive(:open).once.with("https://github.com/defunkt/project/tree/master")
16
+ end
17
+ end
18
+
19
+ # -- browse --
20
+ specify "browse should open the project home page with the current branch" do
21
+ running :browse do
22
+ setup_url_for
23
+ setup_user_and_branch("user", "test-branch")
24
+ @helper.should_receive(:open).once.with("https://github.com/user/project/tree/test-branch")
25
+ end
26
+ end
27
+
28
+ specify "browse pending should open the project home page with the 'pending' branch" do
29
+ running :browse, "pending" do
30
+ setup_url_for
31
+ setup_user_and_branch("user", "test-branch")
32
+ @helper.should_receive(:open).once.with("https://github.com/user/project/tree/pending")
33
+ end
34
+ end
35
+
36
+ specify "browse defunkt pending should open the home page of defunkt's fork with the 'pending' branch" do
37
+ running :browse, "defunkt", "pending" do
38
+ setup_url_for
39
+ @helper.should_receive(:open).once.with("https://github.com/defunkt/project/tree/pending")
40
+ end
41
+ end
42
+
43
+ specify "browse defunkt/pending should open the home page of defunkt's fork with the 'pending' branch" do
44
+ running :browse, "defunkt/pending" do
45
+ setup_url_for
46
+ @helper.should_receive(:open).once.with("https://github.com/defunkt/project/tree/pending")
47
+ end
48
+ end
49
+
50
+ # -- network --
51
+ specify "network should open the network page for this repo" do
52
+ running :network do
53
+ setup_url_for
54
+ @helper.should_receive(:open).once.with("https://github.com/user/project/network")
55
+ end
56
+ end
57
+
58
+ specify "network defunkt should open the network page for defunkt's fork" do
59
+ running :network, "defunkt" do
60
+ setup_url_for
61
+ @helper.should_receive(:open).once.with("https://github.com/defunkt/project/network")
62
+ end
63
+ end
64
+
65
+ # -- info --
66
+ specify "info should show info for this project" do
67
+ running :info do
68
+ setup_url_for
69
+ setup_remote(:origin, :user => "user", :ssh => true)
70
+ setup_remote(:defunkt)
71
+ setup_remote(:external, :url => "home:/path/to/project.git")
72
+ stdout.should == <<-EOF
73
+ == Info for project
74
+ You are user
75
+ Currently tracking:
76
+ - user (as origin)
77
+ - defunkt (as defunkt)
78
+ - home:/path/to/project.git (as external)
79
+ EOF
80
+ end
81
+ end
82
+
83
+ # -- track --
84
+ specify "track defunkt should track a new remote for defunkt" do
85
+ running :track, "defunkt" do
86
+ setup_url_for
87
+ @helper.should_receive(:tracking?).with("defunkt").once.and_return(false)
88
+ @command.should_receive(:git).with("remote add defunkt git://github.com/defunkt/project.git").once
89
+ end
90
+ end
91
+
92
+ specify "track --private defunkt should track a new remote for defunkt using ssh" do
93
+ running :track, "--private", "defunkt" do
94
+ setup_url_for
95
+ @helper.should_receive(:tracking?).with("defunkt").and_return(false)
96
+ @command.should_receive(:git).with("remote add defunkt git@github.com:defunkt/project.git")
97
+ end
98
+ end
99
+
100
+ specify "track --ssh defunkt should be equivalent to track --private defunkt" do
101
+ running :track, "--ssh", "defunkt" do
102
+ setup_url_for
103
+ @helper.should_receive(:tracking?).with("defunkt").and_return(false)
104
+ @command.should_receive(:git).with("remote add defunkt git@github.com:defunkt/project.git")
105
+ end
106
+ end
107
+
108
+ specify "track defunkt should die if the defunkt remote exists" do
109
+ running :track, "defunkt" do
110
+ setup_url_for
111
+ @helper.should_receive(:tracking?).with("defunkt").once.and_return(true)
112
+ @command.should_receive(:die).with("Already tracking defunkt").and_return { raise "Died" }
113
+ self.should raise_error("Died")
114
+ end
115
+ end
116
+
117
+ specify "track should die with no args" do
118
+ running :track do
119
+ @command.should_receive(:die).with("Specify a user to track").and_return { raise "Died" }
120
+ self.should raise_error("Died")
121
+ end
122
+ end
123
+
124
+ specify "track should accept user/project syntax" do
125
+ running :track, "defunkt/github-gem.git" do
126
+ setup_url_for
127
+ @helper.should_receive(:tracking?).with("defunkt").and_return false
128
+ @command.should_receive(:git).with("remote add defunkt git://github.com/defunkt/github-gem.git")
129
+ end
130
+ end
131
+
132
+ specify "track defunkt/github-gem.git should function with no origin remote" do
133
+ running :track, "defunkt/github-gem.git" do
134
+ @helper.stub!(:url_for).with(:origin).and_return ""
135
+ @helper.stub!(:tracking?).and_return false
136
+ @command.should_receive(:git).with("remote add defunkt git://github.com/defunkt/github-gem.git")
137
+ self.should_not raise_error(SystemExit)
138
+ stderr.should_not =~ /^Error/
139
+ end
140
+ end
141
+
142
+ specify "track origin defunkt/github-gem should track defunkt/github-gem as the origin remote" do
143
+ running :track, "origin", "defunkt/github-gem" do
144
+ @helper.stub!(:url_for).with(:origin).and_return ""
145
+ @helper.stub!(:tracking?).and_return false
146
+ @command.should_receive(:git).with("remote add origin git://github.com/defunkt/github-gem.git")
147
+ stderr.should_not =~ /^Error/
148
+ end
149
+ end
150
+
151
+ specify "track --private origin defunkt/github-gem should track defunkt/github-gem as the origin remote using ssh" do
152
+ running :track, "--private", "origin", "defunkt/github-gem" do
153
+ @helper.stub!(:url_for).with(:origin).and_return ""
154
+ @helper.stub!(:tracking?).and_return false
155
+ @command.should_receive(:git).with("remote add origin git@github.com:defunkt/github-gem.git")
156
+ stderr.should_not =~ /^Error/
157
+ end
158
+ end
159
+
160
+ # -- pull --
161
+ specify "pull should die with no args" do
162
+ running :pull do
163
+ @command.should_receive(:die).with("Specify a user to pull from").and_return { raise "Died" }
164
+ self.should raise_error("Died")
165
+ end
166
+ end
167
+
168
+ specify "pull defunkt should start tracking defunkt if they're not already tracked" do
169
+ running :pull, "defunkt" do
170
+ setup_remote(:origin, :user => "user", :ssh => true)
171
+ setup_remote(:external, :url => "home:/path/to/project.git")
172
+ GitHub.should_receive(:invoke).with(:track, "defunkt").and_return { raise "Tracked" }
173
+ self.should raise_error("Tracked")
174
+ end
175
+ end
176
+
177
+ specify "pull defunkt should create defunkt/master and pull from the defunkt remote" do
178
+ running :pull, "defunkt" do
179
+ setup_remote(:defunkt)
180
+ @command.should_receive(:git).with("checkout -b defunkt/master").ordered.and_return do
181
+ mock("checkout -b defunkt/master").tap { |m| m.stub!(:error?) }
182
+ end
183
+ @command.should_receive(:git_exec).with("pull defunkt master").ordered
184
+ stdout.should == "Switching to defunkt/master\n"
185
+ end
186
+ end
187
+
188
+ specify "pull defunkt should switch to pre-existing defunkt/master and pull from the defunkt remote" do
189
+ running :pull, "defunkt" do
190
+ setup_remote(:defunkt)
191
+ @command.should_receive(:git).with("checkout -b defunkt/master").ordered.and_return do
192
+ mock("checkout -b defunkt/master").tap { |m| m.should_receive(:error?) { true } }
193
+ end
194
+ @command.should_receive(:git).with("checkout defunkt/master").ordered
195
+ @command.should_receive(:git_exec).with("pull defunkt master").ordered
196
+ stdout.should == "Switching to defunkt/master\n"
197
+ end
198
+ end
199
+
200
+ specify "pull defunkt wip should create defunkt/wip and pull from wip branch on defunkt remote" do
201
+ running :pull, "defunkt", "wip" do
202
+ setup_remote(:defunkt)
203
+ @command.should_receive(:git).with("checkout -b defunkt/wip").ordered.and_return do
204
+ mock("checkout -b defunkt/wip").tap { |m| m.stub!(:error?) }
205
+ end
206
+ @command.should_receive(:git_exec).with("pull defunkt wip").ordered
207
+ stdout.should == "Switching to defunkt/wip\n"
208
+ end
209
+ end
210
+
211
+ specify "pull defunkt/wip should switch to pre-existing defunkt/wip and pull from wip branch on defunkt remote" do
212
+ running :pull, "defunkt/wip" do
213
+ setup_remote(:defunkt)
214
+ @command.should_receive(:git).with("checkout -b defunkt/wip").ordered.and_return do
215
+ mock("checkout -b defunkt/wip").tap { |m| m.should_receive(:error?) { true } }
216
+ end
217
+ @command.should_receive(:git).with("checkout defunkt/wip").ordered
218
+ @command.should_receive(:git_exec).with("pull defunkt wip").ordered
219
+ stdout.should == "Switching to defunkt/wip\n"
220
+ end
221
+ end
222
+
223
+ specify "pull --merge defunkt should pull from defunkt remote into current branch" do
224
+ running :pull, "--merge", "defunkt" do
225
+ setup_remote(:defunkt)
226
+ @command.should_receive(:git_exec).with("pull defunkt master")
227
+ end
228
+ end
229
+
230
+ # -- clone --
231
+ specify "clone should die with no args" do
232
+ running :clone do
233
+ @command.should_receive(:die).with("Specify a user to pull from").and_return { raise "Died" }
234
+ self.should raise_error("Died")
235
+ end
236
+ end
237
+
238
+ specify "clone should die with just one arg" do
239
+ running :clone, "user" do
240
+ @command.should_receive(:die).with("Specify a repo to pull from").and_return { raise "Died" }
241
+ self.should raise_error("Died")
242
+ end
243
+ end
244
+
245
+ specify "clone defunkt github-gem should clone the repo" do
246
+ running :clone, "defunkt", "github-gem" do
247
+ @command.should_receive(:git_exec).with("clone git://github.com/defunkt/github-gem.git")
248
+ end
249
+ end
250
+
251
+ specify "clone --ssh defunkt github-gem should clone the repo using the private URL" do
252
+ running :clone, "--ssh", "defunkt", "github-gem" do
253
+ @command.should_receive(:git_exec).with("clone git@github.com:defunkt/github-gem.git")
254
+ end
255
+ end
256
+
257
+ specify "clone defunkt github-gem repo should clone the repo into the dir 'repo'" do
258
+ running :clone, "defunkt", "github-gem", "repo" do
259
+ @command.should_receive(:git_exec).with("clone git://github.com/defunkt/github-gem.git repo")
260
+ end
261
+ end
262
+
263
+ specify "clone --ssh defunkt github-gem repo should clone the repo using the private URL into the dir 'repo'" do
264
+ running :clone, "--ssh", "defunkt", "github-gem", "repo" do
265
+ @command.should_receive(:git_exec).with("clone git@github.com:defunkt/github-gem.git repo")
266
+ end
267
+ end
268
+
269
+ specify "clone defunkt/github-gem repo should clone the repo into the dir 'repo'" do
270
+ running :clone, "defunkt/github-gem", "repo" do
271
+ @command.should_receive(:git_exec).with("clone git://github.com/defunkt/github-gem.git repo")
272
+ end
273
+ end
274
+
275
+ # -- pull-request --
276
+ specify "pull-request should die with no args" do
277
+ running :'pull-request' do
278
+ setup_url_for
279
+ @command.should_receive(:die).with("Specify a user for the pull request").and_return { raise "Died" }
280
+ self.should raise_error("Died")
281
+ end
282
+ end
283
+
284
+ specify "pull-request user should track user if untracked" do
285
+ running :'pull-request', "user" do
286
+ setup_url_for
287
+ setup_remote :origin, :user => "kballard"
288
+ setup_remote :defunkt
289
+ GitHub.should_receive(:invoke).with(:track, "user").and_return { raise "Tracked" }
290
+ self.should raise_error("Tracked")
291
+ end
292
+ end
293
+
294
+ specify "pull-request user/branch should generate a pull request" do
295
+ running :'pull-request', "user/branch" do
296
+ setup_url_for
297
+ setup_remote :origin, :user => "kballard"
298
+ setup_remote :user
299
+ @command.should_receive(:git_exec).with("request-pull user/branch origin")
300
+ end
301
+ end
302
+
303
+ specify "pull-request user should generate a pull request with branch master" do
304
+ running :'pull-request', "user" do
305
+ setup_url_for
306
+ setup_remote :origin, :user => "kballard"
307
+ setup_remote :user
308
+ @command.should_receive(:git_exec).with("request-pull user/master origin")
309
+ end
310
+ end
311
+
312
+ specify "pull-request user branch should generate a pull request" do
313
+ running:'pull-request', "user", "branch" do
314
+ setup_url_for
315
+ setup_remote :origin, :user => "kballard"
316
+ setup_remote :user
317
+ @command.should_receive(:git_exec).with("request-pull user/branch origin")
318
+ end
319
+ end
320
+
321
+ # -- default --
322
+ specify "should print the default message" do
323
+ running :default do
324
+ GitHub.should_receive(:descriptions).any_number_of_times.and_return({
325
+ "home" => "Open the home page",
326
+ "track" => "Track a new repo",
327
+ "browse" => "Browse the github page for this branch",
328
+ "command" => "description"
329
+ })
330
+ GitHub.should_receive(:flag_descriptions).any_number_of_times.and_return({
331
+ "home" => {:flag => "Flag description"},
332
+ "track" => {:flag1 => "Flag one", :flag2 => "Flag two"},
333
+ "browse" => {},
334
+ "command" => {}
335
+ })
336
+ @command.should_receive(:puts).with("Usage: github command <space separated arguments>", '').ordered
337
+ @command.should_receive(:puts).with("Available commands:", '').ordered
338
+ @command.should_receive(:puts).with(" home => Open the home page")
339
+ @command.should_receive(:puts).with(" --flag: Flag description")
340
+ @command.should_receive(:puts).with(" track => Track a new repo")
341
+ @command.should_receive(:puts).with(" --flag1: Flag one")
342
+ @command.should_receive(:puts).with(" --flag2: Flag two")
343
+ @command.should_receive(:puts).with(" browse => Browse the github page for this branch")
344
+ @command.should_receive(:puts).with(" command => description")
345
+ @command.should_receive(:puts).with()
346
+ end
347
+ end
348
+
349
+ # -----------------
350
+
351
+ def running(cmd, *args, &block)
352
+ Runner.new(self, cmd, *args, &block).run
353
+ end
354
+
355
+ class Runner
356
+ include SetupMethods
357
+
358
+ def initialize(parent, cmd, *args, &block)
359
+ @cmd_name = cmd.to_s
360
+ @command = GitHub.commands[cmd.to_s]
361
+ @helper = @command.helper
362
+ @args = args
363
+ @block = block
364
+ @parent = parent
365
+ end
366
+
367
+ def run
368
+ self.instance_eval &@block
369
+ mock_remotes unless @remotes.nil?
370
+ GitHub.should_receive(:load).with("commands.rb")
371
+ GitHub.should_receive(:load).with("helpers.rb")
372
+ args = @args.clone
373
+ GitHub.parse_options(args) # strip out the flags
374
+ GitHub.should_receive(:invoke).with(@cmd_name, *args).and_return do
375
+ GitHub.send(GitHub.send(:__mock_proxy).send(:munge, :invoke), @cmd_name, *args)
376
+ end
377
+ invoke = lambda { GitHub.activate([@cmd_name, *@args]) }
378
+ if @expected_result
379
+ expectation, result = @expected_result
380
+ case result
381
+ when Spec::Matchers::RaiseError, Spec::Matchers::Change, Spec::Matchers::ThrowSymbol
382
+ invoke.send expectation, result
383
+ else
384
+ invoke.call.send expectation, result
385
+ end
386
+ else
387
+ invoke.call
388
+ end
389
+ @stdout_mock.invoke unless @stdout_mock.nil?
390
+ @stderr_mock.invoke unless @stderr_mock.nil?
391
+ end
392
+
393
+ def setup_remote(remote, options = {:user => nil, :project => "project"})
394
+ @remotes ||= {}
395
+ user = options[:user] || remote
396
+ project = options[:project]
397
+ ssh = options[:ssh]
398
+ url = options[:url]
399
+ if url
400
+ @remotes[remote.to_sym] = url
401
+ elsif ssh
402
+ @remotes[remote.to_sym] = "git@github.com:#{user}/#{project}.git"
403
+ else
404
+ @remotes[remote.to_sym] = "git://github.com/#{user}/#{project}.git"
405
+ end
406
+ end
407
+
408
+ def mock_remotes()
409
+ @helper.should_receive(:remotes).any_number_of_times.and_return(@remotes)
410
+ end
411
+
412
+ def should(result)
413
+ @expected_result = [:should, result]
414
+ end
415
+
416
+ def should_not(result)
417
+ @expected_result = [:should_not, result]
418
+ end
419
+
420
+ def stdout
421
+ if @stdout_mock.nil?
422
+ output = ""
423
+ @stdout_mock = DeferredMock.new(output)
424
+ STDOUT.should_receive(:write).any_number_of_times do |str|
425
+ output << str
426
+ end
427
+ end
428
+ @stdout_mock
429
+ end
430
+
431
+ def stderr
432
+ if @stderr_mock.nil?
433
+ output = ""
434
+ @stderr_mock = DeferredMock.new(output)
435
+ STDERR.should_receive(:write).any_number_of_times do |str|
436
+ output << str
437
+ end
438
+ end
439
+ @stderr_mock
440
+ end
441
+
442
+ class DeferredMock
443
+ def initialize(obj = nil)
444
+ @obj = obj
445
+ @calls = []
446
+ @expectations = []
447
+ end
448
+
449
+ attr_reader :obj
450
+
451
+ def invoke(obj = nil)
452
+ obj ||= @obj
453
+ @calls.each do |sym, args|
454
+ obj.send sym, *args
455
+ end
456
+ @expectations.each do |exp|
457
+ exp.invoke
458
+ end
459
+ end
460
+
461
+ def should(*args)
462
+ if args.empty?
463
+ exp = Expectation.new(self, :should)
464
+ @expectations << exp
465
+ exp
466
+ else
467
+ @calls << [:should, args]
468
+ end
469
+ end
470
+
471
+ def should_not(*args)
472
+ if args.empty?
473
+ exp = Expectation.new(self, :should_not)
474
+ @expectations << exp
475
+ exp
476
+ else
477
+ @calls << [:should_not, args]
478
+ end
479
+ end
480
+
481
+ class Expectation
482
+ def initialize(mock, call)
483
+ @mock = mock
484
+ @call = call
485
+ @calls = []
486
+ end
487
+
488
+ undef_method *(instance_methods.map { |x| x.to_sym } - [:__id__, :__send__])
489
+
490
+ def invoke
491
+ @calls.each do |sym, args|
492
+ (@mock.obj.send @call).send sym, *args
493
+ end
494
+ end
495
+
496
+ def method_missing(sym, *args)
497
+ @calls << [sym, args]
498
+ end
499
+ end
500
+ end
501
+
502
+ def method_missing(sym, *args)
503
+ @parent.send sym, *args
504
+ end
505
+ end
506
+ end