hub_test.rb 30.0 KB
Newer Older
1 2
$LOAD_PATH.unshift File.dirname(__FILE__)
require 'helper'
3
require 'webmock/test_unit'
4
require 'rbconfig'
C
Chris Wanstrath 已提交
5

6 7 8 9 10 11
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 已提交
12
class HubTest < Test::Unit::TestCase
13 14 15 16 17
  if defined? WebMock::API
    include WebMock::API
  else
    include WebMock
  end
C
Chris Wanstrath 已提交
18

19 20
  COMMANDS = []

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

28
  def setup
29
    COMMANDS.replace %w[open groff]
30
    Hub::Context::DIRNAME.replace 'hub'
31
    Hub::Context::REMOTES.clear
32

33 34
    Hub::Context::GIT_CONFIG.executable = 'git'

35
    @git = Hub::Context::GIT_CONFIG.replace(Hash.new { |h, k|
M
Mislav Marohnić 已提交
36 37 38
      unless k.index('config alias.') == 0
        raise ArgumentError, "`git #{k}` not stubbed"
      end
39
    }).update(
40
      'remote' => "mislav\norigin",
41 42 43
      'symbolic-ref -q HEAD' => 'refs/heads/master',
      'config github.user'   => 'tpw',
      'config github.token'  => 'abc123',
44 45
      'config --get-all remote.origin.url' => 'git://github.com/defunkt/hub.git',
      'config --get-all remote.mislav.url' => 'git://github.com/mislav/hub.git',
46 47
      'config branch.master.remote'  => 'origin',
      'config branch.master.merge'   => 'refs/heads/master',
48
      'config --bool hub.http-clone' => 'false',
49
      'rev-parse --git-dir' => '.git'
50
    )
51
    super
52 53
  end

C
Chris Wanstrath 已提交
54
  def test_private_clone
55 56
    input   = "clone -p rtomayko/ronn"
    command = "git clone git@github.com:rtomayko/ronn.git"
C
Chris Wanstrath 已提交
57
    assert_command input, command
C
Chris Wanstrath 已提交
58 59 60
  end

  def test_public_clone
61 62
    input   = "clone rtomayko/ronn"
    command = "git clone git://github.com/rtomayko/ronn.git"
C
Chris Wanstrath 已提交
63
    assert_command input, command
C
Chris Wanstrath 已提交
64 65
  end

66 67 68 69 70 71 72 73 74 75 76 77
  def test_your_private_clone
    input   = "clone -p resque"
    command = "git clone git@github.com:tpw/resque.git"
    assert_command input, command
  end

  def test_your_public_clone
    input   = "clone resque"
    command = "git clone git://github.com/tpw/resque.git"
    assert_command input, command
  end

78 79 80
  def test_clone_with_arguments
    input   = "clone --bare -o master resque"
    command = "git clone --bare -o master git://github.com/tpw/resque.git"
81 82 83
    assert_command input, command
  end

84 85 86 87
  def test_clone_with_arguments_and_destination
    assert_forwarded "clone --template=one/two git://github.com/tpw/resque.git --origin master resquetastic"
  end

88 89
  def test_your_private_clone_fails_without_config
    out = hub("clone -p mustache") do
90
      stub_github_user(nil)
91 92
    end

93
    assert_equal "** No GitHub user set. See http://help.github.com/git-email-settings/\n", out
94 95 96 97
  end

  def test_your_public_clone_fails_without_config
    out = hub("clone mustache") do
98
      stub_github_user(nil)
99 100
    end

101
    assert_equal "** No GitHub user set. See http://help.github.com/git-email-settings/\n", out
102 103
  end

104
  def test_private_clone_left_alone
105
    assert_forwarded "clone git@github.com:rtomayko/ronn.git"
106 107 108
  end

  def test_public_clone_left_alone
109
    assert_forwarded "clone git://github.com/rtomayko/ronn.git"
110
  end
C
Chris Wanstrath 已提交
111 112

  def test_normal_public_clone_with_path
113
    assert_forwarded "clone git://github.com/rtomayko/ronn.git ronn-dev"
C
Chris Wanstrath 已提交
114
  end
115 116

  def test_normal_clone_from_path
117
    assert_forwarded "clone ./test"
118
  end
119

M
Mislav Marohnić 已提交
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
  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

139 140 141 142 143 144 145 146 147 148 149 150
  def test_remote_origin
    input   = "remote add origin"
    command = "git remote add origin git://github.com/tpw/hub.git"
    assert_command input, command
  end

  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

151 152 153 154 155 156
  def test_public_remote_origin_as_normal
    input   = "remote add origin http://github.com/defunkt/resque.git"
    command = "git remote add origin http://github.com/defunkt/resque.git"
    assert_command input, command
  end

157
  def test_remote_from_rel_path
158
    assert_forwarded "remote add origin ./path"
159 160 161
  end

  def test_remote_from_abs_path
162
    assert_forwarded "remote add origin /path"
163 164
  end

165
  def test_private_remote_origin_as_normal
166
    assert_forwarded "remote add origin git@github.com:defunkt/resque.git"
C
Chris Wanstrath 已提交
167 168
  end

S
Stephen Celis 已提交
169 170
  def test_public_submodule
    input   = "submodule add wycats/bundler vendor/bundler"
J
Justin Ridgewell 已提交
171 172
    command = "git submodule add git://github.com/wycats/bundler.git vendor/bundler"
    assert_command input, command
S
Stephen Celis 已提交
173 174 175 176
  end

  def test_private_submodule
    input   = "submodule add -p grit vendor/grit"
J
Justin Ridgewell 已提交
177 178 179 180 181 182 183 184
    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 已提交
185 186 187 188 189
  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 已提交
190
    assert_command input, command
S
Stephen Celis 已提交
191 192
  end

C
Chris Wanstrath 已提交
193
  def test_private_remote
194
    input   = "remote add -p rtomayko"
C
Chris Wanstrath 已提交
195 196
    command = "git remote add rtomayko git@github.com:rtomayko/hub.git"
    assert_command input, command
C
Chris Wanstrath 已提交
197 198 199
  end

  def test_public_remote
200
    input   = "remote add rtomayko"
C
Chris Wanstrath 已提交
201 202
    command = "git remote add rtomayko git://github.com/rtomayko/hub.git"
    assert_command input, command
C
Chris Wanstrath 已提交
203 204
  end

C
Chris Wanstrath 已提交
205 206 207 208 209 210
  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

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

217 218 219 220 221 222
  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 已提交
223
  def test_private_remote_with_repo
224 225
    input   = "remote add -p jashkenas/coffee-script"
    command = "git remote add jashkenas git@github.com:jashkenas/coffee-script.git"
C
Chris Wanstrath 已提交
226 227 228 229
    assert_command input, command
  end

  def test_public_remote_with_repo
230 231
    input   = "remote add jashkenas/coffee-script"
    command = "git remote add jashkenas git://github.com/jashkenas/coffee-script.git"
232 233 234 235
    assert_command input, command
  end

  def test_public_remote_f_with_repo
236 237
    input   = "remote add -f jashkenas/coffee-script"
    command = "git remote add -f jashkenas git://github.com/jashkenas/coffee-script.git"
C
Chris Wanstrath 已提交
238 239 240
    assert_command input, command
  end

241
  def test_named_private_remote_with_repo
242 243
    input   = "remote add -p origin jashkenas/coffee-script"
    command = "git remote add origin git@github.com:jashkenas/coffee-script.git"
244 245 246
    assert_command input, command
  end

247
  def test_fetch_existing_remote
248
    assert_forwarded "fetch mislav"
249 250 251 252 253 254
  end

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

255 256 257
    assert_commands "git remote add xoebus git://github.com/xoebus/hub.git",
                    "git fetch xoebus",
                    "fetch xoebus"
258 259 260 261 262 263
  end

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

264 265 266
    assert_commands "git remote add xoebus git://github.com/xoebus/hub.git",
                    "git fetch --depth=1 --prune xoebus",
                    "fetch --depth=1 --prune xoebus"
267 268 269 270 271 272 273 274
  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')

275 276 277 278
    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"
279 280 281 282 283 284 285 286
  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')

287 288 289 290
    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"
291 292 293 294 295 296 297 298 299 300 301 302 303 304
  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
305 306 307
    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"
308 309
  end

310
  def test_cherry_pick
311
    assert_forwarded "cherry-pick a319d88"
312 313 314
  end

  def test_cherry_pick_url
315
    url = 'http://github.com/mislav/hub/commit/a319d88'
316
    assert_commands "git fetch mislav", "git cherry-pick a319d88", "cherry-pick #{url}"
317 318
  end

319 320
  def test_cherry_pick_url_with_fragment
    url = 'http://github.com/mislav/hub/commit/abcdef0123456789#comments'
321
    assert_commands "git fetch mislav", "git cherry-pick abcdef0123456789", "cherry-pick #{url}"
322 323
  end

324 325
  def test_cherry_pick_url_with_remote_add
    url = 'https://github.com/xoebus/hub/commit/a319d88'
326
    assert_commands "git remote add -f xoebus git://github.com/xoebus/hub.git",
327 328
                    "git cherry-pick a319d88",
                    "cherry-pick #{url}"
329 330 331 332
  end

  def test_cherry_pick_origin_url
    url = 'https://github.com/defunkt/hub/commit/a319d88'
333
    assert_commands "git fetch origin", "git cherry-pick a319d88", "cherry-pick #{url}"
334 335 336
  end

  def test_cherry_pick_github_user_notation
337
    assert_commands "git fetch mislav", "git cherry-pick 368af20", "cherry-pick mislav@368af20"
338 339 340 341
  end

  def test_cherry_pick_github_user_repo_notation
    # not supported
342
    assert_forwarded "cherry-pick mislav/hubbub@a319d88"
343 344 345
  end

  def test_cherry_pick_github_notation_too_short
346
    assert_forwarded "cherry-pick mislav@a319"
347 348 349
  end

  def test_cherry_pick_github_notation_with_remote_add
350 351 352
    assert_commands "git remote add -f xoebus git://github.com/xoebus/hub.git",
                    "git cherry-pick a319d88",
                    "cherry-pick xoebus@a319d88"
353 354
  end

355 356 357 358 359 360 361 362 363
  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"
364 365 366

      cmd = Hub("am https://github.com/defunkt/hub/pull/55/files").command
      assert_includes '/pull/55.patch', cmd
367 368 369 370 371 372 373 374 375 376 377 378 379
    end
  end

  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

380 381 382 383 384 385 386 387 388 389
  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

390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
  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 已提交
425
  def test_init
426
    assert_commands "git init", "git remote add origin git@github.com:tpw/hub.git", "init -g"
427 428 429 430
  end

  def test_init_no_login
    out = hub("init -g") do
431
      stub_github_user(nil)
432 433
    end

434
    assert_equal "** No GitHub user set. See http://help.github.com/git-email-settings/\n", out
C
Chris Wanstrath 已提交
435 436
  end

437 438 439 440
  def test_push_untouched
    assert_forwarded "push"
  end

441
  def test_push_two
442 443
    assert_commands "git push origin cool-feature", "git push staging cool-feature",
                    "push origin,staging cool-feature"
444 445
  end

446 447 448 449 450 451
  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 已提交
452
  def test_push_more
453 454 455 456
    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 已提交
457
  end
C
Chris Wanstrath 已提交
458

459
  def test_create
460
    stub_no_remotes
461
    stub_nonexisting_fork('tpw')
462 463
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
      with(:body => { 'name' => 'hub' })
464

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

470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
  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

492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
  def test_create_no_openssl
    stub_no_remotes
    stub_nonexisting_fork('tpw')
    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

508 509 510
  def test_create_failed
    stub_no_remotes
    stub_nonexisting_fork('tpw')
511
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
512 513
      to_return(:status => [401, "Your token is fail"])

514 515
    expected = "Error creating repository: Your token is fail (HTTP 401)\n"
    expected << "Check your token configuration (`git config github.token`)\n"
516 517 518
    assert_equal expected, hub("create") { ENV['GIT'] = 'echo' }
  end

519 520 521 522 523 524 525 526 527
  def test_create_with_env_authentication
    stub_no_remotes
    stub_nonexisting_fork('mojombo')

    old_user  = ENV['GITHUB_USER']
    old_token = ENV['GITHUB_TOKEN']
    ENV['GITHUB_USER']  = 'mojombo'
    ENV['GITHUB_TOKEN'] = '123abc'

528 529
    stub_request(:post, "https://#{auth('mojombo', '123abc')}github.com/api/v2/yaml/repos/create").
      with(:body => { 'name' => 'hub' })
530 531 532 533 534 535 536 537 538 539

    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

540
  def test_create_private_repository
541
    stub_no_remotes
542
    stub_nonexisting_fork('tpw')
543 544
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
      with(:body => { 'name' => 'hub', 'public' => '0' })
545

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

551
  def test_create_with_description_and_homepage
552
    stub_no_remotes
553
    stub_nonexisting_fork('tpw')
554 555
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").with(:body => {
      'name' => 'hub', 'description' => 'toyproject', 'homepage' => 'http://example.com'
556 557
    })

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

563 564 565 566 567
  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

568
  def test_create_with_existing_repository
569
    stub_no_remotes
570 571 572 573
    stub_existing_fork('tpw')

    expected = "tpw/hub already exists on GitHub\n"
    expected << "remote add -f origin git@github.com:tpw/hub.git\n"
574
    expected << "set remote origin: tpw/hub\n"
575 576 577
    assert_equal expected, hub("create") { ENV['GIT'] = 'echo' }
  end

578
  def test_create_no_user
579
    stub_no_remotes
580 581 582
    out = hub("create") do
      stub_github_token(nil)
    end
583
    assert_equal "** No GitHub token set. See http://help.github.com/git-email-settings/\n", out
584 585
  end

586
  def test_create_outside_git_repo
587
    stub_no_git_repo
588 589
    assert_equal "'create' must be run from inside a git repository\n", hub("create")
  end
590 591

  def test_create_origin_already_exists
C
Chris Wanstrath 已提交
592
    stub_nonexisting_fork('tpw')
593 594
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
      with(:body => { 'name' => 'hub' })
C
Chris Wanstrath 已提交
595 596

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

600
  def test_fork
C
Chris Wanstrath 已提交
601
    stub_nonexisting_fork('tpw')
602
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/fork/defunkt/hub")
C
Chris Wanstrath 已提交
603

C
Chris Wanstrath 已提交
604
    expected = "remote add -f tpw git@github.com:tpw/hub.git\n"
605 606 607 608
    expected << "new remote: tpw\n"
    assert_equal expected, hub("fork") { ENV['GIT'] = 'echo' }
  end

609 610
  def test_fork_failed
    stub_nonexisting_fork('tpw')
611
    stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/fork/defunkt/hub").
612 613
      to_return(:status => [500, "Your fork is fail"])

614
    expected = "Error creating fork: Your fork is fail (HTTP 500)\n"
615 616 617
    assert_equal expected, hub("fork") { ENV['GIT'] = 'echo' }
  end

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

622 623 624 625
    assert_equal "", hub("fork --no-remote") { ENV['GIT'] = 'echo' }
  end

  def test_fork_already_exists
626
    stub_existing_fork('tpw')
C
Chris Wanstrath 已提交
627

628
    expected = "tpw/hub already exists on GitHub\n"
C
Chris Wanstrath 已提交
629
    expected << "remote add -f tpw git@github.com:tpw/hub.git\n"
630 631 632
    expected << "new remote: tpw\n"
    assert_equal expected, hub("fork") { ENV['GIT'] = 'echo' }
  end
C
Chris Wanstrath 已提交
633

C
Chris Wanstrath 已提交
634
  def test_version
635
    out = hub('--version')
636
    assert_includes "git version 1.7.0.4", out
C
Chris Wanstrath 已提交
637
    assert_includes "hub version #{Hub::Version}", out
C
Chris Wanstrath 已提交
638
  end
C
Chris Wanstrath 已提交
639

640 641 642 643 644 645 646
  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')
647
    assert_equal Hub::Commands.improved_help_text, out
648 649 650 651 652 653 654
  end

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

C
Chris Wanstrath 已提交
655 656 657 658 659 660 661
  def test_help
    assert_equal Hub::Commands.improved_help_text, hub("help")
  end

  def test_help_by_default
    assert_equal Hub::Commands.improved_help_text, hub("")
  end
C
Chris Wanstrath 已提交
662

S
Stephen Celis 已提交
663 664 665 666
  def test_help_with_pager
    assert_equal Hub::Commands.improved_help_text, hub("-p")
  end

C
Chris Wanstrath 已提交
667 668 669 670
  def test_help_hub
    help_manpage = hub("help hub")
    assert_includes "git + hub = github", help_manpage
    assert_includes <<-config, help_manpage
C
Chris Wanstrath 已提交
671
Use git-config(1) to display the currently configured GitHub username:
C
Chris Wanstrath 已提交
672 673 674 675
config
  end

  def test_help_hub_no_groff
676 677
    stub_available_commands()
    assert_equal "** Can't find groff(1)\n", hub("help hub")
C
Chris Wanstrath 已提交
678
  end
679

680 681 682 683 684
  def test_hub_standalone
    help_standalone = hub("hub standalone")
    assert_equal Hub::Standalone.build, help_standalone
  end

C
Chris Wanstrath 已提交
685 686
  def test_hub_compare
    assert_command "compare refactor",
687
      "open https://github.com/defunkt/hub/compare/refactor"
688
  end
C
Chris Wanstrath 已提交
689

690 691 692 693
  def test_hub_compare_nothing
    expected = "Usage: hub compare [USER] [<START>...]<END>\n"
    assert_equal expected, hub("compare")
  end
C
Chris Wanstrath 已提交
694

695 696 697 698 699 700 701 702
  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')
703
    stub_tracking('feature', 'mislav', 'refs/heads/experimental')
704 705

    assert_command "compare",
706
      "open https://github.com/mislav/hub/compare/experimental"
707 708
  end

709
  def test_hub_compare_range
C
Chris Wanstrath 已提交
710
    assert_command "compare 1.0...fix",
711
      "open https://github.com/defunkt/hub/compare/1.0...fix"
712
  end
C
Chris Wanstrath 已提交
713

714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
  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

729 730 731 732 733 734
  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

735
  def test_hub_compare_fork
C
Chris Wanstrath 已提交
736
    assert_command "compare myfork feature",
737
      "open https://github.com/myfork/hub/compare/feature"
738 739 740 741
  end

  def test_hub_compare_url
    assert_command "compare -u 1.0...1.1",
742
      "echo https://github.com/defunkt/hub/compare/1.0...1.1"
743 744 745
  end

  def test_hub_browse
746
    assert_command "browse mojombo/bert", "open https://github.com/mojombo/bert"
747 748
  end

749 750 751 752
  def test_hub_browse_commit
    assert_command "browse mojombo/bert commit/5d5582", "open https://github.com/mojombo/bert/commit/5d5582"
  end

753 754
  def test_hub_browse_tracking_nothing
    stub_tracking_nothing
755
    assert_command "browse mojombo/bert", "open https://github.com/mojombo/bert"
756 757
  end

758
  def test_hub_browse_url
759
    assert_command "browse -u mojombo/bert", "echo https://github.com/mojombo/bert"
760 761
  end

762
  def test_hub_browse_self
763
    assert_command "browse resque", "open https://github.com/tpw/resque"
764 765
  end

766 767
  def test_hub_browse_subpage
    assert_command "browse resque commits",
768
      "open https://github.com/tpw/resque/commits/master"
769
    assert_command "browse resque issues",
770
      "open https://github.com/tpw/resque/issues"
771
    assert_command "browse resque wiki",
772
      "open https://github.com/tpw/resque/wiki"
773 774 775 776
  end

  def test_hub_browse_on_branch
    stub_branch('refs/heads/feature')
777
    stub_tracking('feature', 'mislav', 'refs/heads/experimental')
778

779
    assert_command "browse resque", "open https://github.com/tpw/resque"
780
    assert_command "browse resque commits",
781
      "open https://github.com/tpw/resque/commits/master"
782 783

    assert_command "browse",
784
      "open https://github.com/mislav/hub/tree/experimental"
785
    assert_command "browse -- tree",
786
      "open https://github.com/mislav/hub/tree/experimental"
787
    assert_command "browse -- commits",
788
      "open https://github.com/mislav/hub/commits/experimental"
789
  end
790

791
  def test_hub_browse_current
792 793
    assert_command "browse", "open https://github.com/defunkt/hub"
    assert_command "browse --", "open https://github.com/defunkt/hub"
794 795
  end

796 797 798 799
  def test_hub_browse_commit_from_current
    assert_command "browse -- commit/6616e4", "open https://github.com/defunkt/hub/commit/6616e4"
  end

800 801 802 803 804 805 806 807 808 809 810
  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')
    stub_tracking('feature', nil, nil)
    assert_command "browse", "open https://github.com/defunkt/hub"
  end

811 812 813 814 815 816 817 818 819
  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

820 821
  def test_hub_browse_current_subpage
    assert_command "browse -- network",
822
      "open https://github.com/defunkt/hub/network"
823
    assert_command "browse -- anything/everything",
824
      "open https://github.com/defunkt/hub/anything/everything"
825 826
  end

827 828 829 830
  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
831 832
  end

833 834 835
  def test_hub_browse_no_repo
    stub_repo_url(nil)
    assert_equal "Usage: hub browse [<USER>/]<REPOSITORY>\n", hub("browse")
836
  end
837 838 839 840 841 842 843 844 845 846

  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
847
      with_host_os("i686-linux") do
848 849 850 851 852 853 854 855
        assert_browser("xdg-open")
      end
    end
  end

  def test_cygwin_browser
    stub_available_commands "open", "cygstart"
    with_browser_env(nil) do
856
      with_host_os("i686-linux") do
857 858 859 860 861 862 863 864 865
        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
866
      with_host_os("i686-linux") do
867 868 869 870 871
        assert_equal expected, hub("browse")
      end
    end
  end

872
  def test_context_method_doesnt_hijack_git_command
873
    assert_forwarded 'remotes'
874 875
  end

876 877 878 879 880
  def test_not_choking_on_ruby_methods
    assert_forwarded 'id'
    assert_forwarded 'name'
  end

881 882
  def test_multiple_remote_urls
    stub_repo_url("git://example.com/other.git\ngit://github.com/my/repo.git")
883
    assert_command "browse", "open https://github.com/my/repo"
884 885
  end

886 887 888 889 890 891
  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'
    assert_equal %w[git --bare -c core.awesome=true -c name=value --git-dir=/srv/www], @git.executable
  end

892 893
  protected

894 895 896 897
    def stub_github_user(name)
      @git['config github.user'] = name
    end

898 899 900 901
    def stub_github_token(token)
      @git['config github.token'] = token
    end

902
    def stub_repo_url(value)
903
      @git['config --get-all remote.origin.url'] = value
904 905 906 907 908 909 910
      Hub::Context::REMOTES.clear
    end

    def stub_branch(value)
      @git['symbolic-ref -q HEAD'] = value
    end

911 912 913 914 915
    def stub_tracking(from, remote_name, remote_branch)
      @git["config branch.#{from}.remote"] = remote_name
      @git["config branch.#{from}.merge"] = remote_branch
    end

916
    def stub_tracking_nothing
917
      stub_tracking('master', nil, nil)
918 919
    end

920 921 922 923
    def stub_remotes_group(name, value)
      @git["config remotes.#{name}"] = value
    end

924 925 926 927 928 929 930 931
    def stub_no_remotes
      @git['remote'] = ''
    end

    def stub_no_git_repo
      @git.replace({})
    end

M
Mislav Marohnić 已提交
932 933 934 935
    def stub_alias(name, value)
      @git["config alias.#{name}"] = value
    end

936 937
    def stub_existing_fork(user, repo = 'hub')
      stub_fork(user, repo, 200)
938 939
    end

940 941
    def stub_nonexisting_fork(user, repo = 'hub')
      stub_fork(user, repo, 404)
942 943
    end

944 945
    def stub_fork(user, repo, status)
      stub_request(:get, "github.com/api/v2/yaml/repos/show/#{user}/#{repo}").
946 947 948
        to_return(:status => status)
    end

949 950 951 952 953 954 955 956 957 958 959
    def stub_available_commands(*names)
      COMMANDS.replace names
    end

    def with_browser_env(value)
      browser, ENV['BROWSER'] = ENV['BROWSER'], value
      yield
    ensure
      ENV['BROWSER'] = browser
    end

960 961 962 963 964 965 966
    def with_tmpdir(value)
      dir, ENV['TMPDIR'] = ENV['TMPDIR'], value
      yield
    ensure
      ENV['TMPDIR'] = dir
    end

967
    def assert_browser(browser)
968
      assert_command "browse", "#{browser} https://github.com/defunkt/hub"
969 970
    end

971 972 973 974 975 976 977 978
    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
979 980
    end

981 982 983 984
    def auth(user = @git['config github.user'], password = @git['config github.token'])
      "#{user}%2Ftoken:#{password}@"
    end

C
Chris Wanstrath 已提交
985
end