topfunky-github 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,28 @@
1
+ # define #try
2
+ class Object
3
+ def try
4
+ self
5
+ end
6
+ end
7
+
8
+ class NilClass
9
+ klass = Class.new
10
+ klass.class_eval do
11
+ instance_methods.each { |meth| undef_method meth.to_sym unless meth =~ /^__(id|send)__$/ }
12
+ def method_missing(*args)
13
+ self
14
+ end
15
+ end
16
+ NilProxy = klass.new
17
+ def try
18
+ NilProxy
19
+ end
20
+ end
21
+
22
+ # define #tap
23
+ class Object
24
+ def tap(&block)
25
+ block.call(self)
26
+ self
27
+ end
28
+ end
@@ -0,0 +1,4 @@
1
+ module GitHub
2
+ class Helper
3
+ end
4
+ end
@@ -0,0 +1,66 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe GitHub::Command do
4
+ before(:each) do
5
+ @command = GitHub::Command.new(proc { |x| puts x })
6
+ end
7
+
8
+ it "should return a GitHub::Helper" do
9
+ @command.helper.should be_instance_of(GitHub::Helper)
10
+ end
11
+
12
+ it "should call successfully" do
13
+ @command.should_receive(:puts).with("test").once
14
+ @command.call("test")
15
+ end
16
+
17
+ it "should return options" do
18
+ GitHub.should_receive(:options).with().once.and_return({:ssh => true})
19
+ @command.options.should == {:ssh => true}
20
+ end
21
+
22
+ it "should successfully call out to the shell" do
23
+ unguard(Kernel, :fork)
24
+ unguard(Kernel, :exec)
25
+ hi = @command.sh("echo hi")
26
+ hi.should == "hi"
27
+ hi.out?.should be(true)
28
+ hi.error?.should be(false)
29
+ hi.command.should == "echo hi"
30
+ bye = @command.sh("echo bye >&2")
31
+ bye.should == "bye"
32
+ bye.out?.should be(false)
33
+ bye.error?.should be(true)
34
+ bye.command.should == "echo bye >&2"
35
+ end
36
+
37
+ it "should return the results of a git operation" do
38
+ GitHub::Command::Shell.should_receive(:new).with("git rev-parse master").once.and_return do |*cmds|
39
+ s = mock("GitHub::Commands::Shell")
40
+ s.should_receive(:run).once.and_return("sha1")
41
+ s
42
+ end
43
+ @command.git("rev-parse master").should == "sha1"
44
+ end
45
+
46
+ it "should print the results of a git operation" do
47
+ @command.should_receive(:puts).with("sha1").once
48
+ GitHub::Command::Shell.should_receive(:new).with("git rev-parse master").once.and_return do |*cmds|
49
+ s = mock("GitHub::Commands::Shell")
50
+ s.should_receive(:run).once.and_return("sha1")
51
+ s
52
+ end
53
+ @command.pgit("rev-parse master")
54
+ end
55
+
56
+ it "should exec a git command" do
57
+ @command.should_receive(:exec).with("git rev-parse master").once
58
+ @command.git_exec "rev-parse master"
59
+ end
60
+
61
+ it "should die" do
62
+ @command.should_receive(:puts).once.with("=> message")
63
+ @command.should_receive(:exit!).once
64
+ @command.die "message"
65
+ end
66
+ end
@@ -0,0 +1,36 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
3
+ describe "When calling #try" do
4
+ specify "objects should return themselves" do
5
+ obj = 1; obj.try.should equal(obj)
6
+ obj = "foo"; obj.try.should equal(obj)
7
+ obj = { :foo => "bar" }; obj.try.should equal(obj)
8
+ end
9
+
10
+ specify "objects should behave as if #try wasn't called" do
11
+ "foo".try.size.should == 3
12
+ { :foo => :bar }.try.fetch(:foo).should == :bar
13
+ [1, 2, 3].try.map { |x| x + 1 }.should == [2, 3, 4]
14
+ end
15
+
16
+ specify "nil should return the singleton NilClass::NilProxy" do
17
+ nil.try.should equal(NilClass::NilProxy)
18
+ end
19
+
20
+ specify "nil should ignore any calls made past #try" do
21
+ nil.try.size.should equal(NilClass::NilProxy)
22
+ nil.try.sdlfj.should equal(NilClass::NilProxy)
23
+ nil.try.one.two.three.should equal(NilClass::NilProxy)
24
+ end
25
+
26
+ specify "classes should respond just like objects" do
27
+ String.try.should equal(String)
28
+ end
29
+ end
30
+
31
+ describe "When calling #tap" do
32
+ specify "objects should behave like Ruby 1.9's #tap" do
33
+ obj = "foo"
34
+ obj.tap { |obj| obj.size.should == 3 }.should equal(obj)
35
+ end
36
+ end
@@ -0,0 +1,65 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "GitHub.parse_options" do
4
+ it "should parse --bare options" do
5
+ args = ["--bare", "--test"]
6
+ GitHub.parse_options(args).should == {:bare => true, :test => true}
7
+ args.should == []
8
+ end
9
+
10
+ it "should parse options intermixed with non-options" do
11
+ args = ["text", "--bare", "more text", "--option", "--foo"]
12
+ GitHub.parse_options(args).should == {:bare => true, :option => true, :foo => true}
13
+ args.should == ["text", "more text"]
14
+ end
15
+
16
+ it "should parse --foo=bar style options" do
17
+ args = ["--foo=bar", "--bare"]
18
+ GitHub.parse_options(args).should == {:bare => true, :foo => "bar"}
19
+ args.should == []
20
+ end
21
+
22
+ it "should stop parsing options at --" do
23
+ args = ["text", "--bare", "--", "--foo"]
24
+ GitHub.parse_options(args).should == {:bare => true}
25
+ args.should == ["text", "--foo"]
26
+ end
27
+
28
+ it "should handle duplicate options" do
29
+ args = ["text", "--foo=bar", "--bare", "--foo=baz"]
30
+ GitHub.parse_options(args).should == {:foo => "baz", :bare => true}
31
+ args.should == ["text"]
32
+ end
33
+
34
+ it "should handle duplicate --bare options surrounding --" do
35
+ args = ["text", "--bare", "--", "--bare"]
36
+ GitHub.parse_options(args).should == {:bare => true}
37
+ args.should == ["text", "--bare"]
38
+ end
39
+
40
+ it "should handle no options" do
41
+ args = ["text", "more text"]
42
+ GitHub.parse_options(args).should == {}
43
+ args.should == ["text", "more text"]
44
+ end
45
+
46
+ it "should handle no args" do
47
+ args = []
48
+ GitHub.parse_options(args).should == {}
49
+ args.should == []
50
+ end
51
+
52
+ it "should not set up debugging when --debug not passed" do
53
+ GitHub.stub!(:load)
54
+ GitHub.stub!(:invoke)
55
+ GitHub.activate(['default'])
56
+ GitHub.should_not be_debug
57
+ end
58
+
59
+ it "should set up debugging when passed --debug" do
60
+ GitHub.stub!(:load)
61
+ GitHub.stub!(:invoke)
62
+ GitHub.activate(['default', '--debug'])
63
+ GitHub.should be_debug
64
+ end
65
+ end
@@ -0,0 +1,212 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ class HelperRunner
4
+ def initialize(parent, name)
5
+ @parent = parent
6
+ @name = name
7
+ end
8
+
9
+ def run(&block)
10
+ self.instance_eval(&block)
11
+ end
12
+
13
+ def it(str, &block)
14
+ @parent.send :it, "#{@name} #{str}", &block
15
+ end
16
+ alias specify it
17
+ end
18
+
19
+ describe GitHub::Helper do
20
+ include SetupMethods
21
+
22
+ def self.helper(name, &block)
23
+ HelperRunner.new(self, name).run(&block)
24
+ end
25
+
26
+ before(:each) do
27
+ @helper = GitHub::Helper.new
28
+ end
29
+
30
+ helper :owner do
31
+ it "should return repo owner" do
32
+ setup_url_for :origin, "hacker"
33
+ @helper.owner.should == "hacker"
34
+ end
35
+ end
36
+
37
+ helper :private_url_for do
38
+ it "should return an ssh-style url" do
39
+ setup_url_for :origin, "user", "merb-core"
40
+ @helper.private_url_for("wycats").should == "git@github.com:wycats/merb-core.git"
41
+ end
42
+ end
43
+
44
+ helper :private_url_for_user_and_repo do
45
+ it "should return an ssh-style url" do
46
+ @helper.should_not_receive(:project)
47
+ @helper.private_url_for_user_and_repo("defunkt", "github-gem").should == "git@github.com:defunkt/github-gem.git"
48
+ end
49
+ end
50
+
51
+ helper :public_url_for do
52
+ it "should return a git:// URL" do
53
+ setup_url_for :origin, "user", "merb-core"
54
+ @helper.public_url_for("wycats").should == "git://github.com/wycats/merb-core.git"
55
+ end
56
+ end
57
+
58
+ helper :public_url_for_user_and_repo do
59
+ it "should return a git:// URL" do
60
+ @helper.should_not_receive(:project)
61
+ @helper.public_url_for_user_and_repo("defunkt", "github-gem").should == "git://github.com/defunkt/github-gem.git"
62
+ end
63
+ end
64
+
65
+ helper :project do
66
+ it "should return project-awesome" do
67
+ setup_url_for :origin, "user", "project-awesome"
68
+ @helper.project.should == "project-awesome"
69
+ end
70
+
71
+ it "should exit due to missing origin" do
72
+ @helper.should_receive(:url_for).twice.with(:origin).and_return("")
73
+ STDERR.should_receive(:puts).with("Error: missing remote 'origin'")
74
+ lambda { @helper.project }.should raise_error(SystemExit)
75
+ end
76
+
77
+ it "should exit due to non-github origin" do
78
+ @helper.should_receive(:url_for).twice.with(:origin).and_return("home:path/to/repo.git")
79
+ STDERR.should_receive(:puts).with("Error: remote 'origin' is not a github URL")
80
+ lambda { @helper.project }.should raise_error(SystemExit)
81
+ end
82
+ end
83
+
84
+ helper :repo_for do
85
+ it "should return mephisto.git" do
86
+ setup_url_for :mojombo, "mojombo", "mephisto"
87
+ @helper.repo_for(:mojombo).should == "mephisto.git"
88
+ end
89
+ end
90
+
91
+ helper :user_and_repo_from do
92
+ it "should parse a git:// url" do
93
+ @helper.user_and_repo_from("git://github.com/defunkt/github.git").should == ["defunkt", "github.git"]
94
+ end
95
+
96
+ it "should parse a ssh-based url" do
97
+ @helper.user_and_repo_from("git@github.com:mojombo/god.git").should == ["mojombo", "god.git"]
98
+ end
99
+
100
+ it "should parse a non-standard ssh-based url" do
101
+ @helper.user_and_repo_from("ssh://git@github.com:mojombo/god.git").should == ["mojombo", "god.git"]
102
+ @helper.user_and_repo_from("github.com:mojombo/god.git").should == ["mojombo", "god.git"]
103
+ @helper.user_and_repo_from("ssh://github.com:mojombo/god.git").should == ["mojombo", "god.git"]
104
+ end
105
+
106
+ it "should return nothing for other urls" do
107
+ @helper.user_and_repo_from("home:path/to/repo.git").should == nil
108
+ end
109
+
110
+ it "should return nothing for invalid git:// urls" do
111
+ @helper.user_and_repo_from("git://github.com/foo").should == nil
112
+ end
113
+
114
+ it "should return nothing for invalid ssh-based urls" do
115
+ @helper.user_and_repo_from("git@github.com:kballard").should == nil
116
+ @helper.user_and_repo_from("git@github.com:kballard/test/repo.git").should == nil
117
+ @helper.user_and_repo_from("ssh://git@github.com:kballard").should == nil
118
+ @helper.user_and_repo_from("github.com:kballard").should == nil
119
+ @helper.user_and_repo_from("ssh://github.com:kballard").should == nil
120
+ end
121
+ end
122
+
123
+ helper :user_for do
124
+ it "should return defunkt" do
125
+ setup_url_for :origin, "defunkt"
126
+ @helper.user_for(:origin).should == "defunkt"
127
+ end
128
+ end
129
+
130
+ helper :url_for do
131
+ it "should call out to the shell" do
132
+ @helper.should_receive(:`).with("git config --get remote.origin.url").and_return "git://github.com/user/project.git\n"
133
+ @helper.url_for(:origin).should == "git://github.com/user/project.git"
134
+ end
135
+ end
136
+
137
+ helper :remotes do
138
+ it "should return a list of remotes" do
139
+ @helper.should_receive(:`).with('git config --get-regexp \'^remote\.(.+)\.url$\'').and_return <<-EOF
140
+ remote.origin.url git@github.com:kballard/github-gem.git
141
+ remote.defunkt.url git://github.com/defunkt/github-gem.git
142
+ remote.nex3.url git://github.com/nex3/github-gem.git
143
+ EOF
144
+ @helper.remotes.should == {
145
+ :origin => "git@github.com:kballard/github-gem.git",
146
+ :defunkt => "git://github.com/defunkt/github-gem.git",
147
+ :nex3 => "git://github.com/nex3/github-gem.git"
148
+ }
149
+ end
150
+ end
151
+
152
+ helper :tracking do
153
+ it "should return a list of remote/user_or_url pairs" do
154
+ @helper.should_receive(:remotes).and_return({
155
+ :origin => "git@github.com:kballard/github-gem.git",
156
+ :defunkt => "git://github.com/defunkt/github-gem.git",
157
+ :external => "server:path/to/github-gem.git"
158
+ })
159
+ @helper.tracking.should == {
160
+ :origin => "kballard",
161
+ :defunkt => "defunkt",
162
+ :external => "server:path/to/github-gem.git"
163
+ }
164
+ end
165
+ end
166
+
167
+ helper :tracking? do
168
+ it "should return whether the user is tracked" do
169
+ @helper.should_receive(:tracking).any_number_of_times.and_return({
170
+ :origin => "kballard",
171
+ :defunkt => "defunkt",
172
+ :external => "server:path/to/github-gem.git"
173
+ })
174
+ @helper.tracking?("kballard").should == true
175
+ @helper.tracking?("defunkt").should == true
176
+ @helper.tracking?("nex3").should == false
177
+ end
178
+ end
179
+
180
+ helper :user_and_branch do
181
+ it "should return owner and branch for unqualified branches" do
182
+ setup_url_for
183
+ @helper.should_receive(:`).with("git rev-parse --symbolic-full-name HEAD").and_return "refs/heads/master"
184
+ @helper.user_and_branch.should == ["user", "master"]
185
+ end
186
+
187
+ it "should return user and branch for user/branch-style branches" do
188
+ @helper.should_receive(:`).with("git rev-parse --symbolic-full-name HEAD").and_return "refs/heads/defunkt/wip"
189
+ @helper.user_and_branch.should == ["defunkt", "wip"]
190
+ end
191
+ end
192
+
193
+ helper :open do
194
+ it "should launch the URL when Launchy is installed" do
195
+ begin
196
+ require 'launchy'
197
+ @helper.should_receive(:gem).with('launchy')
198
+ # @helper.should_receive(:has_launchy?).and_return { |blk| blk.call }
199
+ Launchy::Browser.next_instance.should_receive(:visit).with("http://www.google.com")
200
+ @helper.open "http://www.google.com"
201
+ rescue LoadError
202
+ fail "Launchy is required for this spec"
203
+ end
204
+ end
205
+
206
+ it "should fail when Launchy is not installed" do
207
+ @helper.should_receive(:gem).with('launchy').and_raise(Gem::LoadError)
208
+ STDERR.should_receive(:puts).with("Sorry, you need to install launchy: `gem install launchy`")
209
+ @helper.open "http://www.google.com"
210
+ end
211
+ end
212
+ end
@@ -0,0 +1,138 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ require File.dirname(__FILE__) + '/../lib/github'
5
+
6
+ class Module
7
+ def metaclass
8
+ class << self;self;end
9
+ end
10
+ end
11
+
12
+ class Spec::NextInstanceProxy
13
+ def initialize
14
+ @deferred = []
15
+ end
16
+
17
+ def method_missing(sym, *args)
18
+ proxy = Spec::NextInstanceProxy.new
19
+ @deferred << [sym, args, proxy]
20
+ proxy
21
+ end
22
+
23
+ def should_receive(*args)
24
+ method_missing(:should_receive, *args)
25
+ end
26
+ alias stub! should_receive
27
+
28
+ def invoke(obj)
29
+ @deferred.each do |(sym, args, proxy)|
30
+ result = obj.send(sym, *args)
31
+ proxy.invoke(result)
32
+ end
33
+ end
34
+ end
35
+
36
+ class Class
37
+ def next_instance
38
+ meth = metaclass.instance_method(:new)
39
+ proxy = Spec::NextInstanceProxy.new
40
+ metaclass.send :define_method, :new do |*args|
41
+ instance = meth.bind(self).call(*args)
42
+ proxy.invoke(instance)
43
+ metaclass.send :define_method, :new, meth
44
+ instance
45
+ end
46
+ proxy
47
+ end
48
+ end
49
+
50
+ module Spec::Example::ExampleGroupSubclassMethods
51
+ def add_guard(klass, name, is_class = false)
52
+ guarded = nil # define variable now for scoping
53
+ target = (is_class ? klass.metaclass : klass)
54
+ sep = (is_class ? "." : "#")
55
+ target.class_eval do
56
+ guarded = instance_method(name)
57
+ define_method name do |*args|
58
+ raise "Testing guards violated: Cannot call #{klass}#{sep}#{name}"
59
+ end
60
+ end
61
+ @guards ||= []
62
+ @guards << [klass, name, is_class, guarded]
63
+ end
64
+
65
+ def add_class_guard(klass, name)
66
+ add_guard(klass, name, true)
67
+ end
68
+
69
+ def unguard(klass, name, is_class = false)
70
+ row = @guards.find { |(k,n,i)| k == klass and n == name and i == is_class }
71
+ raise "#{klass}#{is_class ? "." : "#"}#{name} is not guarded" if row.nil?
72
+ (is_class ? klass.metaclass : klass).class_eval do
73
+ define_method name, row.last
74
+ end
75
+ @guards.delete row
76
+ end
77
+
78
+ def class_unguard(klass, name)
79
+ unguard(klass, name, true)
80
+ end
81
+
82
+ def unguard_all
83
+ @guards ||= []
84
+ @guards.each do |klass, name, is_class, guarded|
85
+ (is_class ? klass.metaclass : klass).class_eval do
86
+ define_method name, guarded
87
+ end
88
+ end
89
+ @guards.clear
90
+ end
91
+ end
92
+
93
+ # prevent the use of `` in tests
94
+ Spec::Runner.configure do |configuration|
95
+ # load this here so it's covered by the `` guard
96
+ configuration.prepend_before(:all) do
97
+ module GitHub
98
+ load 'helpers.rb'
99
+ load 'commands.rb'
100
+ end
101
+ end
102
+
103
+ configuration.prepend_after(:each) do
104
+ GitHub.instance_variable_set :'@options', nil
105
+ GitHub.instance_variable_set :'@debug', nil
106
+ end
107
+
108
+ configuration.prepend_before(:all) do
109
+ self.class.send :include, Spec::Example::ExampleGroupSubclassMethods
110
+ end
111
+
112
+ configuration.prepend_before(:each) do
113
+ add_guard Kernel, :`
114
+ add_guard Kernel, :system
115
+ add_guard Kernel, :fork
116
+ add_guard Kernel, :exec
117
+ add_class_guard Process, :fork
118
+ end
119
+
120
+ configuration.append_after(:each) do
121
+ unguard_all
122
+ end
123
+ end
124
+
125
+ # include this in any example group that defines @helper
126
+ module SetupMethods
127
+ def setup_user_and_branch(user = :user, branch = :master)
128
+ @helper.should_receive(:user_and_branch).any_number_of_times.and_return([user, branch])
129
+ end
130
+
131
+ def setup_url_for(remote = :origin, user = nil, project = :project)
132
+ if user.nil?
133
+ user = remote
134
+ user = "user" if remote == :origin
135
+ end
136
+ @helper.should_receive(:url_for).any_number_of_times.with(remote).and_return("git://github.com/#{user}/#{project}.git")
137
+ end
138
+ end