hub_test.rb 24.6 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
      'remote -v' => "origin\tgit://github.com/defunkt/hub.git (fetch)\nmislav\tgit://github.com/mislav/hub.git (fetch)",
78
      'rev-parse --symbolic-full-name master@{upstream}' => 'refs/remotes/origin/master',
79 80
      'config --get --bool hub.http-clone' => 'false',
      'config --get hub.protocol' => nil,
81
      'config --get-all hub.host' => nil,
82
      'rev-parse -q --git-dir' => '.git'
83 84
  end

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

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

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

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

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

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

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

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

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

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

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

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

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

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

172 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
  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 已提交
207
  def test_init
M
Mislav Marohnić 已提交
208 209
    stub_no_remotes
    stub_no_git_repo
210
    assert_commands "git init", "git remote add origin git@github.com:tpw/hub.git", "init -g"
211 212
  end

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

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

225 226 227 228
  def test_push_untouched
    assert_forwarded "push"
  end

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

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

247 248 249 250 251 252
  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

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

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

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

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

272 273 274
    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
275
      }.to_return(:body => mock_pullreq_response(1))
276 277

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

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

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

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

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

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

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

305 306 307 308 309 310 311 312 313
  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

314 315 316 317 318
  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')
319
    stub_command_output "rev-list --cherry-pick --right-only --no-merges origin/feature...", nil
320 321 322
    edit_hub_config do |data|
      data['git.my.org'] = [{'user'=>'myfiname', 'oauth_token' => 'FITOKEN'}]
    end
323

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

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

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

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

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

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

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

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

  def test_pullrequest_explicit_base_with_owner
360 361 362
    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'))
363

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

368
  def test_pullrequest_explicit_base_with_repo
369 370 371
    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'))
372

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

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

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

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

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

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

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

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

    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

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

  def test_checkout_pullrequest
419
    stub_request(:get, "https://api.github.com/repos/defunkt/hub/pulls/73").
420 421 422
      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ć 已提交
423 424
      'git checkout -f --track -B blueyed-feature blueyed/feature -q',
      "checkout -f https://github.com/defunkt/hub/pull/73/files -q"
425 426
  end

427
  def test_checkout_private_pullrequest
428
    stub_request(:get, "https://api.github.com/repos/defunkt/hub/pulls/73").
429 430 431
      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ć 已提交
432
      'git checkout --track -B blueyed-feature blueyed/feature',
433 434 435
      "checkout https://github.com/defunkt/hub/pull/73/files"
  end

436
  def test_checkout_pullrequest_custom_branch
437
    stub_request(:get, "https://api.github.com/repos/defunkt/hub/pulls/73").
438 439 440
      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ć 已提交
441
      'git checkout --track -B review blueyed/feature',
442 443 444 445 446 447
      "checkout https://github.com/defunkt/hub/pull/73/files review"
  end

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

448
    stub_request(:get, "https://api.github.com/repos/defunkt/hub/pulls/73").
449 450 451 452
      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ć 已提交
453
      'git checkout --track -B blueyed-feature blueyed/feature',
454 455 456
      "checkout https://github.com/defunkt/hub/pull/73/files"
  end

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

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

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

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

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

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

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

496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
  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 已提交
512
  def test_help_hub_no_groff
513 514
    stub_available_commands()
    assert_equal "** Can't find groff(1)\n", hub("help hub")
C
Chris Wanstrath 已提交
515
  end
516

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

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

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

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

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

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

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

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

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

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

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

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

M
Mislav Marohnić 已提交
593 594 595 596 597 598 599
  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

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

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

634
  def test_context_method_doesnt_hijack_git_command
635
    assert_forwarded 'remotes'
636 637
  end

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

643 644 645
  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'
646
    assert_equal %w[git --bare -c core.awesome=true -c name=value --git-dir=/srv/www], git_reader.executable
647 648
  end

649
  private
650

M
Mislav Marohnić 已提交
651
    def stub_repo_url(value, remote_name = 'origin')
652
      stub_command_output 'remote -v', "#{remote_name}\t#{value} (fetch)"
653 654 655
    end

    def stub_branch(value)
656
      stub_command_output 'symbolic-ref -q HEAD', value
657 658
    end

659
    def stub_tracking(from, upstream, remote_branch = nil)
660
      stub_command_output "rev-parse --symbolic-full-name #{from}@{upstream}",
661
        remote_branch ? "refs/remotes/#{upstream}/#{remote_branch}" : upstream
662 663
    end

664
    def stub_tracking_nothing(from = 'master')
665
      stub_tracking(from, nil)
666 667
    end

668
    def stub_remotes_group(name, value)
669
      stub_config_value "remotes.#{name}", value
670 671
    end

672
    def stub_no_remotes
673
      stub_command_output 'remote', nil
674 675 676
    end

    def stub_no_git_repo
677
      stub_command_output 'rev-parse -q --git-dir', nil
678 679
    end

M
Mislav Marohnić 已提交
680
    def stub_alias(name, value)
681
      stub_config_value "alias.#{name}", value
M
Mislav Marohnić 已提交
682 683
    end

684 685
    def stub_existing_fork(user, repo = 'hub')
      stub_fork(user, repo, 200)
686 687
    end

688 689
    def stub_nonexisting_fork(user, repo = 'hub')
      stub_fork(user, repo, 404)
690 691
    end

692
    def stub_fork(user, repo, status)
693
      stub_request(:get, "https://api.github.com/repos/#{user}/#{repo}").
694 695 696
        to_return(:status => status)
    end

697 698 699 700
    def stub_available_commands(*names)
      COMMANDS.replace names
    end

701
    def stub_https_is_preferred
702
      stub_config_value 'hub.protocol', 'https'
703 704
    end

705 706 707 708
    def stub_hub_host(names)
      stub_config_value "hub.host", Array(names).join("\n"), '--get-all'
    end

709 710 711 712 713 714 715
    def with_browser_env(value)
      browser, ENV['BROWSER'] = ENV['BROWSER'], value
      yield
    ensure
      ENV['BROWSER'] = browser
    end

716 717 718 719 720 721 722
    def with_tmpdir(value)
      dir, ENV['TMPDIR'] = ENV['TMPDIR'], value
      yield
    ensure
      ENV['TMPDIR'] = dir
    end

723 724 725 726 727 728 729
    def with_host_env(value)
      host, ENV['GITHUB_HOST'] = ENV['GITHUB_HOST'], value
      yield
    ensure
      ENV['GITHUB_HOST'] = host
    end

730
    def assert_browser(browser)
731
      assert_command "browse", "#{browser} https://github.com/defunkt/hub"
732 733
    end

734 735 736 737 738 739 740 741
    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
742 743
    end

744
    def mock_pullreq_response(id, name_with_owner = 'defunkt/hub', host = 'github.com')
745
      Hub::JSON.generate :html_url => "https://#{host}/#{name_with_owner}/pull/#{id}"
746 747
    end

748
    def mock_pull_response(label, priv = false)
749 750 751
      Hub::JSON.generate :head => {
        :label => label,
        :repo => {:private => !!priv}
M
Mislav Marohnić 已提交
752
      }
753 754
    end

755 756 757 758
    def improved_help_text
      Hub::Commands.send :improved_help_text
    end

M
Mislav Marohnić 已提交
759 760 761 762 763 764 765 766 767 768 769
    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
770 771
    end

C
Chris Wanstrath 已提交
772
end