hub_test.rb 44.6 KB
Newer Older
1
require 'helper'
2
require 'webmock/test_unit'
3
require 'rbconfig'
4
require 'yaml'
5
require 'forwardable'
6
require 'fileutils'
C
Chris Wanstrath 已提交
7

8 9 10 11 12 13
WebMock::BodyPattern.class_eval do
  undef normalize_hash
  # override normalizing hash since it otherwise requires JSON
  def normalize_hash(hash) hash end
end

C
Chris Wanstrath 已提交
14
class HubTest < Test::Unit::TestCase
15 16
  extend Forwardable

17 18 19 20 21
  if defined? WebMock::API
    include WebMock::API
  else
    include WebMock
  end
C
Chris Wanstrath 已提交
22

23 24
  COMMANDS = []

25 26 27 28
  Hub::Context.class_eval do
    remove_method :which
    define_method :which do |name|
      COMMANDS.include?(name) ? "/usr/bin/#{name}" : nil
29 30 31
    end
  end

32 33 34 35
  attr_reader :git_reader
  include Hub::Context::GitReaderMethods
  def_delegators :git_reader, :stub_config_value, :stub_command_output

36
  def setup
37
    super
38
    COMMANDS.replace %w[open groff]
39
    Hub::Context::PWD.replace '/path/to/hub'
40
    Hub::SshConfig::CONFIG_FILES.replace []
41

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
    @prompt_stubs = prompt_stubs = []
    @password_prompt_stubs = password_prompt_stubs = []

    Hub::GitHubAPI::Configuration.class_eval do
      undef prompt
      undef prompt_password

      define_method :prompt do |what|
        prompt_stubs.shift.call(what)
      end
      define_method :prompt_password do |host, user|
        password_prompt_stubs.shift.call(host, user)
      end
    end

57 58 59
    @git_reader = Hub::Context::GitReader.new 'git' do |cache, cmd|
      unless cmd.index('config --get alias.') == 0
        raise ArgumentError, "`git #{cmd}` not stubbed"
M
Mislav Marohnić 已提交
60
      end
61 62 63 64
    end

    Hub::Commands.instance_variable_set :@git_reader, @git_reader
    Hub::Commands.instance_variable_set :@local_repo, nil
65 66 67 68 69 70 71
    Hub::Commands.instance_variable_set :@api_client, nil

    FileUtils.rm_rf ENV['HUB_CONFIG']

    edit_hub_config do |data|
      data['github.com'] = [{'user' => 'tpw', 'oauth_token' => 'OTOKEN'}]
    end
72 73

    @git_reader.stub! \
74
      'remote' => "mislav\norigin",
75
      'symbolic-ref -q HEAD' => 'refs/heads/master',
76 77
      'config --get-all remote.origin.url' => 'git://github.com/defunkt/hub.git',
      'config --get-all remote.mislav.url' => 'git://github.com/mislav/hub.git',
78
      'rev-parse --symbolic-full-name master@{upstream}' => 'refs/remotes/origin/master',
79 80
      'config --get --bool hub.http-clone' => 'false',
      'config --get hub.protocol' => nil,
81
      'config --get-all hub.host' => nil,
82
      'rev-parse -q --git-dir' => '.git'
83 84
  end

C
Chris Wanstrath 已提交
85
  def test_private_clone
86
    stub_no_git_repo
87 88
    input   = "clone -p rtomayko/ronn"
    command = "git clone git@github.com:rtomayko/ronn.git"
C
Chris Wanstrath 已提交
89
    assert_command input, command
C
Chris Wanstrath 已提交
90 91
  end

92
  def test_private_clone_noop
93
    stub_no_git_repo
94 95 96 97 98
    input   = "--noop clone -p rtomayko/ronn"
    command = "git clone git@github.com:rtomayko/ronn.git\n"
    assert_output command, hub(input)
  end

99
  def test_https_clone
100
    stub_no_git_repo
101 102 103 104 105 106
    stub_https_is_preferred
    input   = "clone rtomayko/ronn"
    command = "git clone https://github.com/rtomayko/ronn.git"
    assert_command input, command
  end

C
Chris Wanstrath 已提交
107
  def test_public_clone
108
    stub_no_git_repo
109 110
    input   = "clone rtomayko/ronn"
    command = "git clone git://github.com/rtomayko/ronn.git"
C
Chris Wanstrath 已提交
111
    assert_command input, command
C
Chris Wanstrath 已提交
112 113
  end

114
  def test_your_private_clone
115
    stub_no_git_repo
116 117 118 119 120
    input   = "clone -p resque"
    command = "git clone git@github.com:tpw/resque.git"
    assert_command input, command
  end

121
  def test_your_clone_is_always_private
122
    stub_no_git_repo
123
    input   = "clone resque"
124
    command = "git clone git@github.com:tpw/resque.git"
125 126 127
    assert_command input, command
  end

128
  def test_clone_repo_with_period
129
    stub_no_git_repo
130 131 132 133 134
    input   = "clone hookio/hook.js"
    command = "git clone git://github.com/hookio/hook.js.git"
    assert_command input, command
  end

135
  def test_clone_with_arguments
136
    stub_no_git_repo
137
    input   = "clone --bare -o master resque"
138
    command = "git clone --bare -o master git@github.com:tpw/resque.git"
139 140 141
    assert_command input, command
  end

142
  def test_clone_with_arguments_and_destination
143
    stub_no_git_repo
144 145 146
    assert_forwarded "clone --template=one/two git://github.com/tpw/resque.git --origin master resquetastic"
  end

147
  def xtest_your_private_clone_fails_without_config
148
    stub_no_git_repo
149
    out = hub("clone -p mustache") do
150
      stub_github_user(nil)
151 152
    end

153
    assert_equal "** No GitHub user set. See http://help.github.com/set-your-user-name-email-and-github-token/\n", out
154 155
  end

156
  def xtest_your_public_clone_fails_without_config
157
    stub_no_git_repo
158
    out = hub("clone mustache") do
159
      stub_github_user(nil)
160 161
    end

162
    assert_equal "** No GitHub user set. See http://help.github.com/set-your-user-name-email-and-github-token/\n", out
163 164
  end

165
  def test_private_clone_left_alone
166
    stub_no_git_repo
167
    assert_forwarded "clone git@github.com:rtomayko/ronn.git"
168 169 170
  end

  def test_public_clone_left_alone
171
    stub_no_git_repo
172
    assert_forwarded "clone git://github.com/rtomayko/ronn.git"
173
  end
C
Chris Wanstrath 已提交
174 175

  def test_normal_public_clone_with_path
176
    stub_no_git_repo
177
    assert_forwarded "clone git://github.com/rtomayko/ronn.git ronn-dev"
C
Chris Wanstrath 已提交
178
  end
179 180

  def test_normal_clone_from_path
181
    stub_no_git_repo
182
    assert_forwarded "clone ./test"
183
  end
184

185 186 187 188 189 190 191 192 193 194
  def test_unchanged_clone_from_existing_directory
    stub_no_git_repo
    assert_forwarded "clone test"
  end

  def test_local_clone_with_destination
    stub_no_git_repo
    assert_forwarded "clone -l . ../copy"
  end

195
  def test_clone_with_host_alias
196
    stub_no_git_repo
197 198 199
    assert_forwarded "clone server:git/repo.git"
  end

200
  def test_enterprise_clone
201
    stub_no_git_repo
202 203 204 205 206 207 208
    stub_github_user('myfiname', 'git.my.org')
    with_host_env('git.my.org') do
      assert_command "clone myrepo", "git clone git@git.my.org:myfiname/myrepo.git"
      assert_command "clone another/repo", "git clone git@git.my.org:another/repo.git"
    end
  end

M
Mislav Marohnić 已提交
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
  def test_alias_expand
    stub_alias 'c', 'clone --bare'
    input   = "c rtomayko/ronn"
    command = "git clone --bare git://github.com/rtomayko/ronn.git"
    assert_command input, command
  end

  def test_alias_expand_advanced
    stub_alias 'c', 'clone --template="white space"'
    input   = "c rtomayko/ronn"
    command = "git clone '--template=white space' git://github.com/rtomayko/ronn.git"
    assert_command input, command
  end

  def test_alias_doesnt_expand_for_unknown_commands
    stub_alias 'c', 'compute --fast'
    assert_forwarded "c rtomayko/ronn"
  end

228 229 230 231 232 233
  def test_remote_origin
    input   = "remote add origin"
    command = "git remote add origin git://github.com/tpw/hub.git"
    assert_command input, command
  end

234 235 236 237 238 239
  def test_remote_add_with_name
    input   = "remote add another hookio/hub.js"
    command = "git remote add another git://github.com/hookio/hub.js.git"
    assert_command input, command
  end

240 241 242 243 244 245
  def test_private_remote_origin
    input   = "remote add -p origin"
    command = "git remote add origin git@github.com:tpw/hub.git"
    assert_command input, command
  end

246 247 248 249 250 251
  def test_public_remote_url_untouched
    assert_forwarded "remote add origin http://github.com/defunkt/resque.git"
  end

  def test_private_remote_url_untouched
    assert_forwarded "remote add origin git@github.com:defunkt/resque.git"
252 253
  end

254
  def test_remote_from_rel_path
255
    assert_forwarded "remote add origin ./path"
256 257 258
  end

  def test_remote_from_abs_path
259
    assert_forwarded "remote add origin /path"
260 261
  end

262
  def test_remote_with_host_alias
263 264 265
    assert_forwarded "remote add origin server:/git/repo.git"
  end

266 267 268 269
  def test_remote_add_enterprise
    stub_hub_host('git.my.org')
    stub_repo_url('git@git.my.org:defunkt/hub.git')
    assert_command "remote add another", "git remote add another git@git.my.org:another/hub.git"
C
Chris Wanstrath 已提交
270 271
  end

S
Stephen Celis 已提交
272 273
  def test_public_submodule
    input   = "submodule add wycats/bundler vendor/bundler"
J
Justin Ridgewell 已提交
274 275
    command = "git submodule add git://github.com/wycats/bundler.git vendor/bundler"
    assert_command input, command
S
Stephen Celis 已提交
276 277 278 279
  end

  def test_private_submodule
    input   = "submodule add -p grit vendor/grit"
J
Justin Ridgewell 已提交
280 281 282 283 284 285 286 287
    command = "git submodule add git@github.com:tpw/grit.git vendor/grit"
    assert_command input, command
  end

  def test_submodule_branch
    input   = "submodule add -b ryppl ryppl/pip vendor/pip"
    command = "git submodule add -b ryppl git://github.com/ryppl/pip.git vendor/pip"
    assert_command input, command
S
Stephen Celis 已提交
288 289 290 291 292
  end

  def test_submodule_with_args
    input   = "submodule -q add --bare -- grit grit"
    command = "git submodule -q add --bare -- git://github.com/tpw/grit.git grit"
J
Justin Ridgewell 已提交
293
    assert_command input, command
S
Stephen Celis 已提交
294 295
  end

C
Chris Wanstrath 已提交
296
  def test_private_remote
297
    input   = "remote add -p rtomayko"
C
Chris Wanstrath 已提交
298 299
    command = "git remote add rtomayko git@github.com:rtomayko/hub.git"
    assert_command input, command
C
Chris Wanstrath 已提交
300 301
  end

302 303 304 305 306 307 308
  def test_https_protocol_remote
    stub_https_is_preferred
    input   = "remote add rtomayko"
    command = "git remote add rtomayko https://github.com/rtomayko/hub.git"
    assert_command input, command
  end

C
Chris Wanstrath 已提交
309
  def test_public_remote
310
    input   = "remote add rtomayko"
C
Chris Wanstrath 已提交
311 312
    command = "git remote add rtomayko git://github.com/rtomayko/hub.git"
    assert_command input, command
C
Chris Wanstrath 已提交
313 314
  end

C
Chris Wanstrath 已提交
315 316 317 318 319 320
  def test_public_remote_f
    input   = "remote add -f rtomayko"
    command = "git remote add -f rtomayko git://github.com/rtomayko/hub.git"
    assert_command input, command
  end

321 322 323 324 325 326
  def test_named_public_remote
    input   = "remote add origin rtomayko"
    command = "git remote add origin git://github.com/rtomayko/hub.git"
    assert_command input, command
  end

327 328 329 330 331 332
  def test_named_public_remote_f
    input   = "remote add -f origin rtomayko"
    command = "git remote add -f origin git://github.com/rtomayko/hub.git"
    assert_command input, command
  end

C
Chris Wanstrath 已提交
333
  def test_private_remote_with_repo
334 335
    input   = "remote add -p jashkenas/coffee-script"
    command = "git remote add jashkenas git@github.com:jashkenas/coffee-script.git"
C
Chris Wanstrath 已提交
336 337 338 339
    assert_command input, command
  end

  def test_public_remote_with_repo
340 341
    input   = "remote add jashkenas/coffee-script"
    command = "git remote add jashkenas git://github.com/jashkenas/coffee-script.git"
342 343 344 345
    assert_command input, command
  end

  def test_public_remote_f_with_repo
346 347
    input   = "remote add -f jashkenas/coffee-script"
    command = "git remote add -f jashkenas git://github.com/jashkenas/coffee-script.git"
C
Chris Wanstrath 已提交
348 349 350
    assert_command input, command
  end

351
  def test_named_private_remote_with_repo
352 353
    input   = "remote add -p origin jashkenas/coffee-script"
    command = "git remote add origin git@github.com:jashkenas/coffee-script.git"
354 355 356
    assert_command input, command
  end

357
  def test_fetch_existing_remote
358
    assert_forwarded "fetch mislav"
359 360 361 362 363 364
  end

  def test_fetch_new_remote
    stub_remotes_group('xoebus', nil)
    stub_existing_fork('xoebus')

365 366 367
    assert_commands "git remote add xoebus git://github.com/xoebus/hub.git",
                    "git fetch xoebus",
                    "fetch xoebus"
368 369
  end

370 371 372 373 374 375 376 377 378 379
  def test_fetch_new_remote_https_protocol
    stub_remotes_group('xoebus', nil)
    stub_existing_fork('xoebus')
    stub_https_is_preferred

    assert_commands "git remote add xoebus https://github.com/xoebus/hub.git",
                    "git fetch xoebus",
                    "fetch xoebus"
  end

380 381 382 383
  def test_fetch_new_remote_with_options
    stub_remotes_group('xoebus', nil)
    stub_existing_fork('xoebus')

384 385 386
    assert_commands "git remote add xoebus git://github.com/xoebus/hub.git",
                    "git fetch --depth=1 --prune xoebus",
                    "fetch --depth=1 --prune xoebus"
387 388 389 390 391 392 393 394
  end

  def test_fetch_multiple_new_remotes
    stub_remotes_group('xoebus', nil)
    stub_remotes_group('rtomayko', nil)
    stub_existing_fork('xoebus')
    stub_existing_fork('rtomayko')

395 396 397 398
    assert_commands "git remote add xoebus git://github.com/xoebus/hub.git",
                    "git remote add rtomayko git://github.com/rtomayko/hub.git",
                    "git fetch --multiple xoebus rtomayko",
                    "fetch --multiple xoebus rtomayko"
399 400 401 402 403 404 405 406
  end

  def test_fetch_multiple_comma_separated_remotes
    stub_remotes_group('xoebus', nil)
    stub_remotes_group('rtomayko', nil)
    stub_existing_fork('xoebus')
    stub_existing_fork('rtomayko')

407 408 409 410
    assert_commands "git remote add xoebus git://github.com/xoebus/hub.git",
                    "git remote add rtomayko git://github.com/rtomayko/hub.git",
                    "git fetch --multiple xoebus rtomayko",
                    "fetch xoebus,rtomayko"
411 412 413 414 415 416 417 418 419 420 421 422 423 424
  end

  def test_fetch_multiple_new_remotes_with_filtering
    stub_remotes_group('xoebus', nil)
    stub_remotes_group('mygrp', 'one two')
    stub_remotes_group('typo', nil)
    stub_existing_fork('xoebus')
    stub_nonexisting_fork('typo')

    # mislav: existing remote; skipped
    # xoebus: new remote, fork exists; added
    # mygrp:  a remotes group; skipped
    # URL:    can't be a username; skipped
    # typo:   fork doesn't exist; skipped
425 426 427
    assert_commands "git remote add xoebus git://github.com/xoebus/hub.git",
                    "git fetch --multiple mislav xoebus mygrp git://example.com typo",
                    "fetch --multiple mislav xoebus mygrp git://example.com typo"
428 429
  end

430
  def test_cherry_pick
431
    assert_forwarded "cherry-pick a319d88"
432 433 434
  end

  def test_cherry_pick_url
435
    url = 'http://github.com/mislav/hub/commit/a319d88'
436
    assert_commands "git fetch mislav", "git cherry-pick a319d88", "cherry-pick #{url}"
437 438
  end

439 440
  def test_cherry_pick_url_with_fragment
    url = 'http://github.com/mislav/hub/commit/abcdef0123456789#comments'
441
    assert_commands "git fetch mislav", "git cherry-pick abcdef0123456789", "cherry-pick #{url}"
442 443
  end

444 445
  def test_cherry_pick_url_with_remote_add
    url = 'https://github.com/xoebus/hub/commit/a319d88'
446
    assert_commands "git remote add -f xoebus git://github.com/xoebus/hub.git",
447 448
                    "git cherry-pick a319d88",
                    "cherry-pick #{url}"
449 450 451 452
  end

  def test_cherry_pick_origin_url
    url = 'https://github.com/defunkt/hub/commit/a319d88'
453
    assert_commands "git fetch origin", "git cherry-pick a319d88", "cherry-pick #{url}"
454 455 456
  end

  def test_cherry_pick_github_user_notation
457
    assert_commands "git fetch mislav", "git cherry-pick 368af20", "cherry-pick mislav@368af20"
458 459 460 461
  end

  def test_cherry_pick_github_user_repo_notation
    # not supported
462
    assert_forwarded "cherry-pick mislav/hubbub@a319d88"
463 464 465
  end

  def test_cherry_pick_github_notation_too_short
466
    assert_forwarded "cherry-pick mislav@a319"
467 468 469
  end

  def test_cherry_pick_github_notation_with_remote_add
470 471 472
    assert_commands "git remote add -f xoebus git://github.com/xoebus/hub.git",
                    "git cherry-pick a319d88",
                    "cherry-pick xoebus@a319d88"
473 474
  end

475 476 477 478 479 480 481 482
  def test_am_untouched
    assert_forwarded "am some.patch"
  end

  def test_am_pull_request
    with_tmpdir('/tmp/') do
      assert_commands "curl -#LA 'hub #{Hub::Version}' https://github.com/defunkt/hub/pull/55.patch -o /tmp/55.patch",
                      "git am --signoff /tmp/55.patch -p2",
483
                      "am --signoff https://github.com/defunkt/hub/pull/55#comment_123 -p2"
484 485 486

      cmd = Hub("am https://github.com/defunkt/hub/pull/55/files").command
      assert_includes '/pull/55.patch', cmd
487 488 489
    end
  end

490 491 492 493 494 495 496
  def test_am_no_tmpdir
    with_tmpdir(nil) do
      cmd = Hub("am https://github.com/defunkt/hub/pull/55").command
      assert_includes '/tmp/55.patch', cmd
    end
  end

497 498 499 500 501 502 503 504 505 506
  def test_am_commit_url
    with_tmpdir('/tmp/') do
      url = 'https://github.com/davidbalbert/hub/commit/fdb9921'

      assert_commands "curl -#LA 'hub #{Hub::Version}' #{url}.patch -o /tmp/fdb9921.patch",
                      "git am --signoff /tmp/fdb9921.patch -p2",
                      "am --signoff #{url} -p2"
    end
  end

507 508 509 510 511 512 513 514 515 516
  def test_am_gist
    with_tmpdir('/tmp/') do
      url = 'https://gist.github.com/8da7fb575debd88c54cf'

      assert_commands "curl -#LA 'hub #{Hub::Version}' #{url}.txt -o /tmp/gist-8da7fb575debd88c54cf.txt",
                      "git am --signoff /tmp/gist-8da7fb575debd88c54cf.txt -p2",
                      "am --signoff #{url} -p2"
    end
  end

517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
  def test_apply_untouched
    assert_forwarded "apply some.patch"
  end

  def test_apply_pull_request
    with_tmpdir('/tmp/') do
      assert_commands "curl -#LA 'hub #{Hub::Version}' https://github.com/defunkt/hub/pull/55.patch -o /tmp/55.patch",
                      "git apply /tmp/55.patch -p2",
                      "apply https://github.com/defunkt/hub/pull/55 -p2"

      cmd = Hub("apply https://github.com/defunkt/hub/pull/55/files").command
      assert_includes '/pull/55.patch', cmd
    end
  end

  def test_apply_commit_url
    with_tmpdir('/tmp/') do
      url = 'https://github.com/davidbalbert/hub/commit/fdb9921'

      assert_commands "curl -#LA 'hub #{Hub::Version}' #{url}.patch -o /tmp/fdb9921.patch",
                      "git apply /tmp/fdb9921.patch -p2",
                      "apply #{url} -p2"
    end
  end

  def test_apply_gist
    with_tmpdir('/tmp/') do
      url = 'https://gist.github.com/8da7fb575debd88c54cf'

      assert_commands "curl -#LA 'hub #{Hub::Version}' #{url}.txt -o /tmp/gist-8da7fb575debd88c54cf.txt",
                      "git apply /tmp/gist-8da7fb575debd88c54cf.txt -p2",
                      "apply #{url} -p2"
    end
  end

C
Chris Wanstrath 已提交
552
  def test_init
M
Mislav Marohnić 已提交
553 554
    stub_no_remotes
    stub_no_git_repo
555
    assert_commands "git init", "git remote add origin git@github.com:tpw/hub.git", "init -g"
556 557
  end

558 559 560
  def test_init_enterprise
    stub_no_remotes
    stub_no_git_repo
561 562 563 564
    edit_hub_config do |data|
      data['git.my.org'] = [{'user'=>'myfiname'}]
    end

565 566 567 568 569
    with_host_env('git.my.org') do
      assert_commands "git init", "git remote add origin git@git.my.org:myfiname/hub.git", "init -g"
    end
  end

570 571 572 573
  def test_push_untouched
    assert_forwarded "push"
  end

574
  def test_push_two
575 576
    assert_commands "git push origin cool-feature", "git push staging cool-feature",
                    "push origin,staging cool-feature"
577 578
  end

579 580 581 582 583 584
  def test_push_current_branch
    stub_branch('refs/heads/cool-feature')
    assert_commands "git push origin cool-feature", "git push staging cool-feature",
                    "push origin,staging"
  end

C
Chris Wanstrath 已提交
585
  def test_push_more
586 587 588 589
    assert_commands "git push origin cool-feature",
                    "git push staging cool-feature",
                    "git push qa cool-feature",
                    "push origin,staging,qa cool-feature"
C
Chris Wanstrath 已提交
590
  end
C
Chris Wanstrath 已提交
591

592
  def test_create
593
    stub_no_remotes
594
    stub_nonexisting_fork('tpw')
595 596
    stub_request(:post, "https://api.github.com/user/repos").
      with(:body => { 'name' => 'hub', 'private' => false })
597

598
    expected = "remote add -f origin git@github.com:tpw/hub.git\n"
599
    expected << "created repository: tpw/hub\n"
600 601 602
    assert_equal expected, hub("create") { ENV['GIT'] = 'echo' }
  end

603 604 605
  def test_create_custom_name
    stub_no_remotes
    stub_nonexisting_fork('tpw', 'hubbub')
606 607
    stub_request(:post, "https://api.github.com/user/repos").
      with(:body => { 'name' => 'hubbub', 'private' => false })
608 609 610 611 612 613 614 615 616

    expected = "remote add -f origin git@github.com:tpw/hubbub.git\n"
    expected << "created repository: tpw/hubbub\n"
    assert_equal expected, hub("create hubbub") { ENV['GIT'] = 'echo' }
  end

  def test_create_in_organization
    stub_no_remotes
    stub_nonexisting_fork('acme', 'hubbub')
617 618
    stub_request(:post, "https://api.github.com/orgs/acme/repos").
      with(:body => { 'name' => 'hubbub', 'private' => false })
619 620 621 622 623 624

    expected = "remote add -f origin git@github.com:acme/hubbub.git\n"
    expected << "created repository: acme/hubbub\n"
    assert_equal expected, hub("create acme/hubbub") { ENV['GIT'] = 'echo' }
  end

625 626 627
  def test_create_failed
    stub_no_remotes
    stub_nonexisting_fork('tpw')
628
    stub_request(:post, "https://api.github.com/user/repos").
629 630
      to_return(:status => [401, "Your token is fail"])

631
    expected = "Error creating repository: Your token is fail (HTTP 401)\n"
632 633 634
    assert_equal expected, hub("create") { ENV['GIT'] = 'echo' }
  end

635
  def test_create_private_repository
636
    stub_no_remotes
637
    stub_nonexisting_fork('tpw')
638 639
    stub_request(:post, "https://api.github.com/user/repos").
      with(:body => { 'name' => 'hub', 'private' => true })
640

641
    expected = "remote add -f origin git@github.com:tpw/hub.git\n"
642
    expected << "created repository: tpw/hub\n"
643 644 645
    assert_equal expected, hub("create -p") { ENV['GIT'] = 'echo' }
  end

646 647 648
  def test_create_private_repository_fails
    stub_no_remotes
    stub_nonexisting_fork('tpw')
649
    stub_request(:post, "https://api.github.com/user/repos").
650 651
      to_return(:status => [422, "Unprocessable Entity"],
                :headers => {"Content-type" => "application/json"},
652
                :body => %({"message":"repository creation failed: You are over your quota."}))
653 654 655 656 657 658

    expected = "Error creating repository: Unprocessable Entity (HTTP 422)\n"
    expected << "repository creation failed: You are over your quota.\n"
    assert_equal expected, hub("create -p") { ENV['GIT'] = 'echo' }
  end

659
  def test_create_with_description_and_homepage
660
    stub_no_remotes
661
    stub_nonexisting_fork('tpw')
662 663 664
    stub_request(:post, "https://api.github.com/user/repos").with(:body => {
      'name' => 'hub', 'private' => false,
      'description' => 'toyproject', 'homepage' => 'http://example.com'
665 666
    })

667
    expected = "remote add -f origin git@github.com:tpw/hub.git\n"
668
    expected << "created repository: tpw/hub\n"
669
    assert_equal expected, hub("create -d toyproject -h http://example.com") { ENV['GIT'] = 'echo' }
670 671
  end

672 673 674 675 676
  def test_create_with_invalid_arguments
    assert_equal "invalid argument: -a\n",   hub("create -a blah")   { ENV['GIT'] = 'echo' }
    assert_equal "invalid argument: bleh\n", hub("create blah bleh") { ENV['GIT'] = 'echo' }
  end

677
  def test_create_with_existing_repository
678
    stub_no_remotes
679 680
    stub_existing_fork('tpw')

681
    expected = "tpw/hub already exists on github.com\n"
682
    expected << "remote add -f origin git@github.com:tpw/hub.git\n"
683
    expected << "set remote origin: tpw/hub\n"
684 685 686
    assert_equal expected, hub("create") { ENV['GIT'] = 'echo' }
  end

687 688 689 690 691
  def test_create_https_protocol
    stub_no_remotes
    stub_existing_fork('tpw')
    stub_https_is_preferred

692
    expected = "tpw/hub already exists on github.com\n"
693 694 695 696 697
    expected << "remote add -f origin https://github.com/tpw/hub.git\n"
    expected << "set remote origin: tpw/hub\n"
    assert_equal expected, hub("create") { ENV['GIT'] = 'echo' }
  end

698
  def test_create_outside_git_repo
699
    stub_no_git_repo
700 701
    assert_equal "'create' must be run from inside a git repository\n", hub("create")
  end
702 703

  def test_create_origin_already_exists
C
Chris Wanstrath 已提交
704
    stub_nonexisting_fork('tpw')
705 706
    stub_request(:post, "https://api.github.com/user/repos").
      with(:body => { 'name' => 'hub', 'private' => false })
C
Chris Wanstrath 已提交
707 708

    expected = "remote -v\ncreated repository: tpw/hub\n"
709 710
    assert_equal expected, hub("create") { ENV['GIT'] = 'echo' }
  end
C
Chris Wanstrath 已提交
711

712
  def test_fork
C
Chris Wanstrath 已提交
713
    stub_nonexisting_fork('tpw')
714
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/forks").
715
      with { |req| req.headers['Content-Length'] == 0 }
C
Chris Wanstrath 已提交
716

C
Chris Wanstrath 已提交
717
    expected = "remote add -f tpw git@github.com:tpw/hub.git\n"
718
    expected << "new remote: tpw\n"
719
    assert_output expected, "fork"
720 721
  end

722 723 724
  def test_fork_https_protocol
    stub_https_is_preferred
    stub_nonexisting_fork('tpw')
725
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/forks")
726 727 728 729 730 731

    expected = "remote add -f tpw https://github.com/tpw/hub.git\n"
    expected << "new remote: tpw\n"
    assert_equal expected, hub("fork") { ENV['GIT'] = 'echo' }
  end

732 733 734 735 736 737
  def test_fork_not_in_repo
    stub_no_git_repo
    expected = "fatal: Not a git repository\n"
    assert_output expected, "fork"
  end

738 739 740
  def test_fork_enterprise
    stub_hub_host('git.my.org')
    stub_repo_url('git@git.my.org:defunkt/hub.git')
741 742 743
    edit_hub_config do |data|
      data['git.my.org'] = [{'user'=>'myfiname', 'oauth_token' => 'FITOKEN'}]
    end
744

745
    stub_request(:get, "https://git.my.org/repos/myfiname/hub").
746
      to_return(:status => 404)
747 748
    stub_request(:post, "https://git.my.org/repos/defunkt/hub/forks").
      with(:headers => {"Authorization" => "token FITOKEN"})
749 750 751 752 753 754

    expected = "remote add -f myfiname git@git.my.org:myfiname/hub.git\n"
    expected << "new remote: myfiname\n"
    assert_output expected, "fork"
  end

755 756
  def test_fork_failed
    stub_nonexisting_fork('tpw')
757
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/forks").
758 759
      to_return(:status => [500, "Your fork is fail"])

760
    expected = "Error creating fork: Your fork is fail (HTTP 500)\n"
761 762 763
    assert_equal expected, hub("fork") { ENV['GIT'] = 'echo' }
  end

764
  def test_fork_no_remote
765
    stub_nonexisting_fork('tpw')
766
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/forks")
C
Chris Wanstrath 已提交
767

768 769 770 771
    assert_equal "", hub("fork --no-remote") { ENV['GIT'] = 'echo' }
  end

  def test_fork_already_exists
772
    stub_existing_fork('tpw')
C
Chris Wanstrath 已提交
773

774
    expected = "Error creating fork: tpw/hub already exists on github.com\n"
775 776 777
    assert_equal expected, hub("fork") { ENV['GIT'] = 'echo' }
  end

778
  def test_pullrequest
M
Mislav Marohnić 已提交
779 780 781
    expected = "Aborted: head branch is the same as base (\"master\")\n" <<
      "(use `-h <branch>` to specify an explicit pull request head)\n"
    assert_output expected, "pull-request hereyougo"
782 783
  end

M
Mislav Marohnić 已提交
784 785
  def test_pullrequest_with_unpushed_commits
    stub_tracking('master', 'mislav', 'master')
786
    stub_command_output "rev-list --cherry-pick --right-only --no-merges mislav/master...", "+abcd1234\n+bcde2345"
787

M
Mislav Marohnić 已提交
788
    expected = "Aborted: 2 commits are not yet pushed to mislav/master\n" <<
789
      "(use `-f` to force submit a pull request anyway)\n"
790 791 792 793 794 795
    assert_output expected, "pull-request hereyougo"
  end

  def test_pullrequest_from_branch
    stub_branch('refs/heads/feature')
    stub_tracking_nothing('feature')
M
Mislav Marohnić 已提交
796

797 798 799
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/pulls").
      with(:body => { 'base' => "master", 'head' => "tpw:feature", 'title' => "hereyougo" }) { |req|
        req.headers['Content-Length'] == 63
800
      }.to_return(:body => mock_pullreq_response(1))
801 802

    expected = "https://github.com/defunkt/hub/pull/1\n"
803
    assert_output expected, "pull-request hereyougo -f"
804 805 806 807
  end

  def test_pullrequest_from_tracking_branch
    stub_branch('refs/heads/feature')
M
Mislav Marohnić 已提交
808
    stub_tracking('feature', 'mislav', 'yay-feature')
809

810 811
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/pulls").
      with(:body => {'base' => "master", 'head' => "mislav:yay-feature", 'title' => "hereyougo" }).
812 813 814
      to_return(:body => mock_pullreq_response(1))

    expected = "https://github.com/defunkt/hub/pull/1\n"
815
    assert_output expected, "pull-request hereyougo -f"
816 817
  end

818 819 820 821
  def test_pullrequest_from_branch_tracking_local
    stub_branch('refs/heads/feature')
    stub_tracking('feature', 'refs/heads/master')

822 823
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/pulls").
      with(:body => {'base' => "master", 'head' => "tpw:feature", 'title' => "hereyougo" }).
824 825 826 827 828 829
      to_return(:body => mock_pullreq_response(1))

    expected = "https://github.com/defunkt/hub/pull/1\n"
    assert_output expected, "pull-request hereyougo -f"
  end

830 831 832 833 834 835 836 837 838
  def test_pullrequest_invalid_remote
    stub_repo_url('gh:singingwolfboy/sekrit.git')
    stub_branch('refs/heads/feature')
    stub_tracking('feature', 'origin', 'feature')

    expected = "Aborted: the origin remote doesn't point to a GitHub repository.\n"
    assert_output expected, "pull-request hereyougo"
  end

839 840 841 842 843
  def test_pullrequest_enterprise_no_tracking
    stub_hub_host('git.my.org')
    stub_repo_url('git@git.my.org:defunkt/hub.git')
    stub_branch('refs/heads/feature')
    stub_tracking_nothing('feature')
844
    stub_command_output "rev-list --cherry-pick --right-only --no-merges origin/feature...", nil
845 846 847
    edit_hub_config do |data|
      data['git.my.org'] = [{'user'=>'myfiname', 'oauth_token' => 'FITOKEN'}]
    end
848

849 850
    stub_request(:post, "https://git.my.org/repos/defunkt/hub/pulls").
      with(:body => {'base' => "master", 'head' => "myfiname:feature", 'title' => "hereyougo" }).
851 852 853 854 855 856
      to_return(:body => mock_pullreq_response(1, 'defunkt/hub', 'git.my.org'))

    expected = "https://git.my.org/defunkt/hub/pull/1\n"
    assert_output expected, "pull-request hereyougo -f"
  end

857
  def test_pullrequest_explicit_head
858 859
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/pulls").
      with(:body => {'base' => "master", 'head' => "tpw:yay-feature", 'title' => "hereyougo" }).
860 861 862
      to_return(:body => mock_pullreq_response(1))

    expected = "https://github.com/defunkt/hub/pull/1\n"
863
    assert_output expected, "pull-request hereyougo -h yay-feature -f"
864 865 866
  end

  def test_pullrequest_explicit_head_with_owner
867 868
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/pulls").
      with(:body => {'base' => "master", 'head' => "mojombo:feature", 'title' => "hereyougo" }).
869 870 871
      to_return(:body => mock_pullreq_response(1))

    expected = "https://github.com/defunkt/hub/pull/1\n"
872
    assert_output expected, "pull-request hereyougo -h mojombo:feature -f"
873 874 875
  end

  def test_pullrequest_explicit_base
876 877
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/pulls").
      with(:body => {'base' => "feature", 'head' => "defunkt:master", 'title' => "hereyougo" }).
878 879 880
      to_return(:body => mock_pullreq_response(1))

    expected = "https://github.com/defunkt/hub/pull/1\n"
881
    assert_output expected, "pull-request hereyougo -b feature -f"
882 883 884
  end

  def test_pullrequest_explicit_base_with_owner
885 886 887
    stub_request(:post, "https://api.github.com/repos/mojombo/hub/pulls").
      with(:body => {'base' => "feature", 'head' => "defunkt:master", 'title' => "hereyougo" }).
      to_return(:body => mock_pullreq_response(1, 'mojombo/hub'))
888

889
    expected = "https://github.com/mojombo/hub/pull/1\n"
890
    assert_output expected, "pull-request hereyougo -b mojombo:feature -f"
891 892
  end

893
  def test_pullrequest_explicit_base_with_repo
894 895 896
    stub_request(:post, "https://api.github.com/repos/mojombo/hubbub/pulls").
      with(:body => {'base' => "feature", 'head' => "defunkt:master", 'title' => "hereyougo" }).
      to_return(:body => mock_pullreq_response(1, 'mojombo/hubbub'))
897

898
    expected = "https://github.com/mojombo/hubbub/pull/1\n"
899
    assert_output expected, "pull-request hereyougo -b mojombo/hubbub:feature -f"
900 901 902
  end

  def test_pullrequest_existing_issue
M
Mislav Marohnić 已提交
903 904
    stub_branch('refs/heads/myfix')
    stub_tracking('myfix', 'mislav', 'awesomefix')
905
    stub_command_output "rev-list --cherry-pick --right-only --no-merges mislav/awesomefix...", nil
M
Mislav Marohnić 已提交
906

907 908
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/pulls").
      with(:body => {'base' => "master", 'head' => "mislav:awesomefix", 'issue' => '92' }).
909 910 911
      to_return(:body => mock_pullreq_response(92))

    expected = "https://github.com/defunkt/hub/pull/92\n"
M
Mislav Marohnić 已提交
912
    assert_output expected, "pull-request -i 92"
913 914
  end

915
  def test_pullrequest_existing_issue_url
M
Mislav Marohnić 已提交
916 917
    stub_branch('refs/heads/myfix')
    stub_tracking('myfix', 'mislav', 'awesomefix')
918
    stub_command_output "rev-list --cherry-pick --right-only --no-merges mislav/awesomefix...", nil
M
Mislav Marohnić 已提交
919

920 921
    stub_request(:post, "https://api.github.com/repos/mojombo/hub/pulls").
      with(:body => {'base' => "master", 'head' => "mislav:awesomefix", 'issue' => '92' }).
922 923 924
      to_return(:body => mock_pullreq_response(92, 'mojombo/hub'))

    expected = "https://github.com/mojombo/hub/pull/92\n"
M
Mislav Marohnić 已提交
925
    assert_output expected, "pull-request https://github.com/mojombo/hub/issues/92#comment_4"
926 927
  end

928
  def test_pullrequest_fails
929
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/pulls").
930 931
      to_return(:status => [422, "Unprocessable Entity"],
                :headers => {"Content-type" => "application/json"},
932
                :body => %({"message":["oh no!\\nit failed."]}))
933 934 935 936 937 938

    expected = "Error creating pull request: Unprocessable Entity (HTTP 422)\n"
    expected << "oh no!\nit failed.\n"
    assert_output expected, "pull-request hereyougo -b feature -f"
  end

939 940 941 942 943
  def test_checkout_no_changes
    assert_forwarded "checkout master"
  end

  def test_checkout_pullrequest
944
    stub_request(:get, "https://api.github.com/repos/defunkt/hub/pulls/73").
945 946 947
      to_return(:body => mock_pull_response('blueyed:feature'))

    assert_commands 'git remote add -f -t feature blueyed git://github.com/blueyed/hub.git',
M
Mislav Marohnić 已提交
948 949
      'git checkout -f --track -B blueyed-feature blueyed/feature -q',
      "checkout -f https://github.com/defunkt/hub/pull/73/files -q"
950 951
  end

952
  def test_checkout_private_pullrequest
953
    stub_request(:get, "https://api.github.com/repos/defunkt/hub/pulls/73").
954 955 956
      to_return(:body => mock_pull_response('blueyed:feature', :private))

    assert_commands 'git remote add -f -t feature blueyed git@github.com:blueyed/hub.git',
M
Mislav Marohnić 已提交
957
      'git checkout --track -B blueyed-feature blueyed/feature',
958 959 960
      "checkout https://github.com/defunkt/hub/pull/73/files"
  end

961
  def test_checkout_pullrequest_custom_branch
962
    stub_request(:get, "https://api.github.com/repos/defunkt/hub/pulls/73").
963 964 965
      to_return(:body => mock_pull_response('blueyed:feature'))

    assert_commands 'git remote add -f -t feature blueyed git://github.com/blueyed/hub.git',
M
Mislav Marohnić 已提交
966
      'git checkout --track -B review blueyed/feature',
967 968 969 970 971 972
      "checkout https://github.com/defunkt/hub/pull/73/files review"
  end

  def test_checkout_pullrequest_existing_remote
    stub_command_output 'remote', "origin\nblueyed"

973
    stub_request(:get, "https://api.github.com/repos/defunkt/hub/pulls/73").
974 975 976 977
      to_return(:body => mock_pull_response('blueyed:feature'))

    assert_commands 'git remote set-branches --add blueyed feature',
      'git fetch blueyed +refs/heads/feature:refs/remotes/blueyed/feature',
M
Mislav Marohnić 已提交
978
      'git checkout --track -B blueyed-feature blueyed/feature',
979 980 981
      "checkout https://github.com/defunkt/hub/pull/73/files"
  end

C
Chris Wanstrath 已提交
982
  def test_version
983
    out = hub('--version')
984
    assert_includes "git version 1.7.0.4", out
C
Chris Wanstrath 已提交
985
    assert_includes "hub version #{Hub::Version}", out
C
Chris Wanstrath 已提交
986
  end
C
Chris Wanstrath 已提交
987

988 989 990 991 992 993 994
  def test_exec_path
    out = hub('--exec-path')
    assert_equal "/usr/lib/git-core\n", out
  end

  def test_exec_path_arg
    out = hub('--exec-path=/home/wombat/share/my-l33t-git-core')
995
    assert_equal improved_help_text, out
996 997 998 999 1000 1001 1002
  end

  def test_html_path
    out = hub('--html-path')
    assert_equal "/usr/share/doc/git-doc\n", out
  end

C
Chris Wanstrath 已提交
1003
  def test_help
1004
    assert_equal improved_help_text, hub("help")
C
Chris Wanstrath 已提交
1005 1006 1007
  end

  def test_help_by_default
1008
    assert_equal improved_help_text, hub("")
C
Chris Wanstrath 已提交
1009
  end
C
Chris Wanstrath 已提交
1010

S
Stephen Celis 已提交
1011
  def test_help_with_pager
1012
    assert_equal improved_help_text, hub("-p")
S
Stephen Celis 已提交
1013 1014
  end

C
Chris Wanstrath 已提交
1015 1016 1017
  def test_help_hub
    help_manpage = hub("help hub")
    assert_includes "git + hub = github", help_manpage
1018
    assert_includes "Hub will prompt for GitHub username & password", help_manpage
C
Chris Wanstrath 已提交
1019 1020
  end

1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
  def test_help_flag_on_command
    help_manpage = hub("browse --help")
    assert_includes "git + hub = github", help_manpage
    assert_includes "git browse", help_manpage
  end

  def test_help_short_flag_on_command
    usage_help = hub("create -h")
    expected = "Usage: git create [NAME] [-p] [-d DESCRIPTION] [-h HOMEPAGE]\n"
    assert_equal expected, usage_help

    usage_help = hub("pull-request -h")
    expected = "Usage: git pull-request [-f] [TITLE|-i ISSUE] [-b BASE] [-h HEAD]\n"
    assert_equal expected, usage_help
  end

C
Chris Wanstrath 已提交
1037
  def test_help_hub_no_groff
1038 1039
    stub_available_commands()
    assert_equal "** Can't find groff(1)\n", hub("help hub")
C
Chris Wanstrath 已提交
1040
  end
1041

1042
  def test_hub_standalone
1043
    assert_includes 'This file is generated code', hub("hub standalone")
1044 1045
  end

C
Chris Wanstrath 已提交
1046 1047
  def test_hub_compare
    assert_command "compare refactor",
1048
      "open https://github.com/defunkt/hub/compare/refactor"
1049
  end
C
Chris Wanstrath 已提交
1050

1051 1052 1053 1054
  def test_hub_compare_nothing
    expected = "Usage: hub compare [USER] [<START>...]<END>\n"
    assert_equal expected, hub("compare")
  end
C
Chris Wanstrath 已提交
1055

1056 1057 1058 1059 1060 1061 1062 1063
  def test_hub_compare_tracking_nothing
    stub_tracking_nothing
    expected = "Usage: hub compare [USER] [<START>...]<END>\n"
    assert_equal expected, hub("compare")
  end

  def test_hub_compare_tracking_branch
    stub_branch('refs/heads/feature')
1064
    stub_tracking('feature', 'mislav', 'experimental')
1065 1066

    assert_command "compare",
1067
      "open https://github.com/mislav/hub/compare/experimental"
1068 1069
  end

1070
  def test_hub_compare_range
C
Chris Wanstrath 已提交
1071
    assert_command "compare 1.0...fix",
1072
      "open https://github.com/defunkt/hub/compare/1.0...fix"
1073
  end
C
Chris Wanstrath 已提交
1074

1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089
  def test_hub_compare_range_fixes_two_dots_for_tags
    assert_command "compare 1.0..fix",
      "open https://github.com/defunkt/hub/compare/1.0...fix"
  end

  def test_hub_compare_range_fixes_two_dots_for_shas
    assert_command "compare 1234abc..3456cde",
      "open https://github.com/defunkt/hub/compare/1234abc...3456cde"
  end

  def test_hub_compare_range_ignores_two_dots_for_complex_ranges
    assert_command "compare @{a..b}..@{c..d}",
      "open https://github.com/defunkt/hub/compare/@{a..b}..@{c..d}"
  end

1090 1091 1092 1093 1094 1095
  def test_hub_compare_on_wiki
    stub_repo_url 'git://github.com/defunkt/hub.wiki.git'
    assert_command "compare 1.0...fix",
      "open https://github.com/defunkt/hub/wiki/_compare/1.0...fix"
  end

1096
  def test_hub_compare_fork
C
Chris Wanstrath 已提交
1097
    assert_command "compare myfork feature",
1098
      "open https://github.com/myfork/hub/compare/feature"
1099 1100 1101 1102
  end

  def test_hub_compare_url
    assert_command "compare -u 1.0...1.1",
1103
      "echo https://github.com/defunkt/hub/compare/1.0...1.1"
1104 1105 1106
  end

  def test_hub_browse
1107
    assert_command "browse mojombo/bert", "open https://github.com/mojombo/bert"
1108 1109
  end

1110 1111 1112 1113
  def test_hub_browse_commit
    assert_command "browse mojombo/bert commit/5d5582", "open https://github.com/mojombo/bert/commit/5d5582"
  end

1114 1115
  def test_hub_browse_tracking_nothing
    stub_tracking_nothing
1116
    assert_command "browse mojombo/bert", "open https://github.com/mojombo/bert"
1117 1118
  end

1119
  def test_hub_browse_url
1120
    assert_command "browse -u mojombo/bert", "echo https://github.com/mojombo/bert"
1121 1122
  end

1123
  def test_hub_browse_self
1124
    assert_command "browse resque", "open https://github.com/tpw/resque"
1125 1126
  end

1127 1128
  def test_hub_browse_subpage
    assert_command "browse resque commits",
1129
      "open https://github.com/tpw/resque/commits/master"
1130
    assert_command "browse resque issues",
1131
      "open https://github.com/tpw/resque/issues"
1132
    assert_command "browse resque wiki",
1133
      "open https://github.com/tpw/resque/wiki"
1134 1135 1136 1137
  end

  def test_hub_browse_on_branch
    stub_branch('refs/heads/feature')
1138
    stub_tracking('feature', 'mislav', 'experimental')
1139

1140
    assert_command "browse resque", "open https://github.com/tpw/resque"
1141
    assert_command "browse resque commits",
1142
      "open https://github.com/tpw/resque/commits/master"
1143 1144

    assert_command "browse",
1145
      "open https://github.com/mislav/hub/tree/experimental"
1146
    assert_command "browse -- tree",
1147
      "open https://github.com/mislav/hub/tree/experimental"
1148
    assert_command "browse -- commits",
1149
      "open https://github.com/mislav/hub/commits/experimental"
1150
  end
1151

1152 1153 1154 1155 1156 1157 1158 1159
  def test_hub_browse_on_complex_branch
    stub_branch('refs/heads/feature/foo')
    stub_tracking('feature/foo', 'mislav', 'feature/bar')

    assert_command 'browse',
      'open https://github.com/mislav/hub/tree/feature/bar'
  end

1160 1161 1162 1163 1164
  def test_hub_browse_no_branch
    stub_branch(nil)
    assert_command 'browse', 'open https://github.com/defunkt/hub'
  end

1165
  def test_hub_browse_current
1166 1167
    assert_command "browse", "open https://github.com/defunkt/hub"
    assert_command "browse --", "open https://github.com/defunkt/hub"
1168 1169
  end

1170 1171 1172 1173 1174
  def test_hub_browse_current_https_uri
    stub_repo_url "https://github.com/defunkt/hub"
    assert_command "browse", "open https://github.com/defunkt/hub"
  end

1175 1176 1177 1178
  def test_hub_browse_commit_from_current
    assert_command "browse -- commit/6616e4", "open https://github.com/defunkt/hub/commit/6616e4"
  end

1179 1180 1181 1182 1183 1184 1185
  def test_hub_browse_no_tracking
    stub_tracking_nothing
    assert_command "browse", "open https://github.com/defunkt/hub"
  end

  def test_hub_browse_no_tracking_on_branch
    stub_branch('refs/heads/feature')
1186
    stub_tracking_nothing('feature')
1187 1188 1189
    assert_command "browse", "open https://github.com/defunkt/hub"
  end

1190 1191 1192 1193 1194 1195 1196 1197 1198
  def test_hub_browse_current_wiki
    stub_repo_url 'git://github.com/defunkt/hub.wiki.git'

    assert_command "browse", "open https://github.com/defunkt/hub/wiki"
    assert_command "browse -- wiki", "open https://github.com/defunkt/hub/wiki"
    assert_command "browse -- commits", "open https://github.com/defunkt/hub/wiki/_history"
    assert_command "browse -- pages", "open https://github.com/defunkt/hub/wiki/_pages"
  end

1199 1200
  def test_hub_browse_current_subpage
    assert_command "browse -- network",
1201
      "open https://github.com/defunkt/hub/network"
1202
    assert_command "browse -- anything/everything",
1203
      "open https://github.com/defunkt/hub/anything/everything"
1204 1205
  end

1206 1207 1208 1209
  def test_hub_browse_deprecated_private
    with_browser_env('echo') do
      assert_includes "Warning: the `-p` flag has no effect anymore\n", hub("browse -p defunkt/hub")
    end
1210 1211
  end

1212 1213 1214
  def test_hub_browse_no_repo
    stub_repo_url(nil)
    assert_equal "Usage: hub browse [<USER>/]<REPOSITORY>\n", hub("browse")
1215
  end
1216

1217 1218 1219 1220 1221 1222 1223
  def test_hub_browse_ssh_alias
    with_ssh_config do
      stub_repo_url "gh:singingwolfboy/sekrit.git"
      assert_command "browse", "open https://github.com/singingwolfboy/sekrit"
    end
  end

1224 1225 1226 1227 1228 1229 1230 1231 1232
  def test_custom_browser
    with_browser_env("custom") do
      assert_browser("custom")
    end
  end

  def test_linux_browser
    stub_available_commands "open", "xdg-open", "cygstart"
    with_browser_env(nil) do
1233
      with_host_os("i686-linux") do
1234 1235 1236 1237 1238 1239 1240 1241
        assert_browser("xdg-open")
      end
    end
  end

  def test_cygwin_browser
    stub_available_commands "open", "cygstart"
    with_browser_env(nil) do
1242
      with_host_os("i686-linux") do
1243 1244 1245 1246 1247 1248 1249 1250 1251
        assert_browser("cygstart")
      end
    end
  end

  def test_no_browser
    stub_available_commands()
    expected = "Please set $BROWSER to a web launcher to use this command.\n"
    with_browser_env(nil) do
1252
      with_host_os("i686-linux") do
1253 1254 1255 1256 1257
        assert_equal expected, hub("browse")
      end
    end
  end

1258
  def test_context_method_doesnt_hijack_git_command
1259
    assert_forwarded 'remotes'
1260 1261
  end

1262 1263 1264 1265 1266
  def test_not_choking_on_ruby_methods
    assert_forwarded 'id'
    assert_forwarded 'name'
  end

1267 1268
  def test_multiple_remote_urls
    stub_repo_url("git://example.com/other.git\ngit://github.com/my/repo.git")
1269
    assert_command "browse", "open https://github.com/my/repo"
1270 1271
  end

1272 1273 1274
  def test_global_flags_preserved
    cmd = '--no-pager --bare -c core.awesome=true -c name=value --git-dir=/srv/www perform'
    assert_command cmd, 'git --bare -c core.awesome=true -c name=value --git-dir=/srv/www --no-pager perform'
1275
    assert_equal %w[git --bare -c core.awesome=true -c name=value --git-dir=/srv/www], git_reader.executable
1276 1277
  end

1278
  private
1279

M
Mislav Marohnić 已提交
1280 1281
    def stub_repo_url(value, remote_name = 'origin')
      stub_config_value "remote.#{remote_name}.url", value, '--get-all'
1282 1283 1284
    end

    def stub_branch(value)
1285
      stub_command_output 'symbolic-ref -q HEAD', value
1286 1287
    end

1288
    def stub_tracking(from, upstream, remote_branch = nil)
1289
      stub_command_output "rev-parse --symbolic-full-name #{from}@{upstream}",
1290
        remote_branch ? "refs/remotes/#{upstream}/#{remote_branch}" : upstream
1291 1292
    end

1293
    def stub_tracking_nothing(from = 'master')
1294
      stub_tracking(from, nil)
1295 1296
    end

1297
    def stub_remotes_group(name, value)
1298
      stub_config_value "remotes.#{name}", value
1299 1300
    end

1301
    def stub_no_remotes
1302
      stub_command_output 'remote', nil
1303 1304 1305
    end

    def stub_no_git_repo
1306
      stub_command_output 'rev-parse -q --git-dir', nil
1307 1308
    end

M
Mislav Marohnić 已提交
1309
    def stub_alias(name, value)
1310
      stub_config_value "alias.#{name}", value
M
Mislav Marohnić 已提交
1311 1312
    end

1313 1314
    def stub_existing_fork(user, repo = 'hub')
      stub_fork(user, repo, 200)
1315 1316
    end

1317 1318
    def stub_nonexisting_fork(user, repo = 'hub')
      stub_fork(user, repo, 404)
1319 1320
    end

1321
    def stub_fork(user, repo, status)
1322
      stub_request(:get, "https://api.github.com/repos/#{user}/#{repo}").
1323 1324 1325
        to_return(:status => status)
    end

1326 1327 1328 1329
    def stub_available_commands(*names)
      COMMANDS.replace names
    end

1330
    def stub_https_is_preferred
1331
      stub_config_value 'hub.protocol', 'https'
1332 1333
    end

1334 1335 1336 1337
    def stub_hub_host(names)
      stub_config_value "hub.host", Array(names).join("\n"), '--get-all'
    end

1338 1339 1340 1341 1342 1343 1344
    def with_browser_env(value)
      browser, ENV['BROWSER'] = ENV['BROWSER'], value
      yield
    ensure
      ENV['BROWSER'] = browser
    end

1345 1346 1347 1348 1349 1350 1351
    def with_tmpdir(value)
      dir, ENV['TMPDIR'] = ENV['TMPDIR'], value
      yield
    ensure
      ENV['TMPDIR'] = dir
    end

1352 1353 1354 1355 1356 1357 1358
    def with_host_env(value)
      host, ENV['GITHUB_HOST'] = ENV['GITHUB_HOST'], value
      yield
    ensure
      ENV['GITHUB_HOST'] = host
    end

1359
    def assert_browser(browser)
1360
      assert_command "browse", "#{browser} https://github.com/defunkt/hub"
1361 1362
    end

1363 1364 1365 1366 1367 1368 1369 1370
    def with_host_os(value)
      host_os = RbConfig::CONFIG['host_os']
      RbConfig::CONFIG['host_os'] = value
      begin
        yield
      ensure
        RbConfig::CONFIG['host_os'] = host_os
      end
1371 1372
    end

1373
    def mock_pullreq_response(id, name_with_owner = 'defunkt/hub', host = 'github.com')
1374
      Hub::JSON.generate :html_url => "https://#{host}/#{name_with_owner}/pull/#{id}"
1375 1376
    end

1377
    def mock_pull_response(label, priv = false)
1378 1379 1380 1381
      Hub::JSON.generate :head => {
        :label => label,
        :repo => {:private => !!priv}
      }
1382 1383
    end

1384 1385 1386 1387
    def improved_help_text
      Hub::Commands.send :improved_help_text
    end

1388 1389
    def with_ssh_config
      config_file = File.expand_path '../ssh_config', __FILE__
1390
      Hub::SshConfig::CONFIG_FILES.replace [config_file]
1391 1392 1393
      yield
    end

C
Chris Wanstrath 已提交
1394
end