ghi 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,29 @@
1
+ class GHI::Issue
2
+ attr_reader :number, :title, :body, :votes, :state, :user, :created_at,
3
+ :updated_at
4
+
5
+ def initialize(options = {})
6
+ @number = options["number"]
7
+ @title = options["title"]
8
+ @body = options["body"]
9
+ @votes = options["votes"]
10
+ @state = options["state"]
11
+ @user = options["user"]
12
+ @created_at = options["created_at"]
13
+ @updated_at = options["updated_at"]
14
+ end
15
+
16
+ #-
17
+ # REFACTOR: This code is duplicated from cli.rb:gets_from_editor.
18
+ #+
19
+ def ==(other_issue)
20
+ case other_issue
21
+ when Array
22
+ other_title = other_issue.first.strip
23
+ other_body = other_issue[1..-1].join.sub(/\b\n\b/, " ").strip
24
+ title == other_title && body == other_body
25
+ else
26
+ super other_issue
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,194 @@
1
+ require "ghi"
2
+ require "ghi/api"
3
+ require "ghi/issue"
4
+
5
+ ISSUES_YAML = <<-YAML
6
+ ---
7
+ issues:
8
+ - number: 1
9
+ votes: 0
10
+ created_at: 2009-04-17 14:55:33 -07:00
11
+ body: my sweet, sweet issue
12
+ title: new issue
13
+ updated_at: 2009-04-17 14:55:33 -07:00
14
+ user: schacon
15
+ state: open
16
+ - number: 2
17
+ votes: 0
18
+ created_at: 2009-04-17 15:16:47 -07:00
19
+ body: the body of a second issue
20
+ title: another issue
21
+ updated_at: 2009-04-17 15:16:47 -07:00
22
+ user: schacon
23
+ state: open
24
+ YAML
25
+
26
+ ISSUE_YAML = <<-YAML
27
+ ---
28
+ issue:
29
+ number: 1
30
+ votes: 0
31
+ created_at: 2009-04-17 14:55:33 -07:00
32
+ body: my sweet, sweet issue
33
+ title: new issue
34
+ updated_at: 2009-04-17 14:55:33 -07:00
35
+ user: schacon
36
+ state: open
37
+ YAML
38
+
39
+ LABELS_YAML = <<-YAML
40
+ ---
41
+ labels:
42
+ - testing
43
+ - test_label
44
+ YAML
45
+
46
+ COMMENT_YAML = <<-YAML
47
+ ---
48
+ comment:
49
+ comment: this is amazing
50
+ status: saved
51
+ YAML
52
+
53
+ describe GHI::API do
54
+ it "should require user and repo" do
55
+ proc { GHI::API.new(nil, nil) }.should raise_error(GHI::API::InvalidConnection)
56
+ proc { GHI::API.new("u", nil) }.should raise_error(GHI::API::InvalidConnection)
57
+ proc { GHI::API.new(nil, "r") }.should raise_error(GHI::API::InvalidConnection)
58
+ proc { GHI::API.new("u", "r") }.should_not raise_error(GHI::API::InvalidConnection)
59
+ end
60
+
61
+ describe "requests" do
62
+ before :all do
63
+ @api = GHI::API.new "stephencelis", "ghi"
64
+ GHI.stub!(:login).and_return "stephencelis"
65
+ GHI.stub!(:token).and_return "token"
66
+ end
67
+
68
+ it "should substitute url tokens" do
69
+ @api.send(:url, :open).should ==
70
+ "http://github.com/api/v2/yaml/issues/open/stephencelis/ghi"
71
+ @api.send(:url, :show, 1).should ==
72
+ "http://github.com/api/v2/yaml/issues/show/stephencelis/ghi/1"
73
+ @api.send(:url, :search, :open, "me").should ==
74
+ "http://github.com/api/v2/yaml/issues/search/stephencelis/ghi/open/me"
75
+ @api.send(:url, "label/add", "me").should ==
76
+ "http://github.com/api/v2/yaml/issues/label/add/stephencelis/ghi/me"
77
+ end
78
+
79
+ it "should process gets" do
80
+ url = "http://github.com/api/v2/yaml/issues/open/stephencelis/ghi"
81
+ query = "?login=stephencelis&token=d1cd249db48d51c9847cbf2b291f5ae9"
82
+ @api.stub!(:url).and_return url
83
+ URI.should_receive(:parse).once.with(url + query).and_return("mock")
84
+ Net::HTTP.should_receive(:get).once.with("mock").and_return ISSUES_YAML
85
+ @api.list
86
+ end
87
+
88
+ it "should process posts" do
89
+ url = "http://github.com/api/v2/yaml/issues/open/stephencelis/ghi"
90
+ query = { :login => "stephencelis",
91
+ :token => "d1cd249db48d51c9847cbf2b291f5ae9",
92
+ :title => "Title",
93
+ :body => "Body" }
94
+ @api.stub!(:url).and_return url
95
+ r = mock(Net::HTTPRequest)
96
+ r.should_receive(:body).once.and_return ISSUE_YAML
97
+ URI.should_receive(:parse).once.with(url).and_return "u"
98
+ Net::HTTP.should_receive(:post_form).once.with("u", query).and_return r
99
+ @api.open "Title", "Body"
100
+ end
101
+
102
+ it "should search open by default" do
103
+ @api.should_receive(:url).with(:search, :open, "me").and_return "u"
104
+ Net::HTTP.stub!(:get).and_return ISSUES_YAML
105
+ issues = @api.search "me"
106
+ issues.should be_an_instance_of(Array)
107
+ issues.each { |issue| issue.should be_an_instance_of(GHI::Issue) }
108
+ end
109
+
110
+ it "should search closed" do
111
+ @api.should_receive(:url).with(:search, :closed, "me").and_return "u"
112
+ Net::HTTP.stub!(:get).and_return ISSUES_YAML
113
+ @api.search "me", :closed
114
+ end
115
+
116
+ it "should list open by default" do
117
+ @api.should_receive(:url).with(:list, :open).and_return "u"
118
+ Net::HTTP.stub!(:get).and_return ISSUES_YAML
119
+ issues = @api.list
120
+ issues.should be_an_instance_of(Array)
121
+ issues.each { |issue| issue.should be_an_instance_of(GHI::Issue) }
122
+ end
123
+
124
+ it "should list closed" do
125
+ @api.should_receive(:url).with(:list, :closed).and_return "u"
126
+ Net::HTTP.stub!(:get).and_return ISSUES_YAML
127
+ @api.list :closed
128
+ end
129
+
130
+ it "should show" do
131
+ @api.should_receive(:url).with(:show, 1).and_return "u"
132
+ Net::HTTP.stub!(:get).and_return ISSUE_YAML
133
+ @api.show(1).should be_an_instance_of(GHI::Issue)
134
+ end
135
+
136
+ it "should open" do
137
+ @api.should_receive(:url).with(:open).and_return "u"
138
+ response = mock(Net::HTTPRequest)
139
+ response.stub!(:body).and_return ISSUE_YAML
140
+ Net::HTTP.stub!(:post_form).and_return response
141
+ @api.open("Title", "Body").should be_an_instance_of(GHI::Issue)
142
+ end
143
+
144
+ it "should edit" do
145
+ @api.should_receive(:url).with(:edit, 1).and_return "u"
146
+ response = mock(Net::HTTPRequest)
147
+ response.stub!(:body).and_return ISSUE_YAML
148
+ Net::HTTP.stub!(:post_form).and_return response
149
+ @api.edit(1, "Title", "Body").should be_an_instance_of(GHI::Issue)
150
+ end
151
+
152
+ it "should close" do
153
+ @api.should_receive(:url).with(:close, 1).and_return "u"
154
+ response = mock(Net::HTTPRequest)
155
+ response.stub!(:body).and_return ISSUE_YAML
156
+ Net::HTTP.stub!(:post_form).and_return response
157
+ @api.close(1).should be_an_instance_of(GHI::Issue)
158
+ end
159
+
160
+ it "should reopen" do
161
+ @api.should_receive(:url).with(:reopen, 1).and_return "u"
162
+ response = mock(Net::HTTPRequest)
163
+ response.stub!(:body).and_return ISSUE_YAML
164
+ Net::HTTP.stub!(:post_form).and_return response
165
+ @api.reopen(1).should be_an_instance_of(GHI::Issue)
166
+ end
167
+
168
+ it "should add labels" do
169
+ @api.should_receive(:url).with("label/add", 1, "l").and_return "u"
170
+ response = mock(Net::HTTPRequest)
171
+ response.stub!(:body).and_return LABELS_YAML
172
+ Net::HTTP.stub!(:post_form).and_return response
173
+ @api.add_label(1, "l").should be_an_instance_of(Array)
174
+ end
175
+
176
+ it "should remove labels" do
177
+ @api.should_receive(:url).with("label/remove", 1, "l").and_return "u"
178
+ response = mock(Net::HTTPRequest)
179
+ response.stub!(:body).and_return LABELS_YAML
180
+ Net::HTTP.stub!(:post_form).and_return response
181
+ @api.remove_label(1, "l").should be_an_instance_of(Array)
182
+ end
183
+
184
+ it "should comment" do
185
+ @api.should_receive(:url).with(:comment, 1).and_return "u"
186
+ URI.stub!(:parse).and_return "u"
187
+ response = mock(Net::HTTPRequest)
188
+ response.stub!(:body).and_return COMMENT_YAML
189
+ Net::HTTP.should_receive(:post_form).with("u",
190
+ hash_including(:comment => "Comment")).and_return response
191
+ @api.comment(1, "Comment").should be_an_instance_of(Hash)
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,258 @@
1
+ require "ghi"
2
+ require "ghi/api"
3
+ require "ghi/cli"
4
+
5
+ describe GHI::CLI::Executable do
6
+ before :each do
7
+ @cli = GHI::CLI::Executable.new
8
+ @cli.stub!(:api).and_return(mock(GHI::API))
9
+ $stdout.stub! :close_write
10
+ IO.stub!(:popen).and_return $stdout
11
+ end
12
+
13
+ describe "parsing" do
14
+ describe "with well-formed arguments" do
15
+ before :each do
16
+ @user, @repo = "localuser", "ghi"
17
+ @action = @state = @number = @term =
18
+ @title = @body = @tag = @comment = nil
19
+ end
20
+
21
+ after :each do
22
+ @cli.should_receive(@action)
23
+ @cli.parse! @args
24
+ @cli.action.should == @action
25
+ @cli.state.should == (@state || :open)
26
+ @cli.number.should == @number
27
+ @cli.search_term.should == @term
28
+ @cli.title.should == @title
29
+ @cli.body.should == @body
30
+ @cli.user.should == @user
31
+ @cli.repo.should == @repo
32
+ @cli.tag.should == @tag
33
+ if @commenting
34
+ @cli.should be_commenting
35
+ else
36
+ @cli.should_not be_commenting
37
+ end
38
+ end
39
+
40
+ it "should always parse -r" do
41
+ @args = ["-rremoteuser/remoterepo", "-l"]
42
+ @action, @state, @user, @repo = :list, :open, "remoteuser", "remoterepo"
43
+ end
44
+
45
+ describe "inside a repository" do
46
+ after :each do
47
+ @cli.stub!(:`).and_return "stub@github.com:localuser/ghi.git"
48
+ end
49
+
50
+ it "should parse -l as list open" do
51
+ @args = ["-l"]
52
+ @action, @state = :list, :open
53
+ end
54
+
55
+ it "should parse -lo as list open" do
56
+ @args = ["-lo"]
57
+ @action, @state = :list, :open
58
+ end
59
+
60
+ it "should parse -lc as list closed" do
61
+ @args = ["-lc"]
62
+ @action, @state = :list, :closed
63
+ end
64
+
65
+ it "should parse -l2 as show issue 2" do
66
+ @args = ["-l2"]
67
+ @action, @number = :show, 2
68
+ end
69
+
70
+ it "should parse -l 'term' as search open for 'term'" do
71
+ @args = ["-l", "term"]
72
+ @action, @state, @term = :search, :open, "term"
73
+ end
74
+
75
+ it "should parse -o as open new issue" do
76
+ @args = ["-o"]
77
+ @action = :open
78
+ end
79
+
80
+ it "should parse -o 'New Issue' as open issue with title 'New Issue'" do
81
+ @args = ["-o", "New Issue"]
82
+ @action, @title = :open, "New Issue"
83
+ end
84
+
85
+ it "should parse -om 'New Issue' as open issue with'New Issue'" do
86
+ @args = ["-om", "New Issue"]
87
+ @action, @title = :open, "New Issue"
88
+ end
89
+
90
+ it "should parse -o 'New Issue' -m as open 'New Issue' in $EDITOR" do
91
+ @args = ["-o", "New Issue", "-m"]
92
+ @action, @title, @commenting = :open, "New Issue", true
93
+ end
94
+
95
+ it "should parse -o 'Issue' -m 'Body' as open 'Issue' with 'Body'" do
96
+ @args = ["-o", "Issue", "-m", "Body"]
97
+ @action, @title, @body = :open, "Issue", "Body"
98
+ end
99
+
100
+ it "should parse -o2 as reopen issue 2" do
101
+ @args = ["-o2"]
102
+ @action, @number = :reopen, 2
103
+ end
104
+
105
+ it "should parse -o2 -m as reopen issue 2 with a comment" do
106
+ @args = ["-o2", "-m"]
107
+ @action, @number, @commenting = :reopen, 2, true
108
+ end
109
+
110
+ it "should parse -o2 -m 'Comment' as reopen issue 2" do
111
+ @args = ["-o2", "-m", "Comment"]
112
+ @action, @number, @body = :reopen, 2, "Comment"
113
+ end
114
+
115
+ it "should parse -ol as list open" do
116
+ @args = ["-ol"]
117
+ @action, @state = :list, :open
118
+ end
119
+
120
+ it "should parse -ou as return open issues url" do
121
+ @args = ["-ou"]
122
+ @action = :url # Should state be :open?
123
+ end
124
+
125
+ it "should parse -cl as list closed" do
126
+ @args = ["-cl"]
127
+ @action, @state = :list, :closed
128
+ end
129
+
130
+ it "should parse -c2 as close issue 2" do
131
+ @args = ["-c2"]
132
+ @action, @number = :close, 2
133
+ end
134
+
135
+ it "should parse -c2 -m as close issue 2 with a comment" do
136
+ @args = ["-c2", "-m"]
137
+ @action, @number, @commenting = :close, 2, true
138
+ end
139
+
140
+ it "should parse -c2 -m 'Fixed' as close issue 2 with 'Fixed'" do
141
+ @args = ["-c2", "-m", "Fixed"]
142
+ @action, @number, @body = :close, 2, "Fixed"
143
+ end
144
+
145
+ it "should parse -m2 -c as close issue 2 with a comment" do
146
+ @args = ["-m2", "-c"]
147
+ @action, @number, @commenting = :close, 2, true
148
+ end
149
+
150
+ it "should parse -cu as return closed issues url" do
151
+ @args = ["-cu"]
152
+ @action, @state = :url, :closed
153
+ end
154
+
155
+ it "should parse -e2 as edit issue 2" do
156
+ @args = ["-e2"]
157
+ @action, @number = :edit, 2
158
+ end
159
+
160
+ it "should parse -rlocalrepo as localuser/localrepo" do
161
+ GHI.stub!(:login).and_return "localuser"
162
+ @args = ["-rlocalrepo", "-l"]
163
+ @action, @state, @user, @repo = :list, :open, "localuser", "localrepo"
164
+ end
165
+
166
+ it "should parse -rremoteuser/remoterepo as remoteuser/remoterepo" do
167
+ @args = ["-rremoteuser/remoterepo", "-l"]
168
+ @action, @state, @user, @repo = :list, :open, "remoteuser", "remoterepo"
169
+ end
170
+
171
+ it "should parse -rremoteuser/remoterepo as a later argument" do
172
+ @args = ["-1", "-rremoteuser/remoterepo"]
173
+ @action, @number, @user, @repo = :show, 1, "remoteuser", "remoterepo"
174
+ end
175
+
176
+ it "should parse -t2 'tag' as label issue 2 with 'tag'" do
177
+ @args = ["-t2", "tag"]
178
+ @action, @number, @tag = :label, 2, "tag"
179
+ end
180
+
181
+ it "should parse -d2 'tag' as remove label 'tag' from issue 2" do
182
+ @args = ["-d2", "tag"]
183
+ @action, @number, @tag = :unlabel, 2, "tag"
184
+ end
185
+
186
+ it "should parse -m2 as comment on issue 2" do
187
+ @args = ["-m2"]
188
+ @action, @number, @commenting = :comment, 2, true
189
+ end
190
+
191
+ it "should parse -m2 'Comment' as comment 'Comment' on issue 2" do
192
+ @args = ["-m2", "Comment"]
193
+ @action, @number, @body = :comment, 2, "Comment"
194
+ end
195
+
196
+ it "should parse -u as return open issues url" do
197
+ @args = ["-u"]
198
+ @action = :url # Should state be :open?
199
+ end
200
+
201
+ it "should parse -uo as return open issues url" do
202
+ @args = ["-uo"]
203
+ @action = :url # Should state be :open?
204
+ end
205
+
206
+ it "should parse -uc as return open issues url" do
207
+ @args = ["-uc"]
208
+ @action, @state = :url, :closed
209
+ end
210
+
211
+ it "should parse -u2 as return issue 2 url" do
212
+ @args = ["-u2"]
213
+ @action, @number = :url, 2
214
+ end
215
+
216
+ it "should parse -uu as return unread issues url" do
217
+ @args = ["-uu"]
218
+ @action, @state = :url, :unread
219
+ end
220
+ end
221
+ end
222
+
223
+ describe "with malformed arguments" do
224
+ before :each do
225
+ @cli.should_receive :warn
226
+ @cli.should_receive(:exit).with 1
227
+ end
228
+
229
+ it "should exit with -e" do
230
+ @cli.should_receive :puts
231
+ @cli.parse! ["-e"]
232
+ end
233
+
234
+ it "should exit with -e 'invalid'" do
235
+ @cli.should_receive :puts
236
+ @cli.parse! ["-e", "invalid"]
237
+ end
238
+
239
+ it "should exit with -c as list closed" do
240
+ @cli.parse! ["-c"]
241
+ end
242
+
243
+ it "should exit with -r" do
244
+ @cli.should_receive :puts
245
+ @cli.parse! ["-r"]
246
+ end
247
+
248
+ it "should exit with -t" do
249
+ @cli.should_receive :puts
250
+ @cli.parse! ["-t"]
251
+ end
252
+
253
+ it "should exit with -t2" do
254
+ @cli.parse! ["-t2"]
255
+ end
256
+ end
257
+ end
258
+ end