hub_test.rb 24.8 KB
Newer Older
1
require 'helper'
2
require 'webmock/test_unit'
3
require 'rbconfig'
4
require 'yaml'
5
require 'forwardable'
6
require 'fileutils'
M
Mislav Marohnić 已提交
7
require 'tempfile'
C
Chris Wanstrath 已提交
8

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

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

24 25
  COMMANDS = []

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

33 34 35 36
  attr_reader :git_reader
  include Hub::Context::GitReaderMethods
  def_delegators :git_reader, :stub_config_value, :stub_command_output

37
  def setup
38
    super
39
    COMMANDS.replace %w[open groff]
40
    Hub::Context::PWD.replace '/path/to/hub'
41
    Hub::SshConfig::CONFIG_FILES.replace []
42

43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
    @prompt_stubs = prompt_stubs = []
    @password_prompt_stubs = password_prompt_stubs = []

    Hub::GitHubAPI::Configuration.class_eval do
      undef prompt
      undef prompt_password

      define_method :prompt do |what|
        prompt_stubs.shift.call(what)
      end
      define_method :prompt_password do |host, user|
        password_prompt_stubs.shift.call(host, user)
      end
    end

58 59 60
    @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ć 已提交
61
      end
62 63 64 65
    end

    Hub::Commands.instance_variable_set :@git_reader, @git_reader
    Hub::Commands.instance_variable_set :@local_repo, nil
66 67 68 69 70 71 72
    Hub::Commands.instance_variable_set :@api_client, nil

    FileUtils.rm_rf ENV['HUB_CONFIG']

    edit_hub_config do |data|
      data['github.com'] = [{'user' => 'tpw', 'oauth_token' => 'OTOKEN'}]
    end
73 74

    @git_reader.stub! \
75
      'remote' => "mislav\norigin",
76
      'symbolic-ref -q HEAD' => 'refs/heads/master',
77 78
      'config --get-all remote.origin.url' => 'git://github.com/defunkt/hub.git',
      'config --get-all remote.mislav.url' => 'git://github.com/mislav/hub.git',
79
      'rev-parse --symbolic-full-name master@{upstream}' => 'refs/remotes/origin/master',
80 81
      'config --get --bool hub.http-clone' => 'false',
      'config --get hub.protocol' => nil,
82
      'config --get-all hub.host' => nil,
83
      'rev-parse -q --git-dir' => '.git'
84 85
  end

86
  def test_cherry_pick
87
    assert_forwarded "cherry-pick a319d88"
88 89 90
  end

  def test_cherry_pick_url
91
    url = 'http://github.com/mislav/hub/commit/a319d88'
92
    assert_commands "git fetch mislav", "git cherry-pick a319d88", "cherry-pick #{url}"
93 94
  end

95 96
  def test_cherry_pick_url_with_fragment
    url = 'http://github.com/mislav/hub/commit/abcdef0123456789#comments'
97
    assert_commands "git fetch mislav", "git cherry-pick abcdef0123456789", "cherry-pick #{url}"
98 99
  end

100 101
  def test_cherry_pick_url_with_remote_add
    url = 'https://github.com/xoebus/hub/commit/a319d88'
102
    assert_commands "git remote add -f xoebus git://github.com/xoebus/hub.git",
103 104
                    "git cherry-pick a319d88",
                    "cherry-pick #{url}"
105 106 107 108
  end

  def test_cherry_pick_origin_url
    url = 'https://github.com/defunkt/hub/commit/a319d88'
109
    assert_commands "git fetch origin", "git cherry-pick a319d88", "cherry-pick #{url}"
110 111 112
  end

  def test_cherry_pick_github_user_notation
113
    assert_commands "git fetch mislav", "git cherry-pick 368af20", "cherry-pick mislav@368af20"
114 115 116 117
  end

  def test_cherry_pick_github_user_repo_notation
    # not supported
118
    assert_forwarded "cherry-pick mislav/hubbub@a319d88"
119 120 121
  end

  def test_cherry_pick_github_notation_too_short
122
    assert_forwarded "cherry-pick mislav@a319"
123 124 125
  end

  def test_cherry_pick_github_notation_with_remote_add
126 127 128
    assert_commands "git remote add -f xoebus git://github.com/xoebus/hub.git",
                    "git cherry-pick a319d88",
                    "cherry-pick xoebus@a319d88"
129 130
  end

131 132 133 134 135 136 137 138
  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",
139
                      "am --signoff https://github.com/defunkt/hub/pull/55#comment_123 -p2"
140 141 142

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

146 147 148 149 150 151 152
  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

153 154 155 156 157 158 159 160 161 162
  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

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

173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
  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 已提交
208
  def test_init
M
Mislav Marohnić 已提交
209 210
    stub_no_remotes
    stub_no_git_repo
211
    assert_commands "git init", "git remote add origin git@github.com:tpw/hub.git", "init -g"
212 213
  end

214 215 216
  def test_init_enterprise
    stub_no_remotes
    stub_no_git_repo
217 218 219 220
    edit_hub_config do |data|
      data['git.my.org'] = [{'user'=>'myfiname'}]
    end

221 222 223 224 225
    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

226 227 228 229
  def test_push_untouched
    assert_forwarded "push"
  end

230
  def test_push_two
231 232
    assert_commands "git push origin cool-feature", "git push staging cool-feature",
                    "push origin,staging cool-feature"
233 234
  end

235 236 237 238 239 240
  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 已提交
241
  def test_push_more
242 243 244 245
    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 已提交
246
  end
C
Chris Wanstrath 已提交
247

248 249 250 251 252 253
  def test_push_multiple_refs
    assert_commands "git push origin master new-feature",
                    "git push staging master new-feature",
                    "push origin,staging master new-feature"
  end

254
  def test_pullrequest
M
Mislav Marohnić 已提交
255 256 257
    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"
258 259
  end

M
Mislav Marohnić 已提交
260 261
  def test_pullrequest_with_unpushed_commits
    stub_tracking('master', 'mislav', 'master')
262
    stub_command_output "rev-list --cherry-pick --right-only --no-merges mislav/master...", "+abcd1234\n+bcde2345"
263

M
Mislav Marohnić 已提交
264
    expected = "Aborted: 2 commits are not yet pushed to mislav/master\n" <<
265
      "(use `-f` to force submit a pull request anyway)\n"
266 267 268 269 270 271
    assert_output expected, "pull-request hereyougo"
  end

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

273 274 275
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/pulls").
      with(:body => { 'base' => "master", 'head' => "tpw:feature", 'title' => "hereyougo" }) { |req|
        req.headers['Content-Length'] == 63
276
      }.to_return(:body => mock_pullreq_response(1))
277 278

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

  def test_pullrequest_from_tracking_branch
    stub_branch('refs/heads/feature')
M
Mislav Marohnić 已提交
284
    stub_tracking('feature', 'mislav', 'yay-feature')
285

286 287
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/pulls").
      with(:body => {'base' => "master", 'head' => "mislav:yay-feature", 'title' => "hereyougo" }).
288 289 290
      to_return(:body => mock_pullreq_response(1))

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

294 295 296 297
  def test_pullrequest_from_branch_tracking_local
    stub_branch('refs/heads/feature')
    stub_tracking('feature', 'refs/heads/master')

298 299
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/pulls").
      with(:body => {'base' => "master", 'head' => "tpw:feature", 'title' => "hereyougo" }).
300 301 302 303 304 305
      to_return(:body => mock_pullreq_response(1))

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

306 307 308 309 310 311 312 313 314
  def test_pullrequest_invalid_remote
    stub_repo_url('gh:singingwolfboy/sekrit.git')
    stub_branch('refs/heads/feature')
    stub_tracking('feature', 'origin', 'feature')

    expected = "Aborted: the origin remote doesn't point to a GitHub repository.\n"
    assert_output expected, "pull-request hereyougo"
  end

315 316 317 318 319
  def test_pullrequest_enterprise_no_tracking
    stub_hub_host('git.my.org')
    stub_repo_url('git@git.my.org:defunkt/hub.git')
    stub_branch('refs/heads/feature')
    stub_tracking_nothing('feature')
320
    stub_command_output "rev-list --cherry-pick --right-only --no-merges origin/feature...", nil
321 322 323
    edit_hub_config do |data|
      data['git.my.org'] = [{'user'=>'myfiname', 'oauth_token' => 'FITOKEN'}]
    end
324

325
    stub_request(:post, "https://git.my.org/api/v3/repos/defunkt/hub/pulls").
326
      with(:body => {'base' => "master", 'head' => "myfiname:feature", 'title' => "hereyougo" }).
327
      to_return(:body => mock_pullreq_response(1, 'api/v3/defunkt/hub', 'git.my.org'))
328

329
    expected = "https://git.my.org/api/v3/defunkt/hub/pull/1\n"
330 331 332
    assert_output expected, "pull-request hereyougo -f"
  end

333
  def test_pullrequest_explicit_head
334 335
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/pulls").
      with(:body => {'base' => "master", 'head' => "tpw:yay-feature", 'title' => "hereyougo" }).
336 337 338
      to_return(:body => mock_pullreq_response(1))

    expected = "https://github.com/defunkt/hub/pull/1\n"
339
    assert_output expected, "pull-request hereyougo -h yay-feature -f"
340 341 342
  end

  def test_pullrequest_explicit_head_with_owner
343 344
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/pulls").
      with(:body => {'base' => "master", 'head' => "mojombo:feature", 'title' => "hereyougo" }).
345 346 347
      to_return(:body => mock_pullreq_response(1))

    expected = "https://github.com/defunkt/hub/pull/1\n"
348
    assert_output expected, "pull-request hereyougo -h mojombo:feature -f"
349 350 351
  end

  def test_pullrequest_explicit_base
352 353
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/pulls").
      with(:body => {'base' => "feature", 'head' => "defunkt:master", 'title' => "hereyougo" }).
354 355 356
      to_return(:body => mock_pullreq_response(1))

    expected = "https://github.com/defunkt/hub/pull/1\n"
357
    assert_output expected, "pull-request hereyougo -b feature -f"
358 359 360
  end

  def test_pullrequest_explicit_base_with_owner
361 362 363
    stub_request(:post, "https://api.github.com/repos/mojombo/hub/pulls").
      with(:body => {'base' => "feature", 'head' => "defunkt:master", 'title' => "hereyougo" }).
      to_return(:body => mock_pullreq_response(1, 'mojombo/hub'))
364

365
    expected = "https://github.com/mojombo/hub/pull/1\n"
366
    assert_output expected, "pull-request hereyougo -b mojombo:feature -f"
367 368
  end

369
  def test_pullrequest_explicit_base_with_repo
370 371 372
    stub_request(:post, "https://api.github.com/repos/mojombo/hubbub/pulls").
      with(:body => {'base' => "feature", 'head' => "defunkt:master", 'title' => "hereyougo" }).
      to_return(:body => mock_pullreq_response(1, 'mojombo/hubbub'))
373

374
    expected = "https://github.com/mojombo/hubbub/pull/1\n"
375
    assert_output expected, "pull-request hereyougo -b mojombo/hubbub:feature -f"
376 377 378
  end

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

383 384
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/pulls").
      with(:body => {'base' => "master", 'head' => "mislav:awesomefix", 'issue' => '92' }).
385 386 387
      to_return(:body => mock_pullreq_response(92))

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

391
  def test_pullrequest_existing_issue_url
M
Mislav Marohnić 已提交
392 393
    stub_branch('refs/heads/myfix')
    stub_tracking('myfix', 'mislav', 'awesomefix')
394
    stub_command_output "rev-list --cherry-pick --right-only --no-merges mislav/awesomefix...", nil
M
Mislav Marohnić 已提交
395

396 397
    stub_request(:post, "https://api.github.com/repos/mojombo/hub/pulls").
      with(:body => {'base' => "master", 'head' => "mislav:awesomefix", 'issue' => '92' }).
398 399 400
      to_return(:body => mock_pullreq_response(92, 'mojombo/hub'))

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

404
  def test_pullrequest_fails
405
    stub_request(:post, "https://api.github.com/repos/defunkt/hub/pulls").
406 407
      to_return(:status => [422, "Unprocessable Entity"],
                :headers => {"Content-type" => "application/json"},
408
                :body => %({"message":["oh no!\\nit failed."]}))
409 410 411 412 413 414

    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

415 416 417 418 419
  def test_checkout_no_changes
    assert_forwarded "checkout master"
  end

  def test_checkout_pullrequest
420
    stub_request(:get, "https://api.github.com/repos/defunkt/hub/pulls/73").
421 422 423
      to_return(:body => mock_pull_response('blueyed:feature'))

    assert_commands 'git remote add -f -t feature blueyed git://github.com/blueyed/hub.git',
M
Mislav Marohnić 已提交
424 425
      'git checkout -f --track -B blueyed-feature blueyed/feature -q',
      "checkout -f https://github.com/defunkt/hub/pull/73/files -q"
426 427
  end

428
  def test_checkout_private_pullrequest
429
    stub_request(:get, "https://api.github.com/repos/defunkt/hub/pulls/73").
430 431 432
      to_return(:body => mock_pull_response('blueyed:feature', :private))

    assert_commands 'git remote add -f -t feature blueyed git@github.com:blueyed/hub.git',
M
Mislav Marohnić 已提交
433
      'git checkout --track -B blueyed-feature blueyed/feature',
434 435 436
      "checkout https://github.com/defunkt/hub/pull/73/files"
  end

437
  def test_checkout_pullrequest_custom_branch
438
    stub_request(:get, "https://api.github.com/repos/defunkt/hub/pulls/73").
439 440 441
      to_return(:body => mock_pull_response('blueyed:feature'))

    assert_commands 'git remote add -f -t feature blueyed git://github.com/blueyed/hub.git',
M
Mislav Marohnić 已提交
442
      'git checkout --track -B review blueyed/feature',
443 444 445 446 447 448
      "checkout https://github.com/defunkt/hub/pull/73/files review"
  end

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

449
    stub_request(:get, "https://api.github.com/repos/defunkt/hub/pulls/73").
450 451 452 453
      to_return(:body => mock_pull_response('blueyed:feature'))

    assert_commands 'git remote set-branches --add blueyed feature',
      'git fetch blueyed +refs/heads/feature:refs/remotes/blueyed/feature',
M
Mislav Marohnić 已提交
454
      'git checkout --track -B blueyed-feature blueyed/feature',
455 456 457
      "checkout https://github.com/defunkt/hub/pull/73/files"
  end

C
Chris Wanstrath 已提交
458
  def test_version
459
    out = hub('--version')
460
    assert_includes "git version 1.7.0.4", out
C
Chris Wanstrath 已提交
461
    assert_includes "hub version #{Hub::Version}", out
C
Chris Wanstrath 已提交
462
  end
C
Chris Wanstrath 已提交
463

464 465 466 467 468 469 470
  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')
471
    assert_equal improved_help_text, out
472 473 474 475 476 477 478
  end

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

C
Chris Wanstrath 已提交
479
  def test_help
480
    assert_equal improved_help_text, hub("help")
C
Chris Wanstrath 已提交
481 482 483
  end

  def test_help_by_default
484
    assert_equal improved_help_text, hub("")
C
Chris Wanstrath 已提交
485
  end
C
Chris Wanstrath 已提交
486

S
Stephen Celis 已提交
487
  def test_help_with_pager
488
    assert_equal improved_help_text, hub("-p")
S
Stephen Celis 已提交
489 490
  end

C
Chris Wanstrath 已提交
491 492 493
  def test_help_hub
    help_manpage = hub("help hub")
    assert_includes "git + hub = github", help_manpage
M
Mislav Marohnić 已提交
494
    assert_includes "Hub will prompt for GitHub username & password", help_manpage.gsub(/ {2,}/, ' ')
C
Chris Wanstrath 已提交
495 496
  end

497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512
  def test_help_flag_on_command
    help_manpage = hub("browse --help")
    assert_includes "git + hub = github", help_manpage
    assert_includes "git browse", help_manpage
  end

  def test_help_short_flag_on_command
    usage_help = hub("create -h")
    expected = "Usage: git create [NAME] [-p] [-d DESCRIPTION] [-h HOMEPAGE]\n"
    assert_equal expected, usage_help

    usage_help = hub("pull-request -h")
    expected = "Usage: git pull-request [-f] [TITLE|-i ISSUE] [-b BASE] [-h HEAD]\n"
    assert_equal expected, usage_help
  end

C
Chris Wanstrath 已提交
513
  def test_help_hub_no_groff
514 515
    stub_available_commands()
    assert_equal "** Can't find groff(1)\n", hub("help hub")
C
Chris Wanstrath 已提交
516
  end
517

518
  def test_hub_standalone
519
    assert_includes 'This file is generated code', hub("hub standalone")
520 521
  end

C
Chris Wanstrath 已提交
522 523
  def test_hub_compare
    assert_command "compare refactor",
524
      "open https://github.com/defunkt/hub/compare/refactor"
525
  end
C
Chris Wanstrath 已提交
526

527 528 529 530
  def test_hub_compare_nothing
    expected = "Usage: hub compare [USER] [<START>...]<END>\n"
    assert_equal expected, hub("compare")
  end
C
Chris Wanstrath 已提交
531

532 533 534 535 536 537 538 539
  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')
540
    stub_tracking('feature', 'mislav', 'experimental')
541 542

    assert_command "compare",
543
      "open https://github.com/mislav/hub/compare/experimental"
544 545
  end

546
  def test_hub_compare_range
C
Chris Wanstrath 已提交
547
    assert_command "compare 1.0...fix",
548
      "open https://github.com/defunkt/hub/compare/1.0...fix"
549
  end
C
Chris Wanstrath 已提交
550

551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
  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

566 567 568 569 570 571
  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

572
  def test_hub_compare_fork
C
Chris Wanstrath 已提交
573
    assert_command "compare myfork feature",
574
      "open https://github.com/myfork/hub/compare/feature"
575 576 577 578
  end

  def test_hub_compare_url
    assert_command "compare -u 1.0...1.1",
579
      "echo https://github.com/defunkt/hub/compare/1.0...1.1"
580 581 582 583 584
  end

  def test_hub_browse_no_repo
    stub_repo_url(nil)
    assert_equal "Usage: hub browse [<USER>/]<REPOSITORY>\n", hub("browse")
585
  end
586

587
  def test_hub_browse_ssh_alias
M
Mislav Marohnić 已提交
588
    with_ssh_config "Host gh\n User git\n HostName github.com" do
589 590 591 592 593
      stub_repo_url "gh:singingwolfboy/sekrit.git"
      assert_command "browse", "open https://github.com/singingwolfboy/sekrit"
    end
  end

M
Mislav Marohnić 已提交
594 595 596 597 598 599 600
  def test_hub_browse_ssh_github_alias
    with_ssh_config "Host github.com\n HostName ssh.github.com" do
      stub_repo_url "git@github.com:suan/git-sanity.git"
      assert_command "browse", "open https://github.com/suan/git-sanity"
    end
  end

601 602 603 604 605 606 607 608 609
  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
610
      with_host_os("i686-linux") do
611 612 613 614 615 616 617 618
        assert_browser("xdg-open")
      end
    end
  end

  def test_cygwin_browser
    stub_available_commands "open", "cygstart"
    with_browser_env(nil) do
619
      with_host_os("i686-linux") do
620 621 622 623 624 625 626 627 628
        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
629
      with_host_os("i686-linux") do
630 631 632 633 634
        assert_equal expected, hub("browse")
      end
    end
  end

635
  def test_context_method_doesnt_hijack_git_command
636
    assert_forwarded 'remotes'
637 638
  end

639 640 641 642 643
  def test_not_choking_on_ruby_methods
    assert_forwarded 'id'
    assert_forwarded 'name'
  end

644 645
  def test_multiple_remote_urls
    stub_repo_url("git://example.com/other.git\ngit://github.com/my/repo.git")
646
    assert_command "browse", "open https://github.com/my/repo"
647 648
  end

649 650 651
  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'
652
    assert_equal %w[git --bare -c core.awesome=true -c name=value --git-dir=/srv/www], git_reader.executable
653 654
  end

655
  private
656

M
Mislav Marohnić 已提交
657 658
    def stub_repo_url(value, remote_name = 'origin')
      stub_config_value "remote.#{remote_name}.url", value, '--get-all'
659 660 661
    end

    def stub_branch(value)
662
      stub_command_output 'symbolic-ref -q HEAD', value
663 664
    end

665
    def stub_tracking(from, upstream, remote_branch = nil)
666
      stub_command_output "rev-parse --symbolic-full-name #{from}@{upstream}",
667
        remote_branch ? "refs/remotes/#{upstream}/#{remote_branch}" : upstream
668 669
    end

670
    def stub_tracking_nothing(from = 'master')
671
      stub_tracking(from, nil)
672 673
    end

674
    def stub_remotes_group(name, value)
675
      stub_config_value "remotes.#{name}", value
676 677
    end

678
    def stub_no_remotes
679
      stub_command_output 'remote', nil
680 681 682
    end

    def stub_no_git_repo
683
      stub_command_output 'rev-parse -q --git-dir', nil
684 685
    end

M
Mislav Marohnić 已提交
686
    def stub_alias(name, value)
687
      stub_config_value "alias.#{name}", value
M
Mislav Marohnić 已提交
688 689
    end

690 691
    def stub_existing_fork(user, repo = 'hub')
      stub_fork(user, repo, 200)
692 693
    end

694 695
    def stub_nonexisting_fork(user, repo = 'hub')
      stub_fork(user, repo, 404)
696 697
    end

698
    def stub_fork(user, repo, status)
699
      stub_request(:get, "https://api.github.com/repos/#{user}/#{repo}").
700 701 702
        to_return(:status => status)
    end

703 704 705 706
    def stub_available_commands(*names)
      COMMANDS.replace names
    end

707
    def stub_https_is_preferred
708
      stub_config_value 'hub.protocol', 'https'
709 710
    end

711 712 713 714
    def stub_hub_host(names)
      stub_config_value "hub.host", Array(names).join("\n"), '--get-all'
    end

715 716 717 718 719 720 721
    def with_browser_env(value)
      browser, ENV['BROWSER'] = ENV['BROWSER'], value
      yield
    ensure
      ENV['BROWSER'] = browser
    end

722 723 724 725 726 727 728
    def with_tmpdir(value)
      dir, ENV['TMPDIR'] = ENV['TMPDIR'], value
      yield
    ensure
      ENV['TMPDIR'] = dir
    end

729 730 731 732 733 734 735
    def with_host_env(value)
      host, ENV['GITHUB_HOST'] = ENV['GITHUB_HOST'], value
      yield
    ensure
      ENV['GITHUB_HOST'] = host
    end

736
    def assert_browser(browser)
737
      assert_command "browse", "#{browser} https://github.com/defunkt/hub"
738 739
    end

740 741 742 743 744 745 746 747
    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
748 749
    end

750
    def mock_pullreq_response(id, name_with_owner = 'defunkt/hub', host = 'github.com')
751
      Hub::JSON.generate :html_url => "https://#{host}/#{name_with_owner}/pull/#{id}"
752 753
    end

754
    def mock_pull_response(label, priv = false)
755 756 757
      Hub::JSON.generate :head => {
        :label => label,
        :repo => {:private => !!priv}
M
Mislav Marohnić 已提交
758
      }
759 760
    end

761 762 763 764
    def improved_help_text
      Hub::Commands.send :improved_help_text
    end

M
Mislav Marohnić 已提交
765 766 767 768 769 770 771 772 773 774 775
    def with_ssh_config content
      config_file = Tempfile.open 'ssh_config'
      config_file << content
      config_file.close

      begin
        Hub::SshConfig::CONFIG_FILES.replace [config_file.path]
        yield
      ensure
        config_file.unlink
      end
776 777
    end

C
Chris Wanstrath 已提交
778
end