hub_test.rb 45.4 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
  def test_pullrequest_with_unpushed_commits
    stub_tracking('master', 'mislav', 'master')
819
    stub_command_output "rev-list --cherry-pick --right-only --no-merges 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
    stub_tracking('feature', 'mislav', 'yay-feature')
842

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

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

851 852 853 854 855 856 857 858 859 860 861 862
  def test_pullrequest_from_branch_tracking_local
    stub_branch('refs/heads/feature')
    stub_tracking('feature', 'refs/heads/master')

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

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

863 864 865 866 867 868 869
  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')
870
    stub_command_output "rev-list --cherry-pick --right-only --no-merges origin/feature...", nil
871 872 873 874 875 876 877 878 879

    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

880
  def test_pullrequest_explicit_head
881
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub").
882 883 884 885
      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"
886
    assert_output expected, "pull-request hereyougo -h yay-feature -f"
887 888 889
  end

  def test_pullrequest_explicit_head_with_owner
890
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub").
891 892 893 894
      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"
895
    assert_output expected, "pull-request hereyougo -h mojombo:feature -f"
896 897 898
  end

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

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

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

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

916
  def test_pullrequest_explicit_base_with_repo
917
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/mojombo/hubbub").
M
Mislav Marohnić 已提交
918
      with(:body => { 'pull' => {'base' => "feature", 'head' => "defunkt:master", 'title' => "hereyougo"} }).
919 920 921
      to_return(:body => mock_pullreq_response(1))

    expected = "https://github.com/defunkt/hub/pull/1\n"
922
    assert_output expected, "pull-request hereyougo -b mojombo/hubbub:feature -f"
923 924 925
  end

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

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

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

938
  def test_pullrequest_existing_issue_url
M
Mislav Marohnić 已提交
939 940
    stub_branch('refs/heads/myfix')
    stub_tracking('myfix', 'mislav', 'awesomefix')
941
    stub_command_output "rev-list --cherry-pick --right-only --no-merges mislav/awesomefix...", nil
M
Mislav Marohnić 已提交
942

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

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

951 952 953 954 955 956 957 958 959 960 961
  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

962 963 964 965 966
  def test_checkout_no_changes
    assert_forwarded "checkout master"
  end

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

975 976 977 978 979
  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ć 已提交
980
      'git checkout --track -B blueyed-feature blueyed/feature',
981 982 983
      "checkout https://github.com/defunkt/hub/pull/73/files"
  end

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

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

996
    stub_request(:get, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub/73").
997 998 999 1000
      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ć 已提交
1001
      'git checkout --track -B blueyed-feature blueyed/feature',
1002 1003 1004
      "checkout https://github.com/defunkt/hub/pull/73/files"
  end

C
Chris Wanstrath 已提交
1005
  def test_version
1006
    out = hub('--version')
1007
    assert_includes "git version 1.7.0.4", out
C
Chris Wanstrath 已提交
1008
    assert_includes "hub version #{Hub::Version}", out
C
Chris Wanstrath 已提交
1009
  end
C
Chris Wanstrath 已提交
1010

1011 1012 1013 1014 1015 1016 1017
  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')
1018
    assert_equal improved_help_text, out
1019 1020 1021 1022 1023 1024 1025
  end

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

C
Chris Wanstrath 已提交
1026
  def test_help
1027
    assert_equal improved_help_text, hub("help")
C
Chris Wanstrath 已提交
1028 1029 1030
  end

  def test_help_by_default
1031
    assert_equal improved_help_text, hub("")
C
Chris Wanstrath 已提交
1032
  end
C
Chris Wanstrath 已提交
1033

S
Stephen Celis 已提交
1034
  def test_help_with_pager
1035
    assert_equal improved_help_text, hub("-p")
S
Stephen Celis 已提交
1036 1037
  end

C
Chris Wanstrath 已提交
1038 1039 1040 1041
  def test_help_hub
    help_manpage = hub("help hub")
    assert_includes "git + hub = github", help_manpage
    assert_includes <<-config, help_manpage
C
Chris Wanstrath 已提交
1042
Use git-config(1) to display the currently configured GitHub username:
C
Chris Wanstrath 已提交
1043 1044 1045 1046
config
  end

  def test_help_hub_no_groff
1047 1048
    stub_available_commands()
    assert_equal "** Can't find groff(1)\n", hub("help hub")
C
Chris Wanstrath 已提交
1049
  end
1050

1051 1052 1053 1054 1055
  def test_hub_standalone
    help_standalone = hub("hub standalone")
    assert_equal Hub::Standalone.build, help_standalone
  end

C
Chris Wanstrath 已提交
1056 1057
  def test_hub_compare
    assert_command "compare refactor",
1058
      "open https://github.com/defunkt/hub/compare/refactor"
1059
  end
C
Chris Wanstrath 已提交
1060

1061 1062 1063 1064
  def test_hub_compare_nothing
    expected = "Usage: hub compare [USER] [<START>...]<END>\n"
    assert_equal expected, hub("compare")
  end
C
Chris Wanstrath 已提交
1065

1066 1067 1068 1069 1070 1071 1072 1073
  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')
1074
    stub_tracking('feature', 'mislav', 'experimental')
1075 1076

    assert_command "compare",
1077
      "open https://github.com/mislav/hub/compare/experimental"
1078 1079
  end

1080
  def test_hub_compare_range
C
Chris Wanstrath 已提交
1081
    assert_command "compare 1.0...fix",
1082
      "open https://github.com/defunkt/hub/compare/1.0...fix"
1083
  end
C
Chris Wanstrath 已提交
1084

1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099
  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

1100 1101 1102 1103 1104 1105
  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

1106
  def test_hub_compare_fork
C
Chris Wanstrath 已提交
1107
    assert_command "compare myfork feature",
1108
      "open https://github.com/myfork/hub/compare/feature"
1109 1110 1111 1112
  end

  def test_hub_compare_url
    assert_command "compare -u 1.0...1.1",
1113
      "echo https://github.com/defunkt/hub/compare/1.0...1.1"
1114 1115 1116
  end

  def test_hub_browse
1117
    assert_command "browse mojombo/bert", "open https://github.com/mojombo/bert"
1118 1119
  end

1120 1121 1122 1123
  def test_hub_browse_commit
    assert_command "browse mojombo/bert commit/5d5582", "open https://github.com/mojombo/bert/commit/5d5582"
  end

1124 1125
  def test_hub_browse_tracking_nothing
    stub_tracking_nothing
1126
    assert_command "browse mojombo/bert", "open https://github.com/mojombo/bert"
1127 1128
  end

1129
  def test_hub_browse_url
1130
    assert_command "browse -u mojombo/bert", "echo https://github.com/mojombo/bert"
1131 1132
  end

1133
  def test_hub_browse_self
1134
    assert_command "browse resque", "open https://github.com/tpw/resque"
1135 1136
  end

1137 1138
  def test_hub_browse_subpage
    assert_command "browse resque commits",
1139
      "open https://github.com/tpw/resque/commits/master"
1140
    assert_command "browse resque issues",
1141
      "open https://github.com/tpw/resque/issues"
1142
    assert_command "browse resque wiki",
1143
      "open https://github.com/tpw/resque/wiki"
1144 1145 1146 1147
  end

  def test_hub_browse_on_branch
    stub_branch('refs/heads/feature')
1148
    stub_tracking('feature', 'mislav', 'experimental')
1149

1150
    assert_command "browse resque", "open https://github.com/tpw/resque"
1151
    assert_command "browse resque commits",
1152
      "open https://github.com/tpw/resque/commits/master"
1153 1154

    assert_command "browse",
1155
      "open https://github.com/mislav/hub/tree/experimental"
1156
    assert_command "browse -- tree",
1157
      "open https://github.com/mislav/hub/tree/experimental"
1158
    assert_command "browse -- commits",
1159
      "open https://github.com/mislav/hub/commits/experimental"
1160
  end
1161

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

1170 1171 1172 1173 1174
  def test_hub_browse_no_branch
    stub_branch(nil)
    assert_command 'browse', 'open https://github.com/defunkt/hub'
  end

1175
  def test_hub_browse_current
1176 1177
    assert_command "browse", "open https://github.com/defunkt/hub"
    assert_command "browse --", "open https://github.com/defunkt/hub"
1178 1179
  end

1180 1181 1182 1183 1184
  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

1185 1186 1187 1188
  def test_hub_browse_commit_from_current
    assert_command "browse -- commit/6616e4", "open https://github.com/defunkt/hub/commit/6616e4"
  end

1189 1190 1191 1192 1193 1194 1195
  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')
1196
    stub_tracking_nothing('feature')
1197 1198 1199
    assert_command "browse", "open https://github.com/defunkt/hub"
  end

1200 1201 1202 1203 1204 1205 1206 1207 1208
  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

1209 1210
  def test_hub_browse_current_subpage
    assert_command "browse -- network",
1211
      "open https://github.com/defunkt/hub/network"
1212
    assert_command "browse -- anything/everything",
1213
      "open https://github.com/defunkt/hub/anything/everything"
1214 1215
  end

1216 1217 1218 1219
  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
1220 1221
  end

1222 1223 1224
  def test_hub_browse_no_repo
    stub_repo_url(nil)
    assert_equal "Usage: hub browse [<USER>/]<REPOSITORY>\n", hub("browse")
1225
  end
1226 1227 1228 1229 1230 1231 1232 1233 1234 1235

  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
1236
      with_host_os("i686-linux") do
1237 1238 1239 1240 1241 1242 1243 1244
        assert_browser("xdg-open")
      end
    end
  end

  def test_cygwin_browser
    stub_available_commands "open", "cygstart"
    with_browser_env(nil) do
1245
      with_host_os("i686-linux") do
1246 1247 1248 1249 1250 1251 1252 1253 1254
        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
1255
      with_host_os("i686-linux") do
1256 1257 1258 1259 1260
        assert_equal expected, hub("browse")
      end
    end
  end

1261
  def test_context_method_doesnt_hijack_git_command
1262
    assert_forwarded 'remotes'
1263 1264
  end

1265 1266 1267 1268 1269
  def test_not_choking_on_ruby_methods
    assert_forwarded 'id'
    assert_forwarded 'name'
  end

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

1275 1276 1277
  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'
1278
    assert_equal %w[git --bare -c core.awesome=true -c name=value --git-dir=/srv/www], git_reader.executable
1279 1280
  end

1281
  private
1282

1283 1284 1285
    def stub_github_user(name, host = '')
      host = %(."#{host}") unless host.empty?
      stub_config_value "github#{host}.user", name
1286 1287
    end

1288 1289 1290
    def stub_github_token(token, host = '')
      host = %(."#{host}") unless host.empty?
      stub_config_value "github#{host}.token", token
1291 1292
    end

M
Mislav Marohnić 已提交
1293 1294
    def stub_repo_url(value, remote_name = 'origin')
      stub_config_value "remote.#{remote_name}.url", value, '--get-all'
1295 1296 1297
    end

    def stub_branch(value)
1298
      stub_command_output 'symbolic-ref -q HEAD', value
1299 1300
    end

1301
    def stub_tracking(from, upstream, remote_branch = nil)
1302
      stub_command_output "rev-parse --symbolic-full-name #{from}@{upstream}",
1303
        remote_branch ? "refs/remotes/#{upstream}/#{remote_branch}" : upstream
1304 1305
    end

1306
    def stub_tracking_nothing(from = 'master')
1307
      stub_tracking(from, nil)
1308 1309
    end

1310
    def stub_remotes_group(name, value)
1311
      stub_config_value "remotes.#{name}", value
1312 1313
    end

1314
    def stub_no_remotes
1315
      stub_command_output 'remote', nil
1316 1317 1318
    end

    def stub_no_git_repo
1319
      stub_command_output 'rev-parse -q --git-dir', nil
1320 1321
    end

M
Mislav Marohnić 已提交
1322
    def stub_alias(name, value)
1323
      stub_config_value "alias.#{name}", value
M
Mislav Marohnić 已提交
1324 1325
    end

1326 1327
    def stub_existing_fork(user, repo = 'hub')
      stub_fork(user, repo, 200)
1328 1329
    end

1330 1331
    def stub_nonexisting_fork(user, repo = 'hub')
      stub_fork(user, repo, 404)
1332 1333
    end

1334
    def stub_fork(user, repo, status)
1335
      stub_request(:get, "https://#{auth}github.com/api/v2/yaml/repos/show/#{user}/#{repo}").
1336 1337 1338
        to_return(:status => status)
    end

1339 1340 1341 1342
    def stub_available_commands(*names)
      COMMANDS.replace names
    end

1343
    def stub_https_is_preferred
1344
      stub_config_value 'hub.protocol', 'https'
1345 1346
    end

1347 1348 1349 1350
    def stub_hub_host(names)
      stub_config_value "hub.host", Array(names).join("\n"), '--get-all'
    end

1351 1352 1353 1354 1355 1356 1357
    def with_browser_env(value)
      browser, ENV['BROWSER'] = ENV['BROWSER'], value
      yield
    ensure
      ENV['BROWSER'] = browser
    end

1358 1359 1360 1361 1362 1363 1364
    def with_tmpdir(value)
      dir, ENV['TMPDIR'] = ENV['TMPDIR'], value
      yield
    ensure
      ENV['TMPDIR'] = dir
    end

1365 1366 1367 1368 1369 1370 1371
    def with_host_env(value)
      host, ENV['GITHUB_HOST'] = ENV['GITHUB_HOST'], value
      yield
    ensure
      ENV['GITHUB_HOST'] = host
    end

1372
    def assert_browser(browser)
1373
      assert_command "browse", "#{browser} https://github.com/defunkt/hub"
1374 1375
    end

1376 1377 1378 1379 1380 1381 1382 1383
    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
1384 1385
    end

1386
    def auth(user = git_config('github.user'), password = git_config('github.token'))
1387 1388 1389
      "#{user}%2Ftoken:#{password}@"
    end

1390 1391
    def mock_pullreq_response(id, name_with_owner = 'defunkt/hub', host = 'github.com')
      %({"pull": { "html_url": "https://#{host}/#{name_with_owner}/pull/#{id}" }})
1392 1393
    end

1394 1395
    def mock_pull_response(label, priv = false)
      %({"pull": { "head": { "label": "#{label}", "repository": {"private":#{!!priv}} }}})
1396 1397
    end

1398 1399 1400 1401
    def improved_help_text
      Hub::Commands.send :improved_help_text
    end

C
Chris Wanstrath 已提交
1402
end