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

7 8 9 10 11 12
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 已提交
13
class HubTest < Test::Unit::TestCase
14 15
  extend Forwardable

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

22 23
  COMMANDS = []

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

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

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

40 41 42
    @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ć 已提交
43
      end
44 45 46 47 48 49
    end

    Hub::Commands.instance_variable_set :@git_reader, @git_reader
    Hub::Commands.instance_variable_set :@local_repo, nil

    @git_reader.stub! \
50
      'remote' => "mislav\norigin",
51
      'symbolic-ref -q HEAD' => 'refs/heads/master',
52 53
      'config --get github.user'   => 'tpw',
      'config --get github.token'  => 'abc123',
54 55
      'config --get-all remote.origin.url' => 'git://github.com/defunkt/hub.git',
      'config --get-all remote.mislav.url' => 'git://github.com/mislav/hub.git',
56
      'rev-parse --symbolic-full-name master@{upstream}' => 'refs/remotes/origin/master',
57 58
      'config --get --bool hub.http-clone' => 'false',
      'config --get hub.protocol' => nil,
59
      'config --get-all hub.host' => nil,
60
      'rev-parse -q --git-dir' => '.git'
61 62
  end

C
Chris Wanstrath 已提交
63
  def test_private_clone
64
    stub_no_git_repo
65 66
    input   = "clone -p rtomayko/ronn"
    command = "git clone git@github.com:rtomayko/ronn.git"
C
Chris Wanstrath 已提交
67
    assert_command input, command
C
Chris Wanstrath 已提交
68 69
  end

70
  def test_private_clone_noop
71
    stub_no_git_repo
72 73 74 75 76
    input   = "--noop clone -p rtomayko/ronn"
    command = "git clone git@github.com:rtomayko/ronn.git\n"
    assert_output command, hub(input)
  end

77
  def test_https_clone
78
    stub_no_git_repo
79 80 81 82 83 84
    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 已提交
85
  def test_public_clone
86
    stub_no_git_repo
87 88
    input   = "clone 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_your_private_clone
93
    stub_no_git_repo
94 95 96 97 98
    input   = "clone -p resque"
    command = "git clone git@github.com:tpw/resque.git"
    assert_command input, command
  end

99
  def test_your_clone_is_always_private
100
    stub_no_git_repo
101
    input   = "clone resque"
102
    command = "git clone git@github.com:tpw/resque.git"
103 104 105
    assert_command input, command
  end

106
  def test_clone_repo_with_period
107
    stub_no_git_repo
108 109 110 111 112
    input   = "clone hookio/hook.js"
    command = "git clone git://github.com/hookio/hook.js.git"
    assert_command input, command
  end

113
  def test_clone_with_arguments
114
    stub_no_git_repo
115
    input   = "clone --bare -o master resque"
116
    command = "git clone --bare -o master git@github.com:tpw/resque.git"
117 118 119
    assert_command input, command
  end

120
  def test_clone_with_arguments_and_destination
121
    stub_no_git_repo
122 123 124
    assert_forwarded "clone --template=one/two git://github.com/tpw/resque.git --origin master resquetastic"
  end

125
  def test_your_private_clone_fails_without_config
126
    stub_no_git_repo
127
    out = hub("clone -p mustache") do
128
      stub_github_user(nil)
129 130
    end

131
    assert_equal "** No GitHub user set. See http://help.github.com/set-your-user-name-email-and-github-token/\n", out
132 133 134
  end

  def test_your_public_clone_fails_without_config
135
    stub_no_git_repo
136
    out = hub("clone mustache") do
137
      stub_github_user(nil)
138 139
    end

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

143
  def test_private_clone_left_alone
144
    stub_no_git_repo
145
    assert_forwarded "clone git@github.com:rtomayko/ronn.git"
146 147 148
  end

  def test_public_clone_left_alone
149
    stub_no_git_repo
150
    assert_forwarded "clone git://github.com/rtomayko/ronn.git"
151
  end
C
Chris Wanstrath 已提交
152 153

  def test_normal_public_clone_with_path
154
    stub_no_git_repo
155
    assert_forwarded "clone git://github.com/rtomayko/ronn.git ronn-dev"
C
Chris Wanstrath 已提交
156
  end
157 158

  def test_normal_clone_from_path
159
    stub_no_git_repo
160
    assert_forwarded "clone ./test"
161
  end
162

163 164 165 166 167 168 169 170 171 172
  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

173
  def test_clone_with_host_alias
174
    stub_no_git_repo
175 176 177
    assert_forwarded "clone server:git/repo.git"
  end

178
  def test_enterprise_clone
179
    stub_no_git_repo
180 181 182 183 184 185 186
    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ć 已提交
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
  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

206 207 208 209 210 211
  def test_remote_origin
    input   = "remote add origin"
    command = "git remote add origin git://github.com/tpw/hub.git"
    assert_command input, command
  end

212 213 214 215 216 217
  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

218 219 220 221 222 223
  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

224 225 226 227 228 229
  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"
230 231
  end

232
  def test_remote_from_rel_path
233
    assert_forwarded "remote add origin ./path"
234 235 236
  end

  def test_remote_from_abs_path
237
    assert_forwarded "remote add origin /path"
238 239
  end

240
  def test_remote_with_host_alias
241 242 243
    assert_forwarded "remote add origin server:/git/repo.git"
  end

244 245 246 247
  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 已提交
248 249
  end

S
Stephen Celis 已提交
250 251
  def test_public_submodule
    input   = "submodule add wycats/bundler vendor/bundler"
J
Justin Ridgewell 已提交
252 253
    command = "git submodule add git://github.com/wycats/bundler.git vendor/bundler"
    assert_command input, command
S
Stephen Celis 已提交
254 255 256 257
  end

  def test_private_submodule
    input   = "submodule add -p grit vendor/grit"
J
Justin Ridgewell 已提交
258 259 260 261 262 263 264 265
    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 已提交
266 267 268 269 270
  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 已提交
271
    assert_command input, command
S
Stephen Celis 已提交
272 273
  end

C
Chris Wanstrath 已提交
274
  def test_private_remote
275
    input   = "remote add -p rtomayko"
C
Chris Wanstrath 已提交
276 277
    command = "git remote add rtomayko git@github.com:rtomayko/hub.git"
    assert_command input, command
C
Chris Wanstrath 已提交
278 279
  end

280 281 282 283 284 285 286
  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 已提交
287
  def test_public_remote
288
    input   = "remote add rtomayko"
C
Chris Wanstrath 已提交
289 290
    command = "git remote add rtomayko git://github.com/rtomayko/hub.git"
    assert_command input, command
C
Chris Wanstrath 已提交
291 292
  end

C
Chris Wanstrath 已提交
293 294 295 296 297 298
  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

299 300 301 302 303 304
  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

305 306 307 308 309 310
  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 已提交
311
  def test_private_remote_with_repo
312 313
    input   = "remote add -p jashkenas/coffee-script"
    command = "git remote add jashkenas git@github.com:jashkenas/coffee-script.git"
C
Chris Wanstrath 已提交
314 315 316 317
    assert_command input, command
  end

  def test_public_remote_with_repo
318 319
    input   = "remote add jashkenas/coffee-script"
    command = "git remote add jashkenas git://github.com/jashkenas/coffee-script.git"
320 321 322 323
    assert_command input, command
  end

  def test_public_remote_f_with_repo
324 325
    input   = "remote add -f jashkenas/coffee-script"
    command = "git remote add -f jashkenas git://github.com/jashkenas/coffee-script.git"
C
Chris Wanstrath 已提交
326 327 328
    assert_command input, command
  end

329
  def test_named_private_remote_with_repo
330 331
    input   = "remote add -p origin jashkenas/coffee-script"
    command = "git remote add origin git@github.com:jashkenas/coffee-script.git"
332 333 334
    assert_command input, command
  end

335
  def test_fetch_existing_remote
336
    assert_forwarded "fetch mislav"
337 338 339 340 341 342
  end

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

343 344 345
    assert_commands "git remote add xoebus git://github.com/xoebus/hub.git",
                    "git fetch xoebus",
                    "fetch xoebus"
346 347
  end

348 349 350 351 352 353 354 355 356 357
  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

358 359 360 361 362 363 364 365 366 367 368 369 370
  def test_fetch_no_auth
    stub_github_user nil
    stub_github_token nil
    stub_remotes_group('xoebus', nil)
    # stub_existing_fork('xoebus')
    stub_request(:get, "https://github.com/api/v2/yaml/repos/show/xoebus/hub").
      to_return(:status => 200)

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

371 372 373 374
  def test_fetch_new_remote_with_options
    stub_remotes_group('xoebus', nil)
    stub_existing_fork('xoebus')

375 376 377
    assert_commands "git remote add xoebus git://github.com/xoebus/hub.git",
                    "git fetch --depth=1 --prune xoebus",
                    "fetch --depth=1 --prune xoebus"
378 379 380 381 382 383 384 385
  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')

386 387 388 389
    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"
390 391 392 393 394 395 396 397
  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')

398 399 400 401
    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"
402 403 404 405 406 407 408 409 410 411 412 413 414 415
  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
416 417 418
    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"
419 420
  end

421
  def test_cherry_pick
422
    assert_forwarded "cherry-pick a319d88"
423 424 425
  end

  def test_cherry_pick_url
426
    url = 'http://github.com/mislav/hub/commit/a319d88'
427
    assert_commands "git fetch mislav", "git cherry-pick a319d88", "cherry-pick #{url}"
428 429
  end

430 431
  def test_cherry_pick_url_with_fragment
    url = 'http://github.com/mislav/hub/commit/abcdef0123456789#comments'
432
    assert_commands "git fetch mislav", "git cherry-pick abcdef0123456789", "cherry-pick #{url}"
433 434
  end

435 436
  def test_cherry_pick_url_with_remote_add
    url = 'https://github.com/xoebus/hub/commit/a319d88'
437
    assert_commands "git remote add -f xoebus git://github.com/xoebus/hub.git",
438 439
                    "git cherry-pick a319d88",
                    "cherry-pick #{url}"
440 441 442 443
  end

  def test_cherry_pick_origin_url
    url = 'https://github.com/defunkt/hub/commit/a319d88'
444
    assert_commands "git fetch origin", "git cherry-pick a319d88", "cherry-pick #{url}"
445 446 447
  end

  def test_cherry_pick_github_user_notation
448
    assert_commands "git fetch mislav", "git cherry-pick 368af20", "cherry-pick mislav@368af20"
449 450 451 452
  end

  def test_cherry_pick_github_user_repo_notation
    # not supported
453
    assert_forwarded "cherry-pick mislav/hubbub@a319d88"
454 455 456
  end

  def test_cherry_pick_github_notation_too_short
457
    assert_forwarded "cherry-pick mislav@a319"
458 459 460
  end

  def test_cherry_pick_github_notation_with_remote_add
461 462 463
    assert_commands "git remote add -f xoebus git://github.com/xoebus/hub.git",
                    "git cherry-pick a319d88",
                    "cherry-pick xoebus@a319d88"
464 465
  end

466 467 468 469 470 471 472 473
  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",
474
                      "am --signoff https://github.com/defunkt/hub/pull/55#comment_123 -p2"
475 476 477

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

481 482 483 484 485 486 487
  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

488 489 490 491 492 493 494 495 496 497
  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

498 499 500 501 502 503 504 505 506 507
  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

508 509 510 511 512 513 514 515 516 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
  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 已提交
543
  def test_init
M
Mislav Marohnić 已提交
544 545
    stub_no_remotes
    stub_no_git_repo
546
    assert_commands "git init", "git remote add origin git@github.com:tpw/hub.git", "init -g"
547 548
  end

549 550 551 552 553 554 555 556 557
  def test_init_enterprise
    stub_no_remotes
    stub_no_git_repo
    stub_github_user('myfiname', 'git.my.org')
    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

558 559
  def test_init_no_login
    out = hub("init -g") do
560
      stub_github_user(nil)
561 562
    end

563
    assert_equal "** No GitHub user set. See http://help.github.com/set-your-user-name-email-and-github-token/\n", out
C
Chris Wanstrath 已提交
564 565
  end

566 567 568 569
  def test_push_untouched
    assert_forwarded "push"
  end

570
  def test_push_two
571 572
    assert_commands "git push origin cool-feature", "git push staging cool-feature",
                    "push origin,staging cool-feature"
573 574
  end

575 576 577 578 579 580
  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 已提交
581
  def test_push_more
582 583 584 585
    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 已提交
586
  end
C
Chris Wanstrath 已提交
587

588
  def test_create
589
    stub_no_remotes
590
    stub_nonexisting_fork('tpw')
591 592
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
      with(:body => { 'name' => 'hub' })
593

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

599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620
  def test_create_custom_name
    stub_no_remotes
    stub_nonexisting_fork('tpw', 'hubbub')
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
      with(:body => { 'name' => 'hubbub' })

    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')
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
      with(:body => { 'name' => 'acme/hubbub' })

    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

621 622
  def test_create_no_openssl
    stub_no_remotes
623 624 625 626
    # stub_nonexisting_fork('tpw')
    stub_request(:get, "http://#{auth}github.com/api/v2/yaml/repos/show/tpw/hub").
      to_return(:status => 404)

627 628 629 630 631 632 633 634 635 636 637 638 639
    stub_request(:post, "http://#{auth}github.com/api/v2/yaml/repos/create").
      with(:body => { 'name' => 'hub' })

    expected = "remote add -f origin git@github.com:tpw/hub.git\n"
    expected << "created repository: tpw/hub\n"

    assert_equal expected, hub("create") {
      ENV['GIT'] = 'echo'
      require 'net/https'
      Object.send :remove_const, :OpenSSL
    }
  end

640 641 642
  def test_create_failed
    stub_no_remotes
    stub_nonexisting_fork('tpw')
643
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
644 645
      to_return(:status => [401, "Your token is fail"])

646 647
    expected = "Error creating repository: Your token is fail (HTTP 401)\n"
    expected << "Check your token configuration (`git config github.token`)\n"
648 649 650
    assert_equal expected, hub("create") { ENV['GIT'] = 'echo' }
  end

651 652 653 654 655 656 657
  def test_create_with_env_authentication
    stub_no_remotes
    old_user  = ENV['GITHUB_USER']
    old_token = ENV['GITHUB_TOKEN']
    ENV['GITHUB_USER']  = 'mojombo'
    ENV['GITHUB_TOKEN'] = '123abc'

658 659 660 661
    # stub_nonexisting_fork('mojombo')
    stub_request(:get, "https://#{auth('mojombo', '123abc')}github.com/api/v2/yaml/repos/show/mojombo/hub").
      to_return(:status => 404)

662 663
    stub_request(:post, "https://#{auth('mojombo', '123abc')}github.com/api/v2/yaml/repos/create").
      with(:body => { 'name' => 'hub' })
664 665 666 667 668 669 670 671 672 673

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

  ensure
    ENV['GITHUB_USER']  = old_user
    ENV['GITHUB_TOKEN'] = old_token
  end

674
  def test_create_private_repository
675
    stub_no_remotes
676
    stub_nonexisting_fork('tpw')
677 678
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
      with(:body => { 'name' => 'hub', 'public' => '0' })
679

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

685
  def test_create_with_description_and_homepage
686
    stub_no_remotes
687
    stub_nonexisting_fork('tpw')
688 689
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").with(:body => {
      'name' => 'hub', 'description' => 'toyproject', 'homepage' => 'http://example.com'
690 691
    })

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

697 698 699 700 701
  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

702
  def test_create_with_existing_repository
703
    stub_no_remotes
704 705
    stub_existing_fork('tpw')

706
    expected = "tpw/hub already exists on github.com\n"
707
    expected << "remote add -f origin git@github.com:tpw/hub.git\n"
708
    expected << "set remote origin: tpw/hub\n"
709 710 711
    assert_equal expected, hub("create") { ENV['GIT'] = 'echo' }
  end

712 713 714 715 716
  def test_create_https_protocol
    stub_no_remotes
    stub_existing_fork('tpw')
    stub_https_is_preferred

717
    expected = "tpw/hub already exists on github.com\n"
718 719 720 721 722
    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

723
  def test_create_no_user
724
    stub_no_remotes
725 726 727
    out = hub("create") do
      stub_github_token(nil)
    end
728
    assert_equal "** No GitHub token set. See http://help.github.com/set-your-user-name-email-and-github-token/\n", out
729 730
  end

731
  def test_create_outside_git_repo
732
    stub_no_git_repo
733 734
    assert_equal "'create' must be run from inside a git repository\n", hub("create")
  end
735 736

  def test_create_origin_already_exists
C
Chris Wanstrath 已提交
737
    stub_nonexisting_fork('tpw')
738 739
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
      with(:body => { 'name' => 'hub' })
C
Chris Wanstrath 已提交
740 741

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

745
  def test_fork
C
Chris Wanstrath 已提交
746
    stub_nonexisting_fork('tpw')
747 748
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/fork/defunkt/hub").
      with { |req| req.headers['Content-Length'] == 0 }
C
Chris Wanstrath 已提交
749

C
Chris Wanstrath 已提交
750
    expected = "remote add -f tpw git@github.com:tpw/hub.git\n"
751
    expected << "new remote: tpw\n"
752
    assert_output expected, "fork"
753 754
  end

755 756 757 758 759 760
  def test_fork_not_in_repo
    stub_no_git_repo
    expected = "fatal: Not a git repository\n"
    assert_output expected, "fork"
  end

761 762 763 764 765 766 767 768 769 770 771 772 773 774 775
  def test_fork_enterprise
    stub_hub_host('git.my.org')
    stub_repo_url('git@git.my.org:defunkt/hub.git')
    stub_github_user('myfiname', 'git.my.org')
    stub_github_token('789xyz', 'git.my.org')

    stub_request(:get, "https://#{auth('myfiname', '789xyz')}git.my.org/api/v2/yaml/repos/show/myfiname/hub").
      to_return(:status => 404)
    stub_request(:post, "https://#{auth('myfiname', '789xyz')}git.my.org/api/v2/yaml/repos/fork/defunkt/hub")

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

776 777
  def test_fork_failed
    stub_nonexisting_fork('tpw')
778
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/fork/defunkt/hub").
779 780
      to_return(:status => [500, "Your fork is fail"])

781
    expected = "Error creating fork: Your fork is fail (HTTP 500)\n"
782 783 784
    assert_equal expected, hub("fork") { ENV['GIT'] = 'echo' }
  end

785
  def test_fork_no_remote
786
    stub_nonexisting_fork('tpw')
787
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/fork/defunkt/hub")
C
Chris Wanstrath 已提交
788

789 790 791 792
    assert_equal "", hub("fork --no-remote") { ENV['GIT'] = 'echo' }
  end

  def test_fork_already_exists
793
    stub_existing_fork('tpw')
C
Chris Wanstrath 已提交
794

795
    expected = "tpw/hub already exists on github.com\n"
C
Chris Wanstrath 已提交
796
    expected << "remote add -f tpw git@github.com:tpw/hub.git\n"
797 798 799
    expected << "new remote: tpw\n"
    assert_equal expected, hub("fork") { ENV['GIT'] = 'echo' }
  end
C
Chris Wanstrath 已提交
800

801 802 803 804
  def test_fork_https_protocol
    stub_existing_fork('tpw')
    stub_https_is_preferred

805
    expected = "tpw/hub already exists on github.com\n"
806 807 808 809 810
    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

811
  def test_pullrequest
M
Mislav Marohnić 已提交
812 813 814
    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"
815 816
  end

M
Mislav Marohnić 已提交
817 818 819
  def test_pullrequest_with_unpushed_commits
    stub_tracking('master', 'mislav', 'master')
    stub_command_output "rev-list --cherry mislav/master...", "+abcd1234\n+bcde2345"
820

M
Mislav Marohnić 已提交
821
    expected = "Aborted: 2 commits are not yet pushed to mislav/master\n" <<
822
      "(use `-f` to force submit a pull request anyway)\n"
823 824 825 826 827 828
    assert_output expected, "pull-request hereyougo"
  end

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

830
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub").
831 832 833
      with(:body => { 'pull' => {'base' => "master", 'head' => "tpw:feature", 'title' => "hereyougo"} }) { |req|
        req.headers['Content-Length'] == 76
      }.to_return(:body => mock_pullreq_response(1))
834 835

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

  def test_pullrequest_from_tracking_branch
    stub_branch('refs/heads/feature')
M
Mislav Marohnić 已提交
841 842
    stub_tracking('feature', 'mislav', 'yay-feature')
    stub_command_output "rev-list --cherry mislav/master...", nil
843

844
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub").
M
Mislav Marohnić 已提交
845
      with(:body => { 'pull' => {'base' => "master", 'head' => "mislav:yay-feature", 'title' => "hereyougo"} }).
846 847 848
      to_return(:body => mock_pullreq_response(1))

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

852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868
  def test_pullrequest_enterprise_no_tracking
    stub_hub_host('git.my.org')
    stub_repo_url('git@git.my.org:defunkt/hub.git')
    stub_github_user('myfiname', 'git.my.org')
    stub_github_token('789xyz', 'git.my.org')
    stub_branch('refs/heads/feature')
    stub_tracking_nothing('feature')
    stub_command_output "rev-list --cherry origin/feature...", nil

    stub_request(:post, "https://#{auth('myfiname', '789xyz')}git.my.org/api/v2/json/pulls/defunkt/hub").
      with(:body => { 'pull' => {'base' => "master", 'head' => "myfiname:feature", 'title' => "hereyougo"} }).
      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

869
  def test_pullrequest_explicit_head
870
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub").
871 872 873 874
      with(:body => { 'pull' => {'base' => "master", 'head' => "tpw:yay-feature", 'title' => "hereyougo"} }).
      to_return(:body => mock_pullreq_response(1))

    expected = "https://github.com/defunkt/hub/pull/1\n"
875
    assert_output expected, "pull-request hereyougo -h yay-feature -f"
876 877 878
  end

  def test_pullrequest_explicit_head_with_owner
879
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub").
880 881 882 883
      with(:body => { 'pull' => {'base' => "master", 'head' => "mojombo:feature", 'title' => "hereyougo"} }).
      to_return(:body => mock_pullreq_response(1))

    expected = "https://github.com/defunkt/hub/pull/1\n"
884
    assert_output expected, "pull-request hereyougo -h mojombo:feature -f"
885 886 887
  end

  def test_pullrequest_explicit_base
888
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub").
M
Mislav Marohnić 已提交
889
      with(:body => { 'pull' => {'base' => "feature", 'head' => "defunkt:master", 'title' => "hereyougo"} }).
890 891 892
      to_return(:body => mock_pullreq_response(1))

    expected = "https://github.com/defunkt/hub/pull/1\n"
893
    assert_output expected, "pull-request hereyougo -b feature -f"
894 895 896
  end

  def test_pullrequest_explicit_base_with_owner
897
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/mojombo/hub").
M
Mislav Marohnić 已提交
898
      with(:body => { 'pull' => {'base' => "feature", 'head' => "defunkt:master", 'title' => "hereyougo"} }).
899 900 901
      to_return(:body => mock_pullreq_response(1))

    expected = "https://github.com/defunkt/hub/pull/1\n"
902
    assert_output expected, "pull-request hereyougo -b mojombo:feature -f"
903 904
  end

905
  def test_pullrequest_explicit_base_with_repo
906
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/mojombo/hubbub").
M
Mislav Marohnić 已提交
907
      with(:body => { 'pull' => {'base' => "feature", 'head' => "defunkt:master", 'title' => "hereyougo"} }).
908 909 910
      to_return(:body => mock_pullreq_response(1))

    expected = "https://github.com/defunkt/hub/pull/1\n"
911
    assert_output expected, "pull-request hereyougo -b mojombo/hubbub:feature -f"
912 913 914
  end

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

919
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub").
M
Mislav Marohnić 已提交
920
      with(:body => { 'pull' => {'base' => "master", 'head' => "mislav:awesomefix", 'issue' => '92'} }).
921 922 923
      to_return(:body => mock_pullreq_response(92))

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

927
  def test_pullrequest_existing_issue_url
M
Mislav Marohnić 已提交
928 929 930 931
    stub_branch('refs/heads/myfix')
    stub_tracking('myfix', 'mislav', 'awesomefix')
    stub_command_output "rev-list --cherry mislav/awesomefix...", nil

932
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/mojombo/hub").
M
Mislav Marohnić 已提交
933
      with(:body => { 'pull' => {'base' => "master", 'head' => "mislav:awesomefix", 'issue' => '92'} }).
934 935 936
      to_return(:body => mock_pullreq_response(92, 'mojombo/hub'))

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

940 941 942 943 944 945 946 947 948 949 950
  def test_pullrequest_fails
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub").
      to_return(:status => [422, "Unprocessable Entity"],
                :headers => {"Content-type" => "application/json"},
                :body => %({"error":["oh no!", "it failed."]}))

    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

951 952 953 954 955
  def test_checkout_no_changes
    assert_forwarded "checkout master"
  end

  def test_checkout_pullrequest
956
    stub_request(:get, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub/73").
957 958 959
      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ć 已提交
960 961
      'git checkout -f --track -B blueyed-feature blueyed/feature -q',
      "checkout -f https://github.com/defunkt/hub/pull/73/files -q"
962 963
  end

964 965 966 967 968
  def test_checkout_private_pullrequest
    stub_request(:get, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub/73").
      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ć 已提交
969
      'git checkout --track -B blueyed-feature blueyed/feature',
970 971 972
      "checkout https://github.com/defunkt/hub/pull/73/files"
  end

973
  def test_checkout_pullrequest_custom_branch
974
    stub_request(:get, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub/73").
975 976 977
      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ć 已提交
978
      'git checkout --track -B review blueyed/feature',
979 980 981 982 983 984
      "checkout https://github.com/defunkt/hub/pull/73/files review"
  end

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

985
    stub_request(:get, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub/73").
986 987 988 989
      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ć 已提交
990
      'git checkout --track -B blueyed-feature blueyed/feature',
991 992 993
      "checkout https://github.com/defunkt/hub/pull/73/files"
  end

C
Chris Wanstrath 已提交
994
  def test_version
995
    out = hub('--version')
996
    assert_includes "git version 1.7.0.4", out
C
Chris Wanstrath 已提交
997
    assert_includes "hub version #{Hub::Version}", out
C
Chris Wanstrath 已提交
998
  end
C
Chris Wanstrath 已提交
999

1000 1001 1002 1003 1004 1005 1006
  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')
1007
    assert_equal improved_help_text, out
1008 1009 1010 1011 1012 1013 1014
  end

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

C
Chris Wanstrath 已提交
1015
  def test_help
1016
    assert_equal improved_help_text, hub("help")
C
Chris Wanstrath 已提交
1017 1018 1019
  end

  def test_help_by_default
1020
    assert_equal improved_help_text, hub("")
C
Chris Wanstrath 已提交
1021
  end
C
Chris Wanstrath 已提交
1022

S
Stephen Celis 已提交
1023
  def test_help_with_pager
1024
    assert_equal improved_help_text, hub("-p")
S
Stephen Celis 已提交
1025 1026
  end

C
Chris Wanstrath 已提交
1027 1028 1029 1030
  def test_help_hub
    help_manpage = hub("help hub")
    assert_includes "git + hub = github", help_manpage
    assert_includes <<-config, help_manpage
C
Chris Wanstrath 已提交
1031
Use git-config(1) to display the currently configured GitHub username:
C
Chris Wanstrath 已提交
1032 1033 1034 1035
config
  end

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

1040 1041 1042 1043 1044
  def test_hub_standalone
    help_standalone = hub("hub standalone")
    assert_equal Hub::Standalone.build, help_standalone
  end

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

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

1055 1056 1057 1058 1059 1060 1061 1062
  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')
1063
    stub_tracking('feature', 'mislav', 'experimental')
1064 1065

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

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

1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088
  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

1089 1090 1091 1092 1093 1094
  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

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

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

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

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

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

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

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

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

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

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

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

1151 1152 1153 1154 1155 1156 1157 1158
  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

1159
  def test_hub_browse_current
1160 1161
    assert_command "browse", "open https://github.com/defunkt/hub"
    assert_command "browse --", "open https://github.com/defunkt/hub"
1162 1163
  end

1164 1165 1166 1167 1168
  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

1169 1170 1171 1172
  def test_hub_browse_commit_from_current
    assert_command "browse -- commit/6616e4", "open https://github.com/defunkt/hub/commit/6616e4"
  end

1173 1174 1175 1176 1177 1178 1179
  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')
1180
    stub_tracking_nothing('feature')
1181 1182 1183
    assert_command "browse", "open https://github.com/defunkt/hub"
  end

1184 1185 1186 1187 1188 1189 1190 1191 1192
  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

1193 1194
  def test_hub_browse_current_subpage
    assert_command "browse -- network",
1195
      "open https://github.com/defunkt/hub/network"
1196
    assert_command "browse -- anything/everything",
1197
      "open https://github.com/defunkt/hub/anything/everything"
1198 1199
  end

1200 1201 1202 1203
  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
1204 1205
  end

1206 1207 1208
  def test_hub_browse_no_repo
    stub_repo_url(nil)
    assert_equal "Usage: hub browse [<USER>/]<REPOSITORY>\n", hub("browse")
1209
  end
1210 1211 1212 1213 1214 1215 1216 1217 1218 1219

  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
1220
      with_host_os("i686-linux") do
1221 1222 1223 1224 1225 1226 1227 1228
        assert_browser("xdg-open")
      end
    end
  end

  def test_cygwin_browser
    stub_available_commands "open", "cygstart"
    with_browser_env(nil) do
1229
      with_host_os("i686-linux") do
1230 1231 1232 1233 1234 1235 1236 1237 1238
        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
1239
      with_host_os("i686-linux") do
1240 1241 1242 1243 1244
        assert_equal expected, hub("browse")
      end
    end
  end

1245
  def test_context_method_doesnt_hijack_git_command
1246
    assert_forwarded 'remotes'
1247 1248
  end

1249 1250 1251 1252 1253
  def test_not_choking_on_ruby_methods
    assert_forwarded 'id'
    assert_forwarded 'name'
  end

1254 1255
  def test_multiple_remote_urls
    stub_repo_url("git://example.com/other.git\ngit://github.com/my/repo.git")
1256
    assert_command "browse", "open https://github.com/my/repo"
1257 1258
  end

1259 1260 1261
  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'
1262
    assert_equal %w[git --bare -c core.awesome=true -c name=value --git-dir=/srv/www], git_reader.executable
1263 1264
  end

1265
  private
1266

1267 1268 1269
    def stub_github_user(name, host = '')
      host = %(."#{host}") unless host.empty?
      stub_config_value "github#{host}.user", name
1270 1271
    end

1272 1273 1274
    def stub_github_token(token, host = '')
      host = %(."#{host}") unless host.empty?
      stub_config_value "github#{host}.token", token
1275 1276
    end

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

    def stub_branch(value)
1282
      stub_command_output 'symbolic-ref -q HEAD', value
1283 1284
    end

1285
    def stub_tracking(from, remote_name, remote_branch)
1286 1287
      stub_command_output "rev-parse --symbolic-full-name #{from}@{upstream}",
        remote_branch ? "refs/remotes/#{remote_name}/#{remote_branch}" : nil
1288 1289
    end

1290 1291
    def stub_tracking_nothing(from = 'master')
      stub_tracking(from, nil, nil)
1292 1293
    end

1294
    def stub_remotes_group(name, value)
1295
      stub_config_value "remotes.#{name}", value
1296 1297
    end

1298
    def stub_no_remotes
1299
      stub_command_output 'remote', nil
1300 1301 1302
    end

    def stub_no_git_repo
1303
      stub_command_output 'rev-parse -q --git-dir', nil
1304 1305
    end

M
Mislav Marohnić 已提交
1306
    def stub_alias(name, value)
1307
      stub_config_value "alias.#{name}", value
M
Mislav Marohnić 已提交
1308 1309
    end

1310 1311
    def stub_existing_fork(user, repo = 'hub')
      stub_fork(user, repo, 200)
1312 1313
    end

1314 1315
    def stub_nonexisting_fork(user, repo = 'hub')
      stub_fork(user, repo, 404)
1316 1317
    end

1318
    def stub_fork(user, repo, status)
1319
      stub_request(:get, "https://#{auth}github.com/api/v2/yaml/repos/show/#{user}/#{repo}").
1320 1321 1322
        to_return(:status => status)
    end

1323 1324 1325 1326
    def stub_available_commands(*names)
      COMMANDS.replace names
    end

1327
    def stub_https_is_preferred
1328
      stub_config_value 'hub.protocol', 'https'
1329 1330
    end

1331 1332 1333 1334
    def stub_hub_host(names)
      stub_config_value "hub.host", Array(names).join("\n"), '--get-all'
    end

1335 1336 1337 1338 1339 1340 1341
    def with_browser_env(value)
      browser, ENV['BROWSER'] = ENV['BROWSER'], value
      yield
    ensure
      ENV['BROWSER'] = browser
    end

1342 1343 1344 1345 1346 1347 1348
    def with_tmpdir(value)
      dir, ENV['TMPDIR'] = ENV['TMPDIR'], value
      yield
    ensure
      ENV['TMPDIR'] = dir
    end

1349 1350 1351 1352 1353 1354 1355
    def with_host_env(value)
      host, ENV['GITHUB_HOST'] = ENV['GITHUB_HOST'], value
      yield
    ensure
      ENV['GITHUB_HOST'] = host
    end

1356
    def assert_browser(browser)
1357
      assert_command "browse", "#{browser} https://github.com/defunkt/hub"
1358 1359
    end

1360 1361 1362 1363 1364 1365 1366 1367
    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
1368 1369
    end

1370
    def auth(user = git_config('github.user'), password = git_config('github.token'))
1371 1372 1373
      "#{user}%2Ftoken:#{password}@"
    end

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

1378 1379
    def mock_pull_response(label, priv = false)
      %({"pull": { "head": { "label": "#{label}", "repository": {"private":#{!!priv}} }}})
1380 1381
    end

1382 1383 1384 1385
    def improved_help_text
      Hub::Commands.send :improved_help_text
    end

C
Chris Wanstrath 已提交
1386
end