hub_test.rb 44.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
  def test_clone_with_host_alias
164
    stub_no_git_repo
165 166 167
    assert_forwarded "clone server:git/repo.git"
  end

168
  def test_enterprise_clone
169
    stub_no_git_repo
170 171 172 173 174 175 176
    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ć 已提交
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
  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

196 197 198 199 200 201
  def test_remote_origin
    input   = "remote add origin"
    command = "git remote add origin git://github.com/tpw/hub.git"
    assert_command input, command
  end

202 203 204 205 206 207
  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

208 209 210 211 212 213
  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

214 215 216 217 218 219
  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"
220 221
  end

222
  def test_remote_from_rel_path
223
    assert_forwarded "remote add origin ./path"
224 225 226
  end

  def test_remote_from_abs_path
227
    assert_forwarded "remote add origin /path"
228 229
  end

230
  def test_remote_with_host_alias
231 232 233
    assert_forwarded "remote add origin server:/git/repo.git"
  end

234 235 236 237
  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 已提交
238 239
  end

S
Stephen Celis 已提交
240 241
  def test_public_submodule
    input   = "submodule add wycats/bundler vendor/bundler"
J
Justin Ridgewell 已提交
242 243
    command = "git submodule add git://github.com/wycats/bundler.git vendor/bundler"
    assert_command input, command
S
Stephen Celis 已提交
244 245 246 247
  end

  def test_private_submodule
    input   = "submodule add -p grit vendor/grit"
J
Justin Ridgewell 已提交
248 249 250 251 252 253 254 255
    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 已提交
256 257 258 259 260
  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 已提交
261
    assert_command input, command
S
Stephen Celis 已提交
262 263
  end

C
Chris Wanstrath 已提交
264
  def test_private_remote
265
    input   = "remote add -p rtomayko"
C
Chris Wanstrath 已提交
266 267
    command = "git remote add rtomayko git@github.com:rtomayko/hub.git"
    assert_command input, command
C
Chris Wanstrath 已提交
268 269
  end

270 271 272 273 274 275 276
  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 已提交
277
  def test_public_remote
278
    input   = "remote add rtomayko"
C
Chris Wanstrath 已提交
279 280
    command = "git remote add rtomayko git://github.com/rtomayko/hub.git"
    assert_command input, command
C
Chris Wanstrath 已提交
281 282
  end

C
Chris Wanstrath 已提交
283 284 285 286 287 288
  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

289 290 291 292 293 294
  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

295 296 297 298 299 300
  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 已提交
301
  def test_private_remote_with_repo
302 303
    input   = "remote add -p jashkenas/coffee-script"
    command = "git remote add jashkenas git@github.com:jashkenas/coffee-script.git"
C
Chris Wanstrath 已提交
304 305 306 307
    assert_command input, command
  end

  def test_public_remote_with_repo
308 309
    input   = "remote add jashkenas/coffee-script"
    command = "git remote add jashkenas git://github.com/jashkenas/coffee-script.git"
310 311 312 313
    assert_command input, command
  end

  def test_public_remote_f_with_repo
314 315
    input   = "remote add -f jashkenas/coffee-script"
    command = "git remote add -f jashkenas git://github.com/jashkenas/coffee-script.git"
C
Chris Wanstrath 已提交
316 317 318
    assert_command input, command
  end

319
  def test_named_private_remote_with_repo
320 321
    input   = "remote add -p origin jashkenas/coffee-script"
    command = "git remote add origin git@github.com:jashkenas/coffee-script.git"
322 323 324
    assert_command input, command
  end

325
  def test_fetch_existing_remote
326
    assert_forwarded "fetch mislav"
327 328 329 330 331 332
  end

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

333 334 335
    assert_commands "git remote add xoebus git://github.com/xoebus/hub.git",
                    "git fetch xoebus",
                    "fetch xoebus"
336 337
  end

338 339 340 341 342 343 344 345 346 347
  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

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

361 362 363 364
  def test_fetch_new_remote_with_options
    stub_remotes_group('xoebus', nil)
    stub_existing_fork('xoebus')

365 366 367
    assert_commands "git remote add xoebus git://github.com/xoebus/hub.git",
                    "git fetch --depth=1 --prune xoebus",
                    "fetch --depth=1 --prune xoebus"
368 369 370 371 372 373 374 375
  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')

376 377 378 379
    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"
380 381 382 383 384 385 386 387
  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')

388 389 390 391
    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"
392 393 394 395 396 397 398 399 400 401 402 403 404 405
  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
406 407 408
    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"
409 410
  end

411
  def test_cherry_pick
412
    assert_forwarded "cherry-pick a319d88"
413 414 415
  end

  def test_cherry_pick_url
416
    url = 'http://github.com/mislav/hub/commit/a319d88'
417
    assert_commands "git fetch mislav", "git cherry-pick a319d88", "cherry-pick #{url}"
418 419
  end

420 421
  def test_cherry_pick_url_with_fragment
    url = 'http://github.com/mislav/hub/commit/abcdef0123456789#comments'
422
    assert_commands "git fetch mislav", "git cherry-pick abcdef0123456789", "cherry-pick #{url}"
423 424
  end

425 426
  def test_cherry_pick_url_with_remote_add
    url = 'https://github.com/xoebus/hub/commit/a319d88'
427
    assert_commands "git remote add -f xoebus git://github.com/xoebus/hub.git",
428 429
                    "git cherry-pick a319d88",
                    "cherry-pick #{url}"
430 431 432 433
  end

  def test_cherry_pick_origin_url
    url = 'https://github.com/defunkt/hub/commit/a319d88'
434
    assert_commands "git fetch origin", "git cherry-pick a319d88", "cherry-pick #{url}"
435 436 437
  end

  def test_cherry_pick_github_user_notation
438
    assert_commands "git fetch mislav", "git cherry-pick 368af20", "cherry-pick mislav@368af20"
439 440 441 442
  end

  def test_cherry_pick_github_user_repo_notation
    # not supported
443
    assert_forwarded "cherry-pick mislav/hubbub@a319d88"
444 445 446
  end

  def test_cherry_pick_github_notation_too_short
447
    assert_forwarded "cherry-pick mislav@a319"
448 449 450
  end

  def test_cherry_pick_github_notation_with_remote_add
451 452 453
    assert_commands "git remote add -f xoebus git://github.com/xoebus/hub.git",
                    "git cherry-pick a319d88",
                    "cherry-pick xoebus@a319d88"
454 455
  end

456 457 458 459 460 461 462 463
  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",
464
                      "am --signoff https://github.com/defunkt/hub/pull/55#comment_123 -p2"
465 466 467

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

471 472 473 474 475 476 477
  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

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

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

498 499 500 501 502 503 504 505 506 507 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
  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 已提交
533
  def test_init
M
Mislav Marohnić 已提交
534 535
    stub_no_remotes
    stub_no_git_repo
536
    assert_commands "git init", "git remote add origin git@github.com:tpw/hub.git", "init -g"
537 538
  end

539 540 541 542 543 544 545 546 547
  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

548 549
  def test_init_no_login
    out = hub("init -g") do
550
      stub_github_user(nil)
551 552
    end

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

556 557 558 559
  def test_push_untouched
    assert_forwarded "push"
  end

560
  def test_push_two
561 562
    assert_commands "git push origin cool-feature", "git push staging cool-feature",
                    "push origin,staging cool-feature"
563 564
  end

565 566 567 568 569 570
  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 已提交
571
  def test_push_more
572 573 574 575
    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 已提交
576
  end
C
Chris Wanstrath 已提交
577

578
  def test_create
579
    stub_no_remotes
580
    stub_nonexisting_fork('tpw')
581 582
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
      with(:body => { 'name' => 'hub' })
583

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

589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
  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

611 612
  def test_create_no_openssl
    stub_no_remotes
613 614 615 616
    # stub_nonexisting_fork('tpw')
    stub_request(:get, "http://#{auth}github.com/api/v2/yaml/repos/show/tpw/hub").
      to_return(:status => 404)

617 618 619 620 621 622 623 624 625 626 627 628 629
    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

630 631 632
  def test_create_failed
    stub_no_remotes
    stub_nonexisting_fork('tpw')
633
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
634 635
      to_return(:status => [401, "Your token is fail"])

636 637
    expected = "Error creating repository: Your token is fail (HTTP 401)\n"
    expected << "Check your token configuration (`git config github.token`)\n"
638 639 640
    assert_equal expected, hub("create") { ENV['GIT'] = 'echo' }
  end

641 642 643 644 645 646 647
  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'

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

652 653
    stub_request(:post, "https://#{auth('mojombo', '123abc')}github.com/api/v2/yaml/repos/create").
      with(:body => { 'name' => 'hub' })
654 655 656 657 658 659 660 661 662 663

    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

664
  def test_create_private_repository
665
    stub_no_remotes
666
    stub_nonexisting_fork('tpw')
667 668
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
      with(:body => { 'name' => 'hub', 'public' => '0' })
669

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

675
  def test_create_with_description_and_homepage
676
    stub_no_remotes
677
    stub_nonexisting_fork('tpw')
678 679
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").with(:body => {
      'name' => 'hub', 'description' => 'toyproject', 'homepage' => 'http://example.com'
680 681
    })

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

687 688 689 690 691
  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

692
  def test_create_with_existing_repository
693
    stub_no_remotes
694 695
    stub_existing_fork('tpw')

696
    expected = "tpw/hub already exists on github.com\n"
697
    expected << "remote add -f origin git@github.com:tpw/hub.git\n"
698
    expected << "set remote origin: tpw/hub\n"
699 700 701
    assert_equal expected, hub("create") { ENV['GIT'] = 'echo' }
  end

702 703 704 705 706
  def test_create_https_protocol
    stub_no_remotes
    stub_existing_fork('tpw')
    stub_https_is_preferred

707
    expected = "tpw/hub already exists on github.com\n"
708 709 710 711 712
    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

713
  def test_create_no_user
714
    stub_no_remotes
715 716 717
    out = hub("create") do
      stub_github_token(nil)
    end
718
    assert_equal "** No GitHub token set. See http://help.github.com/set-your-user-name-email-and-github-token/\n", out
719 720
  end

721
  def test_create_outside_git_repo
722
    stub_no_git_repo
723 724
    assert_equal "'create' must be run from inside a git repository\n", hub("create")
  end
725 726

  def test_create_origin_already_exists
C
Chris Wanstrath 已提交
727
    stub_nonexisting_fork('tpw')
728 729
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
      with(:body => { 'name' => 'hub' })
C
Chris Wanstrath 已提交
730 731

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

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

C
Chris Wanstrath 已提交
740
    expected = "remote add -f tpw git@github.com:tpw/hub.git\n"
741
    expected << "new remote: tpw\n"
742
    assert_output expected, "fork"
743 744
  end

745 746 747 748 749 750
  def test_fork_not_in_repo
    stub_no_git_repo
    expected = "fatal: Not a git repository\n"
    assert_output expected, "fork"
  end

751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
  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

766 767
  def test_fork_failed
    stub_nonexisting_fork('tpw')
768
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/fork/defunkt/hub").
769 770
      to_return(:status => [500, "Your fork is fail"])

771
    expected = "Error creating fork: Your fork is fail (HTTP 500)\n"
772 773 774
    assert_equal expected, hub("fork") { ENV['GIT'] = 'echo' }
  end

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

779 780 781 782
    assert_equal "", hub("fork --no-remote") { ENV['GIT'] = 'echo' }
  end

  def test_fork_already_exists
783
    stub_existing_fork('tpw')
C
Chris Wanstrath 已提交
784

785
    expected = "tpw/hub already exists on github.com\n"
C
Chris Wanstrath 已提交
786
    expected << "remote add -f tpw git@github.com:tpw/hub.git\n"
787 788 789
    expected << "new remote: tpw\n"
    assert_equal expected, hub("fork") { ENV['GIT'] = 'echo' }
  end
C
Chris Wanstrath 已提交
790

791 792 793 794
  def test_fork_https_protocol
    stub_existing_fork('tpw')
    stub_https_is_preferred

795
    expected = "tpw/hub already exists on github.com\n"
796 797 798 799 800
    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

801
  def test_pullrequest
M
Mislav Marohnić 已提交
802 803 804
    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"
805 806
  end

M
Mislav Marohnić 已提交
807 808 809
  def test_pullrequest_with_unpushed_commits
    stub_tracking('master', 'mislav', 'master')
    stub_command_output "rev-list --cherry mislav/master...", "+abcd1234\n+bcde2345"
810

M
Mislav Marohnić 已提交
811
    expected = "Aborted: 2 commits are not yet pushed to mislav/master\n" <<
812
      "(use `-f` to force submit a pull request anyway)\n"
813 814 815 816 817 818
    assert_output expected, "pull-request hereyougo"
  end

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

820
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub").
821 822 823
      with(:body => { 'pull' => {'base' => "master", 'head' => "tpw:feature", 'title' => "hereyougo"} }) { |req|
        req.headers['Content-Length'] == 76
      }.to_return(:body => mock_pullreq_response(1))
824 825

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

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

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

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

842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
  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

859
  def test_pullrequest_explicit_head
860
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub").
861 862 863 864
      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"
865
    assert_output expected, "pull-request hereyougo -h yay-feature -f"
866 867 868
  end

  def test_pullrequest_explicit_head_with_owner
869
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub").
870 871 872 873
      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"
874
    assert_output expected, "pull-request hereyougo -h mojombo:feature -f"
875 876 877
  end

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

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

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

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

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

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

  def test_pullrequest_existing_issue
M
Mislav Marohnić 已提交
905 906 907 908
    stub_branch('refs/heads/myfix')
    stub_tracking('myfix', 'mislav', 'awesomefix')
    stub_command_output "rev-list --cherry mislav/awesomefix...", nil

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

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

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

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

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

930 931 932 933 934 935 936 937 938 939 940
  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

941 942 943 944 945
  def test_checkout_no_changes
    assert_forwarded "checkout master"
  end

  def test_checkout_pullrequest
946
    stub_request(:get, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub/73").
947 948 949 950 951 952 953
      to_return(:body => mock_pull_response('blueyed:feature'))

    assert_commands 'git remote add -f -t feature blueyed git://github.com/blueyed/hub.git',
      'git checkout -b blueyed-feature blueyed/feature',
      "checkout https://github.com/defunkt/hub/pull/73/files"
  end

954 955 956 957 958 959 960 961 962
  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',
      'git checkout -b blueyed-feature blueyed/feature',
      "checkout https://github.com/defunkt/hub/pull/73/files"
  end

963
  def test_checkout_pullrequest_custom_branch
964
    stub_request(:get, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub/73").
965 966 967 968 969 970 971 972 973 974
      to_return(:body => mock_pull_response('blueyed:feature'))

    assert_commands 'git remote add -f -t feature blueyed git://github.com/blueyed/hub.git',
      'git checkout -b review blueyed/feature',
      "checkout https://github.com/defunkt/hub/pull/73/files review"
  end

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

975
    stub_request(:get, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub/73").
976 977 978 979 980 981 982 983
      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',
      'git checkout -b blueyed-feature blueyed/feature',
      "checkout https://github.com/defunkt/hub/pull/73/files"
  end

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

990 991 992 993 994 995 996
  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')
997
    assert_equal improved_help_text, out
998 999 1000 1001 1002 1003 1004
  end

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

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

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

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

C
Chris Wanstrath 已提交
1017 1018 1019 1020
  def test_help_hub
    help_manpage = hub("help hub")
    assert_includes "git + hub = github", help_manpage
    assert_includes <<-config, help_manpage
C
Chris Wanstrath 已提交
1021
Use git-config(1) to display the currently configured GitHub username:
C
Chris Wanstrath 已提交
1022 1023 1024 1025
config
  end

  def test_help_hub_no_groff
1026 1027
    stub_available_commands()
    assert_equal "** Can't find groff(1)\n", hub("help hub")
C
Chris Wanstrath 已提交
1028
  end
1029

1030 1031 1032 1033 1034
  def test_hub_standalone
    help_standalone = hub("hub standalone")
    assert_equal Hub::Standalone.build, help_standalone
  end

C
Chris Wanstrath 已提交
1035 1036
  def test_hub_compare
    assert_command "compare refactor",
1037
      "open https://github.com/defunkt/hub/compare/refactor"
1038
  end
C
Chris Wanstrath 已提交
1039

1040 1041 1042 1043
  def test_hub_compare_nothing
    expected = "Usage: hub compare [USER] [<START>...]<END>\n"
    assert_equal expected, hub("compare")
  end
C
Chris Wanstrath 已提交
1044

1045 1046 1047 1048 1049 1050 1051 1052
  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')
1053
    stub_tracking('feature', 'mislav', 'experimental')
1054 1055

    assert_command "compare",
1056
      "open https://github.com/mislav/hub/compare/experimental"
1057 1058
  end

1059
  def test_hub_compare_range
C
Chris Wanstrath 已提交
1060
    assert_command "compare 1.0...fix",
1061
      "open https://github.com/defunkt/hub/compare/1.0...fix"
1062
  end
C
Chris Wanstrath 已提交
1063

1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
  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

1079 1080 1081 1082 1083 1084
  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

1085
  def test_hub_compare_fork
C
Chris Wanstrath 已提交
1086
    assert_command "compare myfork feature",
1087
      "open https://github.com/myfork/hub/compare/feature"
1088 1089 1090 1091
  end

  def test_hub_compare_url
    assert_command "compare -u 1.0...1.1",
1092
      "echo https://github.com/defunkt/hub/compare/1.0...1.1"
1093 1094 1095
  end

  def test_hub_browse
1096
    assert_command "browse mojombo/bert", "open https://github.com/mojombo/bert"
1097 1098
  end

1099 1100 1101 1102
  def test_hub_browse_commit
    assert_command "browse mojombo/bert commit/5d5582", "open https://github.com/mojombo/bert/commit/5d5582"
  end

1103 1104
  def test_hub_browse_tracking_nothing
    stub_tracking_nothing
1105
    assert_command "browse mojombo/bert", "open https://github.com/mojombo/bert"
1106 1107
  end

1108
  def test_hub_browse_url
1109
    assert_command "browse -u mojombo/bert", "echo https://github.com/mojombo/bert"
1110 1111
  end

1112
  def test_hub_browse_self
1113
    assert_command "browse resque", "open https://github.com/tpw/resque"
1114 1115
  end

1116 1117
  def test_hub_browse_subpage
    assert_command "browse resque commits",
1118
      "open https://github.com/tpw/resque/commits/master"
1119
    assert_command "browse resque issues",
1120
      "open https://github.com/tpw/resque/issues"
1121
    assert_command "browse resque wiki",
1122
      "open https://github.com/tpw/resque/wiki"
1123 1124 1125 1126
  end

  def test_hub_browse_on_branch
    stub_branch('refs/heads/feature')
1127
    stub_tracking('feature', 'mislav', 'experimental')
1128

1129
    assert_command "browse resque", "open https://github.com/tpw/resque"
1130
    assert_command "browse resque commits",
1131
      "open https://github.com/tpw/resque/commits/master"
1132 1133

    assert_command "browse",
1134
      "open https://github.com/mislav/hub/tree/experimental"
1135
    assert_command "browse -- tree",
1136
      "open https://github.com/mislav/hub/tree/experimental"
1137
    assert_command "browse -- commits",
1138
      "open https://github.com/mislav/hub/commits/experimental"
1139
  end
1140

1141 1142 1143 1144 1145 1146 1147 1148
  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

1149
  def test_hub_browse_current
1150 1151
    assert_command "browse", "open https://github.com/defunkt/hub"
    assert_command "browse --", "open https://github.com/defunkt/hub"
1152 1153
  end

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

1159 1160 1161 1162
  def test_hub_browse_commit_from_current
    assert_command "browse -- commit/6616e4", "open https://github.com/defunkt/hub/commit/6616e4"
  end

1163 1164 1165 1166 1167 1168 1169
  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')
1170
    stub_tracking_nothing('feature')
1171 1172 1173
    assert_command "browse", "open https://github.com/defunkt/hub"
  end

1174 1175 1176 1177 1178 1179 1180 1181 1182
  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

1183 1184
  def test_hub_browse_current_subpage
    assert_command "browse -- network",
1185
      "open https://github.com/defunkt/hub/network"
1186
    assert_command "browse -- anything/everything",
1187
      "open https://github.com/defunkt/hub/anything/everything"
1188 1189
  end

1190 1191 1192 1193
  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
1194 1195
  end

1196 1197 1198
  def test_hub_browse_no_repo
    stub_repo_url(nil)
    assert_equal "Usage: hub browse [<USER>/]<REPOSITORY>\n", hub("browse")
1199
  end
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209

  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
1210
      with_host_os("i686-linux") do
1211 1212 1213 1214 1215 1216 1217 1218
        assert_browser("xdg-open")
      end
    end
  end

  def test_cygwin_browser
    stub_available_commands "open", "cygstart"
    with_browser_env(nil) do
1219
      with_host_os("i686-linux") do
1220 1221 1222 1223 1224 1225 1226 1227 1228
        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
1229
      with_host_os("i686-linux") do
1230 1231 1232 1233 1234
        assert_equal expected, hub("browse")
      end
    end
  end

1235
  def test_context_method_doesnt_hijack_git_command
1236
    assert_forwarded 'remotes'
1237 1238
  end

1239 1240 1241 1242 1243
  def test_not_choking_on_ruby_methods
    assert_forwarded 'id'
    assert_forwarded 'name'
  end

1244 1245
  def test_multiple_remote_urls
    stub_repo_url("git://example.com/other.git\ngit://github.com/my/repo.git")
1246
    assert_command "browse", "open https://github.com/my/repo"
1247 1248
  end

1249 1250 1251
  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'
1252
    assert_equal %w[git --bare -c core.awesome=true -c name=value --git-dir=/srv/www], git_reader.executable
1253 1254
  end

1255
  private
1256

1257 1258 1259
    def stub_github_user(name, host = '')
      host = %(."#{host}") unless host.empty?
      stub_config_value "github#{host}.user", name
1260 1261
    end

1262 1263 1264
    def stub_github_token(token, host = '')
      host = %(."#{host}") unless host.empty?
      stub_config_value "github#{host}.token", token
1265 1266
    end

M
Mislav Marohnić 已提交
1267 1268
    def stub_repo_url(value, remote_name = 'origin')
      stub_config_value "remote.#{remote_name}.url", value, '--get-all'
1269 1270 1271
    end

    def stub_branch(value)
1272
      stub_command_output 'symbolic-ref -q HEAD', value
1273 1274
    end

1275
    def stub_tracking(from, remote_name, remote_branch)
1276 1277
      stub_command_output "rev-parse --symbolic-full-name #{from}@{upstream}",
        remote_branch ? "refs/remotes/#{remote_name}/#{remote_branch}" : nil
1278 1279
    end

1280 1281
    def stub_tracking_nothing(from = 'master')
      stub_tracking(from, nil, nil)
1282 1283
    end

1284
    def stub_remotes_group(name, value)
1285
      stub_config_value "remotes.#{name}", value
1286 1287
    end

1288
    def stub_no_remotes
1289
      stub_command_output 'remote', nil
1290 1291 1292
    end

    def stub_no_git_repo
1293
      stub_command_output 'rev-parse -q --git-dir', nil
1294 1295
    end

M
Mislav Marohnić 已提交
1296
    def stub_alias(name, value)
1297
      stub_config_value "alias.#{name}", value
M
Mislav Marohnić 已提交
1298 1299
    end

1300 1301
    def stub_existing_fork(user, repo = 'hub')
      stub_fork(user, repo, 200)
1302 1303
    end

1304 1305
    def stub_nonexisting_fork(user, repo = 'hub')
      stub_fork(user, repo, 404)
1306 1307
    end

1308
    def stub_fork(user, repo, status)
1309
      stub_request(:get, "https://#{auth}github.com/api/v2/yaml/repos/show/#{user}/#{repo}").
1310 1311 1312
        to_return(:status => status)
    end

1313 1314 1315 1316
    def stub_available_commands(*names)
      COMMANDS.replace names
    end

1317
    def stub_https_is_preferred
1318
      stub_config_value 'hub.protocol', 'https'
1319 1320
    end

1321 1322 1323 1324
    def stub_hub_host(names)
      stub_config_value "hub.host", Array(names).join("\n"), '--get-all'
    end

1325 1326 1327 1328 1329 1330 1331
    def with_browser_env(value)
      browser, ENV['BROWSER'] = ENV['BROWSER'], value
      yield
    ensure
      ENV['BROWSER'] = browser
    end

1332 1333 1334 1335 1336 1337 1338
    def with_tmpdir(value)
      dir, ENV['TMPDIR'] = ENV['TMPDIR'], value
      yield
    ensure
      ENV['TMPDIR'] = dir
    end

1339 1340 1341 1342 1343 1344 1345
    def with_host_env(value)
      host, ENV['GITHUB_HOST'] = ENV['GITHUB_HOST'], value
      yield
    ensure
      ENV['GITHUB_HOST'] = host
    end

1346
    def assert_browser(browser)
1347
      assert_command "browse", "#{browser} https://github.com/defunkt/hub"
1348 1349
    end

1350 1351 1352 1353 1354 1355 1356 1357
    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
1358 1359
    end

1360
    def auth(user = git_config('github.user'), password = git_config('github.token'))
1361 1362 1363
      "#{user}%2Ftoken:#{password}@"
    end

1364 1365
    def mock_pullreq_response(id, name_with_owner = 'defunkt/hub', host = 'github.com')
      %({"pull": { "html_url": "https://#{host}/#{name_with_owner}/pull/#{id}" }})
1366 1367
    end

1368 1369
    def mock_pull_response(label, priv = false)
      %({"pull": { "head": { "label": "#{label}", "repository": {"private":#{!!priv}} }}})
1370 1371
    end

1372 1373 1374 1375
    def improved_help_text
      Hub::Commands.send :improved_help_text
    end

C
Chris Wanstrath 已提交
1376
end