hub_test.rb 43.6 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 464
  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",
                      "am --signoff https://github.com/defunkt/hub/pull/55 -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 842
  end

  def test_pullrequest_explicit_head
843
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub").
844 845 846 847
      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"
848
    assert_output expected, "pull-request hereyougo -h yay-feature -f"
849 850 851
  end

  def test_pullrequest_explicit_head_with_owner
852
    stub_request(:post, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub").
853 854 855 856
      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"
857
    assert_output expected, "pull-request hereyougo -h mojombo:feature -f"
858 859 860
  end

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

    expected = "https://github.com/defunkt/hub/pull/1\n"
866
    assert_output expected, "pull-request hereyougo -b feature -f"
867 868 869
  end

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

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

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

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

  def test_pullrequest_existing_issue
M
Mislav Marohnić 已提交
888 889 890 891
    stub_branch('refs/heads/myfix')
    stub_tracking('myfix', 'mislav', 'awesomefix')
    stub_command_output "rev-list --cherry mislav/awesomefix...", nil

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

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

900
  def test_pullrequest_existing_issue_url
M
Mislav Marohnić 已提交
901 902 903 904
    stub_branch('refs/heads/myfix')
    stub_tracking('myfix', 'mislav', 'awesomefix')
    stub_command_output "rev-list --cherry mislav/awesomefix...", nil

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

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

913 914 915 916 917 918 919 920 921 922 923
  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

924 925 926 927 928
  def test_checkout_no_changes
    assert_forwarded "checkout master"
  end

  def test_checkout_pullrequest
929
    stub_request(:get, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub/73").
930 931 932 933 934 935 936
      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

937 938 939 940 941 942 943 944 945
  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

946
  def test_checkout_pullrequest_custom_branch
947
    stub_request(:get, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub/73").
948 949 950 951 952 953 954 955 956 957
      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"

958
    stub_request(:get, "https://#{auth}github.com/api/v2/json/pulls/defunkt/hub/73").
959 960 961 962 963 964 965 966
      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 已提交
967
  def test_version
968
    out = hub('--version')
969
    assert_includes "git version 1.7.0.4", out
C
Chris Wanstrath 已提交
970
    assert_includes "hub version #{Hub::Version}", out
C
Chris Wanstrath 已提交
971
  end
C
Chris Wanstrath 已提交
972

973 974 975 976 977 978 979
  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')
980
    assert_equal improved_help_text, out
981 982 983 984 985 986 987
  end

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

C
Chris Wanstrath 已提交
988
  def test_help
989
    assert_equal improved_help_text, hub("help")
C
Chris Wanstrath 已提交
990 991 992
  end

  def test_help_by_default
993
    assert_equal improved_help_text, hub("")
C
Chris Wanstrath 已提交
994
  end
C
Chris Wanstrath 已提交
995

S
Stephen Celis 已提交
996
  def test_help_with_pager
997
    assert_equal improved_help_text, hub("-p")
S
Stephen Celis 已提交
998 999
  end

C
Chris Wanstrath 已提交
1000 1001 1002 1003
  def test_help_hub
    help_manpage = hub("help hub")
    assert_includes "git + hub = github", help_manpage
    assert_includes <<-config, help_manpage
C
Chris Wanstrath 已提交
1004
Use git-config(1) to display the currently configured GitHub username:
C
Chris Wanstrath 已提交
1005 1006 1007 1008
config
  end

  def test_help_hub_no_groff
1009 1010
    stub_available_commands()
    assert_equal "** Can't find groff(1)\n", hub("help hub")
C
Chris Wanstrath 已提交
1011
  end
1012

1013 1014 1015 1016 1017
  def test_hub_standalone
    help_standalone = hub("hub standalone")
    assert_equal Hub::Standalone.build, help_standalone
  end

C
Chris Wanstrath 已提交
1018 1019
  def test_hub_compare
    assert_command "compare refactor",
1020
      "open https://github.com/defunkt/hub/compare/refactor"
1021
  end
C
Chris Wanstrath 已提交
1022

1023 1024 1025 1026
  def test_hub_compare_nothing
    expected = "Usage: hub compare [USER] [<START>...]<END>\n"
    assert_equal expected, hub("compare")
  end
C
Chris Wanstrath 已提交
1027

1028 1029 1030 1031 1032 1033 1034 1035
  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')
1036
    stub_tracking('feature', 'mislav', 'experimental')
1037 1038

    assert_command "compare",
1039
      "open https://github.com/mislav/hub/compare/experimental"
1040 1041
  end

1042
  def test_hub_compare_range
C
Chris Wanstrath 已提交
1043
    assert_command "compare 1.0...fix",
1044
      "open https://github.com/defunkt/hub/compare/1.0...fix"
1045
  end
C
Chris Wanstrath 已提交
1046

1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
  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

1062 1063 1064 1065 1066 1067
  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

1068
  def test_hub_compare_fork
C
Chris Wanstrath 已提交
1069
    assert_command "compare myfork feature",
1070
      "open https://github.com/myfork/hub/compare/feature"
1071 1072 1073 1074
  end

  def test_hub_compare_url
    assert_command "compare -u 1.0...1.1",
1075
      "echo https://github.com/defunkt/hub/compare/1.0...1.1"
1076 1077 1078
  end

  def test_hub_browse
1079
    assert_command "browse mojombo/bert", "open https://github.com/mojombo/bert"
1080 1081
  end

1082 1083 1084 1085
  def test_hub_browse_commit
    assert_command "browse mojombo/bert commit/5d5582", "open https://github.com/mojombo/bert/commit/5d5582"
  end

1086 1087
  def test_hub_browse_tracking_nothing
    stub_tracking_nothing
1088
    assert_command "browse mojombo/bert", "open https://github.com/mojombo/bert"
1089 1090
  end

1091
  def test_hub_browse_url
1092
    assert_command "browse -u mojombo/bert", "echo https://github.com/mojombo/bert"
1093 1094
  end

1095
  def test_hub_browse_self
1096
    assert_command "browse resque", "open https://github.com/tpw/resque"
1097 1098
  end

1099 1100
  def test_hub_browse_subpage
    assert_command "browse resque commits",
1101
      "open https://github.com/tpw/resque/commits/master"
1102
    assert_command "browse resque issues",
1103
      "open https://github.com/tpw/resque/issues"
1104
    assert_command "browse resque wiki",
1105
      "open https://github.com/tpw/resque/wiki"
1106 1107 1108 1109
  end

  def test_hub_browse_on_branch
    stub_branch('refs/heads/feature')
1110
    stub_tracking('feature', 'mislav', 'experimental')
1111

1112
    assert_command "browse resque", "open https://github.com/tpw/resque"
1113
    assert_command "browse resque commits",
1114
      "open https://github.com/tpw/resque/commits/master"
1115 1116

    assert_command "browse",
1117
      "open https://github.com/mislav/hub/tree/experimental"
1118
    assert_command "browse -- tree",
1119
      "open https://github.com/mislav/hub/tree/experimental"
1120
    assert_command "browse -- commits",
1121
      "open https://github.com/mislav/hub/commits/experimental"
1122
  end
1123

1124 1125 1126 1127 1128 1129 1130 1131
  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

1132
  def test_hub_browse_current
1133 1134
    assert_command "browse", "open https://github.com/defunkt/hub"
    assert_command "browse --", "open https://github.com/defunkt/hub"
1135 1136
  end

1137 1138 1139 1140 1141
  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

1142 1143 1144 1145
  def test_hub_browse_commit_from_current
    assert_command "browse -- commit/6616e4", "open https://github.com/defunkt/hub/commit/6616e4"
  end

1146 1147 1148 1149 1150 1151 1152
  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')
1153
    stub_tracking_nothing('feature')
1154 1155 1156
    assert_command "browse", "open https://github.com/defunkt/hub"
  end

1157 1158 1159 1160 1161 1162 1163 1164 1165
  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

1166 1167
  def test_hub_browse_current_subpage
    assert_command "browse -- network",
1168
      "open https://github.com/defunkt/hub/network"
1169
    assert_command "browse -- anything/everything",
1170
      "open https://github.com/defunkt/hub/anything/everything"
1171 1172
  end

1173 1174 1175 1176
  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
1177 1178
  end

1179 1180 1181
  def test_hub_browse_no_repo
    stub_repo_url(nil)
    assert_equal "Usage: hub browse [<USER>/]<REPOSITORY>\n", hub("browse")
1182
  end
1183 1184 1185 1186 1187 1188 1189 1190 1191 1192

  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
1193
      with_host_os("i686-linux") do
1194 1195 1196 1197 1198 1199 1200 1201
        assert_browser("xdg-open")
      end
    end
  end

  def test_cygwin_browser
    stub_available_commands "open", "cygstart"
    with_browser_env(nil) do
1202
      with_host_os("i686-linux") do
1203 1204 1205 1206 1207 1208 1209 1210 1211
        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
1212
      with_host_os("i686-linux") do
1213 1214 1215 1216 1217
        assert_equal expected, hub("browse")
      end
    end
  end

1218
  def test_context_method_doesnt_hijack_git_command
1219
    assert_forwarded 'remotes'
1220 1221
  end

1222 1223 1224 1225 1226
  def test_not_choking_on_ruby_methods
    assert_forwarded 'id'
    assert_forwarded 'name'
  end

1227 1228
  def test_multiple_remote_urls
    stub_repo_url("git://example.com/other.git\ngit://github.com/my/repo.git")
1229
    assert_command "browse", "open https://github.com/my/repo"
1230 1231
  end

1232 1233 1234
  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'
1235
    assert_equal %w[git --bare -c core.awesome=true -c name=value --git-dir=/srv/www], git_reader.executable
1236 1237
  end

1238
  private
1239

1240 1241 1242
    def stub_github_user(name, host = '')
      host = %(."#{host}") unless host.empty?
      stub_config_value "github#{host}.user", name
1243 1244
    end

1245 1246 1247
    def stub_github_token(token, host = '')
      host = %(."#{host}") unless host.empty?
      stub_config_value "github#{host}.token", token
1248 1249
    end

M
Mislav Marohnić 已提交
1250 1251
    def stub_repo_url(value, remote_name = 'origin')
      stub_config_value "remote.#{remote_name}.url", value, '--get-all'
1252 1253 1254
    end

    def stub_branch(value)
1255
      stub_command_output 'symbolic-ref -q HEAD', value
1256 1257
    end

1258
    def stub_tracking(from, remote_name, remote_branch)
1259 1260
      stub_command_output "rev-parse --symbolic-full-name #{from}@{upstream}",
        remote_branch ? "refs/remotes/#{remote_name}/#{remote_branch}" : nil
1261 1262
    end

1263 1264
    def stub_tracking_nothing(from = 'master')
      stub_tracking(from, nil, nil)
1265 1266
    end

1267
    def stub_remotes_group(name, value)
1268
      stub_config_value "remotes.#{name}", value
1269 1270
    end

1271
    def stub_no_remotes
1272
      stub_command_output 'remote', nil
1273 1274 1275
    end

    def stub_no_git_repo
1276
      stub_command_output 'rev-parse -q --git-dir', nil
1277 1278
    end

M
Mislav Marohnić 已提交
1279
    def stub_alias(name, value)
1280
      stub_config_value "alias.#{name}", value
M
Mislav Marohnić 已提交
1281 1282
    end

1283 1284
    def stub_existing_fork(user, repo = 'hub')
      stub_fork(user, repo, 200)
1285 1286
    end

1287 1288
    def stub_nonexisting_fork(user, repo = 'hub')
      stub_fork(user, repo, 404)
1289 1290
    end

1291
    def stub_fork(user, repo, status)
1292
      stub_request(:get, "https://#{auth}github.com/api/v2/yaml/repos/show/#{user}/#{repo}").
1293 1294 1295
        to_return(:status => status)
    end

1296 1297 1298 1299
    def stub_available_commands(*names)
      COMMANDS.replace names
    end

1300
    def stub_https_is_preferred
1301
      stub_config_value 'hub.protocol', 'https'
1302 1303
    end

1304 1305 1306 1307
    def stub_hub_host(names)
      stub_config_value "hub.host", Array(names).join("\n"), '--get-all'
    end

1308 1309 1310 1311 1312 1313 1314
    def with_browser_env(value)
      browser, ENV['BROWSER'] = ENV['BROWSER'], value
      yield
    ensure
      ENV['BROWSER'] = browser
    end

1315 1316 1317 1318 1319 1320 1321
    def with_tmpdir(value)
      dir, ENV['TMPDIR'] = ENV['TMPDIR'], value
      yield
    ensure
      ENV['TMPDIR'] = dir
    end

1322 1323 1324 1325 1326 1327 1328
    def with_host_env(value)
      host, ENV['GITHUB_HOST'] = ENV['GITHUB_HOST'], value
      yield
    ensure
      ENV['GITHUB_HOST'] = host
    end

1329
    def assert_browser(browser)
1330
      assert_command "browse", "#{browser} https://github.com/defunkt/hub"
1331 1332
    end

1333 1334 1335 1336 1337 1338 1339 1340
    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
1341 1342
    end

1343
    def auth(user = git_config('github.user'), password = git_config('github.token'))
1344 1345 1346
      "#{user}%2Ftoken:#{password}@"
    end

1347
    def mock_pullreq_response(id, name_with_owner = 'defunkt/hub')
1348
      %({"pull": { "html_url": "https://github.com/#{name_with_owner}/pull/#{id}" }})
1349 1350
    end

1351 1352
    def mock_pull_response(label, priv = false)
      %({"pull": { "head": { "label": "#{label}", "repository": {"private":#{!!priv}} }}})
1353 1354
    end

1355 1356 1357 1358
    def improved_help_text
      Hub::Commands.send :improved_help_text
    end

C
Chris Wanstrath 已提交
1359
end