octokit 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. data/.document +4 -0
  2. data/.gitignore +24 -0
  3. data/Gemfile +3 -0
  4. data/LICENSE +20 -0
  5. data/README.markdown +69 -0
  6. data/Rakefile +14 -0
  7. data/changelog.markdown +34 -0
  8. data/lib/faraday/raise_error.rb +41 -0
  9. data/lib/octokit.rb +49 -0
  10. data/lib/octokit/client.rb +30 -0
  11. data/lib/octokit/client/authentication.rb +19 -0
  12. data/lib/octokit/client/commits.rb +16 -0
  13. data/lib/octokit/client/connection.rb +32 -0
  14. data/lib/octokit/client/issues.rb +60 -0
  15. data/lib/octokit/client/network.rb +15 -0
  16. data/lib/octokit/client/objects.rb +33 -0
  17. data/lib/octokit/client/organizations.rb +89 -0
  18. data/lib/octokit/client/pulls.rb +19 -0
  19. data/lib/octokit/client/repositories.rb +130 -0
  20. data/lib/octokit/client/request.rb +41 -0
  21. data/lib/octokit/client/timelines.rb +20 -0
  22. data/lib/octokit/client/users.rb +77 -0
  23. data/lib/octokit/configuration.rb +45 -0
  24. data/lib/octokit/event.rb +76 -0
  25. data/lib/octokit/repository.rb +39 -0
  26. data/lib/octokit/version.rb +3 -0
  27. data/octokit.gemspec +33 -0
  28. data/test/fixtures/blob.json +10 -0
  29. data/test/fixtures/branch_commits.json +48 -0
  30. data/test/fixtures/branches.json +6 -0
  31. data/test/fixtures/close_issue.json +1 -0
  32. data/test/fixtures/collaborators.json +1 -0
  33. data/test/fixtures/comment.json +1 -0
  34. data/test/fixtures/commits.json +824 -0
  35. data/test/fixtures/contributors.json +6 -0
  36. data/test/fixtures/emails.json +1 -0
  37. data/test/fixtures/followers.json +3 -0
  38. data/test/fixtures/full_user.json +27 -0
  39. data/test/fixtures/issue.json +14 -0
  40. data/test/fixtures/issues.json +50 -0
  41. data/test/fixtures/keys.json +1 -0
  42. data/test/fixtures/labels.json +1 -0
  43. data/test/fixtures/languages.json +1 -0
  44. data/test/fixtures/network.json +26 -0
  45. data/test/fixtures/network_data.json +1 -0
  46. data/test/fixtures/network_meta.json +109 -0
  47. data/test/fixtures/open_issue.json +1 -0
  48. data/test/fixtures/raw_git_data.yaml +7 -0
  49. data/test/fixtures/reopen_issue.json +1 -0
  50. data/test/fixtures/repo.json +14 -0
  51. data/test/fixtures/repo_search.json +452 -0
  52. data/test/fixtures/repos.json +830 -0
  53. data/test/fixtures/search.json +44 -0
  54. data/test/fixtures/show_commit.json +37 -0
  55. data/test/fixtures/tags.json +8 -0
  56. data/test/fixtures/timeline.json +1018 -0
  57. data/test/fixtures/trees.json +140 -0
  58. data/test/fixtures/user.json +16 -0
  59. data/test/helper.rb +57 -0
  60. data/test/octokit_test.rb +765 -0
  61. data/test/repository_test.rb +45 -0
  62. metadata +377 -0
@@ -0,0 +1,140 @@
1
+ {
2
+ "tree": [{
3
+ "name": ".gitignore",
4
+ "sha": "e43b0f988953ae3a84b00331d0ccf5f7d51cb3cf",
5
+ "mode": "100644",
6
+ "type": "blob"
7
+ },
8
+ {
9
+ "name": "README.txt",
10
+ "sha": "d4fc2d5e810d9b4bc1ce67702603080e3086a4ed",
11
+ "mode": "100644",
12
+ "type": "blob"
13
+ },
14
+ {
15
+ "name": "b.png",
16
+ "sha": "f184e6269b343014f58694093b55558dd5dde193",
17
+ "mode": "100644",
18
+ "type": "blob"
19
+ },
20
+ {
21
+ "name": "bl.png",
22
+ "sha": "f6271859d51654b6fb2719df5fe192c8398ecefc",
23
+ "mode": "100644",
24
+ "type": "blob"
25
+ },
26
+ {
27
+ "name": "br.png",
28
+ "sha": "31f204fc451cd9dd5cfdadfad2d86ed0e1104882",
29
+ "mode": "100644",
30
+ "type": "blob"
31
+ },
32
+ {
33
+ "name": "build_tar.sh",
34
+ "sha": "08f6f1fce2f6a02dcb15b6c66244470794587bb0",
35
+ "mode": "100755",
36
+ "type": "blob"
37
+ },
38
+ {
39
+ "name": "closelabel.gif",
40
+ "sha": "87b4f8bd699386e3a6fcc2e50d7c61bfc4aabb8d",
41
+ "mode": "100755",
42
+ "type": "blob"
43
+ },
44
+ {
45
+ "name": "facebox.css",
46
+ "sha": "08e190d5f81959d73d2bdd3e4f752271800886bf",
47
+ "mode": "100644",
48
+ "type": "blob"
49
+ },
50
+ {
51
+ "name": "facebox.js",
52
+ "sha": "43245f3b1b50a0568ece00b44d2dc67be413f2a4",
53
+ "mode": "100644",
54
+ "type": "blob"
55
+ },
56
+ {
57
+ "name": "faceplant.css",
58
+ "sha": "dc61a86c3f342b930f0a0447cae33fee812e27d3",
59
+ "mode": "100644",
60
+ "type": "blob"
61
+ },
62
+ {
63
+ "name": "index.html",
64
+ "sha": "a9d1c235d08ae383e4d9dedf5e2cc0236defdaa6",
65
+ "mode": "100644",
66
+ "type": "blob"
67
+ },
68
+ {
69
+ "name": "jquery.js",
70
+ "sha": "ebe02bdd357c337e0e817fcbce2a034a54a13287",
71
+ "mode": "100644",
72
+ "type": "blob"
73
+ },
74
+ {
75
+ "name": "loading.gif",
76
+ "sha": "f864d5fd38b7466c76b5a36dc0e3e9455c0126e2",
77
+ "mode": "100755",
78
+ "type": "blob"
79
+ },
80
+ {
81
+ "name": "logo.png",
82
+ "sha": "e41cfe5c654e8e05ad46f15af1c462a1360e9764",
83
+ "mode": "100644",
84
+ "type": "blob"
85
+ },
86
+ {
87
+ "name": "releases",
88
+ "sha": "82e3a754b6a0fcb238b03c0e47d05219fbf9cf89",
89
+ "mode": "040000",
90
+ "type": "tree"
91
+ },
92
+ {
93
+ "name": "remote.html",
94
+ "sha": "98d3e92373d1bc541e7f516e5e73b645a991ddc2",
95
+ "mode": "100644",
96
+ "type": "blob"
97
+ },
98
+ {
99
+ "name": "screenshots",
100
+ "sha": "bbf747873075ac28667d246491ffdefbd314fe4f",
101
+ "mode": "040000",
102
+ "type": "tree"
103
+ },
104
+ {
105
+ "name": "shadow.gif",
106
+ "sha": "e58b35b362ce5347bb5064e91a3bf8e4fed4f6ef",
107
+ "mode": "100644",
108
+ "type": "blob"
109
+ },
110
+ {
111
+ "name": "stairs.jpg",
112
+ "sha": "63459bb418f5f6d896a8eb925c01f45024933ed6",
113
+ "mode": "100644",
114
+ "type": "blob"
115
+ },
116
+ {
117
+ "name": "test.html",
118
+ "sha": "0a279c66167d358e40682186864935d0f856c4c4",
119
+ "mode": "100644",
120
+ "type": "blob"
121
+ },
122
+ {
123
+ "name": "test_programmatic.html",
124
+ "sha": "0249382efbdc7412a67976d19154ef07ac51437f",
125
+ "mode": "100644",
126
+ "type": "blob"
127
+ },
128
+ {
129
+ "name": "tl.png",
130
+ "sha": "d99c8f6c6eaa12d7b49a20f41f08a5006f3ea8b7",
131
+ "mode": "100644",
132
+ "type": "blob"
133
+ },
134
+ {
135
+ "name": "tr.png",
136
+ "sha": "e99b6ec8310e859fd27519694f04e1babf2ab2c4",
137
+ "mode": "100644",
138
+ "type": "blob"
139
+ }]
140
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "user": {
3
+ "name": "Wynn Netherland",
4
+ "company": "Orrka",
5
+ "location": "Dallas, TX",
6
+ "created_at": "2008/02/25 10:24:19 -0800",
7
+ "public_gist_count": 3,
8
+ "public_repo_count": 15,
9
+ "blog": "http://wynnnetherland.com",
10
+ "following_count": 55,
11
+ "id": 865,
12
+ "followers_count": 21,
13
+ "login": "pengwynn",
14
+ "email": "wynn.netherland@gmail.com"
15
+ }
16
+ }
@@ -0,0 +1,57 @@
1
+ require 'test/unit'
2
+ require 'pathname'
3
+
4
+ require 'shoulda'
5
+ require 'matchy'
6
+ require 'mocha'
7
+ require 'fakeweb'
8
+
9
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
10
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
11
+ require 'octokit'
12
+
13
+ FakeWeb.allow_net_connect = false
14
+
15
+ class Test::Unit::TestCase
16
+ end
17
+
18
+ def fixture_file(filename)
19
+ return '' if filename == ''
20
+ file_path = File.expand_path(File.dirname(__FILE__) + '/fixtures/' + filename)
21
+ File.read(file_path)
22
+ end
23
+
24
+ def github_url(url)
25
+ if url =~ /^http/
26
+ url
27
+ elsif @client && @client.authenticated?
28
+ "https://pengwynn%2Ftoken:OU812@github.com/api/v#{Octokit.version}/#{Octokit.format}/#{url}"
29
+ else
30
+ "https://github.com/api/v#{Octokit.version}/#{Octokit.format}/#{url}"
31
+ end
32
+ end
33
+
34
+ def stub_request(method, url, filename, status=nil)
35
+ options = {:body => ""}
36
+ options.merge!({:body => fixture_file(filename)}) if filename
37
+ options.merge!({:body => status.last}) if status
38
+ options.merge!({:status => status}) if status
39
+
40
+ FakeWeb.register_uri(method, github_url(url), options)
41
+ end
42
+
43
+ def stub_delete(*args)
44
+ stub_request(:delete, *args)
45
+ end
46
+
47
+ def stub_get(*args)
48
+ stub_request(:get, *args)
49
+ end
50
+
51
+ def stub_post(*args)
52
+ stub_request(:post, *args)
53
+ end
54
+
55
+ def stub_put(*args)
56
+ stub_request(:put, *args)
57
+ end
@@ -0,0 +1,765 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+
3
+ class OctokitTest < Test::Unit::TestCase
4
+
5
+ context "when authenticated" do
6
+ setup do
7
+ @client = Octokit::Client.new(:login => 'pengwynn', :token => 'OU812')
8
+ end
9
+
10
+ should "should search users" do
11
+ stub_get("user/search/wynn", "search.json")
12
+ users = @client.search_users("wynn")
13
+ users.first.username.should == 'pengwynn'
14
+ end
15
+
16
+ should "return full user info for the authenticated user" do
17
+ stub_get("user/show", "full_user.json")
18
+ user = @client.user
19
+ user.plan.name.should == 'free'
20
+ user.plan.space.should == 307200
21
+ end
22
+
23
+ should "return followers for a user" do
24
+ stub_get("user/show/pengwynn/followers", "followers.json")
25
+ followers = @client.followers("pengwynn")
26
+ followers.size.should == 21
27
+ assert followers.include?("adamstac")
28
+ end
29
+
30
+ should "return followers for the authenticated user" do
31
+ stub_get("user/show/pengwynn/followers", "followers.json")
32
+ followers = @client.followers
33
+ followers.size.should == 21
34
+ assert followers.include?("adamstac")
35
+ end
36
+
37
+ should "return users a user follows" do
38
+ stub_get("user/show/pengwynn/following", "followers.json")
39
+ followers = @client.following("pengwynn")
40
+ followers.size.should == 21
41
+ assert followers.include?("adamstac")
42
+ end
43
+
44
+ should "return the users the authenticated user follows" do
45
+ stub_get("user/show/pengwynn/following", "followers.json")
46
+ followers = @client.following
47
+ followers.size.should == 21
48
+ assert followers.include?("adamstac")
49
+ end
50
+
51
+ should "indicate if one user follows another" do
52
+ stub_get("user/show/pengwynn/following", "followers.json")
53
+ @client.follows?('adamstac')
54
+ end
55
+
56
+ should "return the repos a user watches" do
57
+ stub_get("repos/watched/pengwynn", "repos.json")
58
+ repos = @client.watched
59
+ repos.first.owner.should == 'jnunemaker'
60
+ repos.first.forks.should == 120
61
+ end
62
+
63
+ should "return the repos the authenticated user watched" do
64
+ stub_get("repos/watched/pengwynn", "repos.json")
65
+ repos = @client.watched('pengwynn')
66
+ repos.first.owner.should == 'jnunemaker'
67
+ repos.first.forks.should == 120
68
+ end
69
+
70
+ should "update user info" do
71
+ stub_post("user/show/pengwynn", "user.json")
72
+ user = @client.update_user(:location => "Dallas, TX")
73
+ user.location.should == 'Dallas, TX'
74
+ end
75
+
76
+ should "return emails for the authenticated user" do
77
+ stub_get("user/emails", "emails.json")
78
+ emails = @client.emails
79
+ emails.size.should == 3
80
+ assert emails.include? "wynn@orrka.com"
81
+ end
82
+
83
+ should "add an email for the authenticated user" do
84
+ stub_post("user/email/add", "emails.json")
85
+ emails = @client.add_email('wynn@orrka.com')
86
+ emails.size.should == 3
87
+ assert emails.include? "wynn@orrka.com"
88
+ end
89
+
90
+ should "remove an email for the authenticated user" do
91
+ stub_post("user/email/remove", "emails.json")
92
+ emails = @client.remove_email('wynn@squeejee.com')
93
+ emails.size.should == 3
94
+ end
95
+
96
+ should "return keys for the authenticated user" do
97
+ stub_get("user/keys", "keys.json")
98
+ keys = @client.keys
99
+ keys.size.should == 6
100
+ keys.last.title.should == 'wynn@pengwynn.local'
101
+ end
102
+
103
+ should "add an key for the authenticated user" do
104
+ stub_post("user/key/add", "keys.json")
105
+ keys = @client.add_key('pengwynn', 'ssh-rsa 009aasd0kalsdfa-sd9a-sdf')
106
+ keys.size.should == 6
107
+ keys.last.title.should == 'wynn@pengwynn.local'
108
+ end
109
+
110
+ should "remove an key for the authenticated user" do
111
+ stub_post("user/key/remove", "keys.json")
112
+ keys = @client.remove_key(1234)
113
+ keys.size.should == 6
114
+ end
115
+
116
+ should "open an issue" do
117
+ stub_post("issues/open/pengwynn/linkedin", "open_issue.json")
118
+ issue = @client.open_issue({:username => "pengwynn", :repo => "linkedin"}, "testing", "Testing api")
119
+ issue.title.should == "testing"
120
+ issue.number.should == 2
121
+ end
122
+
123
+ should "close an issue" do
124
+ stub_post("issues/close/pengwynn/linkedin/2", "close_issue.json")
125
+ issue = @client.close_issue({:username => "pengwynn", :repo => "linkedin"}, 2)
126
+ issue.title.should == "testing"
127
+ issue.number.should == 2
128
+ end
129
+
130
+ should "reopen an issue" do
131
+ stub_post("issues/reopen/pengwynn/linkedin/2", "reopen_issue.json")
132
+ issue = @client.close_issue({:username => "pengwynn", :repo => "linkedin"}, 2)
133
+ issue.title.should == "testing"
134
+ issue.number.should == 2
135
+ end
136
+
137
+ should "edit an issue" do
138
+ stub_post("issues/edit/pengwynn/linkedin/2", "open_issue.json")
139
+ issue = @client.update_issue("pengwynn/linkedin", 2, "testing", "Testing api")
140
+ issue.title.should == "testing"
141
+ issue.number.should == 2
142
+ end
143
+
144
+ should "list issue labels for a repo" do
145
+ stub_get("issues/labels/pengwynn/linkedin", "labels.json")
146
+ labels = @client.labels("pengwynn/linkedin")
147
+ labels.first.should == 'oauth'
148
+ end
149
+
150
+ should "add a label to an issue" do
151
+ stub_post("issues/label/add/pengwynn/linkedin/oauth/2", "labels.json")
152
+ labels = @client.add_label('pengwynn/linkedin', 2, 'oauth')
153
+ assert labels.include?("oauth")
154
+ end
155
+
156
+ should "remove a label from an issue" do
157
+ stub_post("issues/label/remove/pengwynn/linkedin/oauth/2", "labels.json")
158
+ labels = @client.remove_label('pengwynn/linkedin', 2, 'oauth')
159
+ assert labels.is_a?(Array)
160
+ end
161
+
162
+ should "add a comment to an issue" do
163
+ stub_post("issues/comment/pengwynn/linkedin/2", "comment.json")
164
+ comment = @client.add_comment('pengwynn/linkedin', 2, 'Nice catch!')
165
+ comment.comment.should == 'Nice catch!'
166
+ end
167
+
168
+ should "watch a repository" do
169
+ stub_post("repos/watch/pengwynn/linkedin", "repo.json")
170
+ repo = @client.watch('pengwynn/linkedin')
171
+ repo.homepage.should == "http://bit.ly/ruby-linkedin"
172
+ end
173
+
174
+ should "unwatch a repository" do
175
+ stub_post("repos/unwatch/pengwynn/linkedin", "repo.json")
176
+ repo = @client.unwatch('pengwynn/linkedin')
177
+ repo.homepage.should == "http://bit.ly/ruby-linkedin"
178
+ end
179
+
180
+ should "fork a repository" do
181
+ stub_post("repos/fork/pengwynn/linkedin", "repo.json")
182
+ repo = @client.fork('pengwynn/linkedin')
183
+ repo.homepage.should == "http://bit.ly/ruby-linkedin"
184
+ end
185
+
186
+ should "create a repository" do
187
+ stub_post("repos/create", "repo.json")
188
+ repo = @client.create(:name => 'linkedin', :description => 'Ruby wrapper for the LinkedIn API', :homepage => 'http://bit.ly/ruby-linkedin', :public => 1)
189
+ repo.homepage.should == "http://bit.ly/ruby-linkedin"
190
+ end
191
+
192
+ # should "return a delete_token when calling delete without supplying a delete_token" do
193
+ #
194
+ # end
195
+
196
+ should "set a repo's visibility to private" do
197
+ stub_post("repos/set/private/linkedin", "repo.json")
198
+ repo = @client.set_private('linkedin')
199
+ repo.homepage.should == "http://bit.ly/ruby-linkedin"
200
+ end
201
+
202
+ should "set a repo's visibility to public" do
203
+ stub_post("repos/set/public/linkedin", "repo.json")
204
+ repo = @client.set_public('linkedin')
205
+ repo.homepage.should == "http://bit.ly/ruby-linkedin"
206
+ end
207
+
208
+ should "return deploy keys for a repo" do
209
+ stub_get("repos/keys/linkedin", "keys.json")
210
+ keys = @client.deploy_keys('linkedin')
211
+ keys.size.should == 6
212
+ keys.last.title.should == 'wynn@pengwynn.local'
213
+ end
214
+
215
+ should "add a deploy key for a repo" do
216
+ stub_post("repos/key/pengwynn/linkedin/add", "keys.json")
217
+ keys = @client.add_deploy_key('pengwynn/linkedin', 'ssh-rsa 009aasd0kalsdfa-sd9a-sdf')
218
+ keys.size.should == 6
219
+ keys.last.title.should == 'wynn@pengwynn.local'
220
+ end
221
+
222
+ should "remove a deploy key for a repo" do
223
+ stub_post("repos/key/pengwynn/linkedin/remove", "keys.json")
224
+ keys = @client.remove_deploy_key('pengwynn/linkedin', 1234)
225
+ keys.size.should == 6
226
+ end
227
+
228
+ should "add a collaborator to a repo" do
229
+ stub_post("repos/collaborators/linkedin/add/adamstac", "collaborators.json")
230
+ collaborators = @client.add_collaborator("linkedin", "adamstac")
231
+ collaborators.first.should == 'pengwynn'
232
+ end
233
+
234
+ should "remove a collaborator from a repo" do
235
+ stub_post("repos/collaborators/linkedin/remove/adamstac", "collaborators.json")
236
+ collaborators = @client.remove_collaborator("linkedin", "adamstac")
237
+ collaborators.last.should == 'adamstac'
238
+ end
239
+
240
+ should "fetch a user's public timeline" do
241
+ stub_get("https://pengwynn%2Ftoken:OU812@github.com/pengwynn.json", "timeline.json")
242
+ events = @client.public_timeline('pengwynn')
243
+ events.first['type'].should == 'FollowEvent'
244
+ events[1].repository.name.should == 'octokit'
245
+ end
246
+
247
+ should "fetch a user's private timeline" do
248
+ stub_get("https://pengwynn%2Ftoken:OU812@github.com/pengwynn.private.json", "timeline.json")
249
+ events = @client.timeline
250
+ events.first['type'].should == 'FollowEvent'
251
+ events[1].repository.name.should == 'octokit'
252
+ end
253
+ end
254
+
255
+
256
+ context "when unauthenticated" do
257
+
258
+ should "search users" do
259
+ stub_get("user/search/wynn", "search.json")
260
+ users = Octokit.search_users("wynn")
261
+ users.first.username.should == 'pengwynn'
262
+ end
263
+
264
+ should "return user info" do
265
+ stub_get("user/show/pengwynn", "user.json")
266
+ user = Octokit.user("pengwynn")
267
+ user.login.should == 'pengwynn'
268
+ user.blog.should == 'http://wynnnetherland.com'
269
+ user.name.should == 'Wynn Netherland'
270
+ end
271
+
272
+ should "return followers for a user" do
273
+ stub_get("user/show/pengwynn/followers", "followers.json")
274
+ followers = Octokit.followers("pengwynn")
275
+ followers.size.should == 21
276
+ assert followers.include?("adamstac")
277
+ end
278
+
279
+ should "indicate if one user follows another" do
280
+ stub_get("user/show/pengwynn/following", "followers.json")
281
+ assert Octokit.follows?('pengwynn', 'adamstac')
282
+ end
283
+
284
+ should "return users a user follows" do
285
+ stub_get("user/show/pengwynn/following", "followers.json")
286
+ followers = Octokit.following("pengwynn")
287
+ followers.size.should == 21
288
+ assert followers.include?("adamstac")
289
+ end
290
+
291
+ should "return the repos a user watches" do
292
+ stub_get("repos/watched/pengwynn", "repos.json")
293
+ repos = Octokit.watched('pengwynn')
294
+ repos.first.owner.should == 'jnunemaker'
295
+ repos.first.forks.should == 120
296
+ end
297
+
298
+ should "search issues for a repo" do
299
+ stub_get("issues/search/jnunemaker/twitter/open/httparty", "issues.json")
300
+ issues = Octokit.search_issues({:username => 'jnunemaker', :repo => 'twitter'}, 'httparty')
301
+ issues.first.title.should == 'Crack error when creating friendship'
302
+ issues.first.votes.should == 2
303
+ end
304
+
305
+ should "list issues for a repo" do
306
+ stub_get("issues/list/jnunemaker/twitter/open", "issues.json")
307
+ issues = Octokit.issues({:username => 'jnunemaker', :repo => 'twitter'}, 'open')
308
+ issues.first.title.should == 'Crack error when creating friendship'
309
+ issues.first.votes.should == 2
310
+ end
311
+
312
+ should "return issue info" do
313
+ stub_get("issues/show/jnunemaker/twitter/3", "issue.json")
314
+ issue = Octokit.issue({:username => 'jnunemaker', :repo => 'twitter'}, 3)
315
+ issue.title.should == 'Crack error when creating friendship'
316
+ issue.votes.should == 2
317
+ end
318
+
319
+ # Repos
320
+
321
+ should "search repos" do
322
+ stub_get("repos/search/compass", "repo_search.json")
323
+ repos = Octokit.search_repos("compass")
324
+ repos.first.username.should == 'chriseppstein'
325
+ repos.first.language.should == 'Ruby'
326
+ end
327
+
328
+ should "return repo information" do
329
+ stub_get("repos/show/pengwynn/linkedin", "repo.json")
330
+ repo = Octokit.repo({:username => "pengwynn", :repo => "linkedin"})
331
+ repo.homepage.should == "http://bit.ly/ruby-linkedin"
332
+ end
333
+
334
+ should "return a repo's contributors list" do
335
+ stub_get("repos/show/pengwynn/linkedin/contributors", "contributors.json")
336
+ contributors_list = Octokit.contributors({:username => "pengwynn", :repo => "linkedin"})
337
+ assert contributors_list.include?(["holman", 1])
338
+ end
339
+
340
+ should "list repos for a user" do
341
+ stub_get("repos/show/pengwynn", "repos.json")
342
+ repos = Octokit.list_repos('pengwynn')
343
+ repos.first.name.should == 'twitter'
344
+ repos.first.watchers.should == 609
345
+ end
346
+
347
+ should "list collaborators for a repo" do
348
+ stub_get("repos/show/pengwynn/octokit/collaborators", "collaborators.json")
349
+ users = Octokit.collaborators({:username => "pengwynn", :repo => "octokit"})
350
+ users.last.should == 'adamstac'
351
+ end
352
+
353
+ should "show the network for a repo" do
354
+ stub_get("repos/show/pengwynn/linkedin/network", "network.json")
355
+ network = Octokit.network({:username => 'pengwynn', :repo => "linkedin"})
356
+ network.last.owner.should == 'nfo'
357
+ end
358
+
359
+ should "show the language breakdown for a repo" do
360
+ stub_get("repos/show/pengwynn/linkedin/languages", "languages.json")
361
+ languages = Octokit.languages({:username => 'pengwynn', :repo => "linkedin"})
362
+ languages['Ruby'].should == 21515
363
+ end
364
+
365
+ should "list all the tags in a repo" do
366
+ stub_get("repos/show/pengwynn/linkedin/tags", "tags.json")
367
+ tags = Octokit.tags(:username => 'pengwynn', :repo => "linkedin")
368
+ assert tags.include?("v0.0.1")
369
+ end
370
+
371
+ should "list all the branches in a repo" do
372
+ stub_get("repos/show/pengwynn/linkedin/branches", "branches.json")
373
+ branches = Octokit.branches(:username => 'pengwynn', :repo => "linkedin")
374
+ assert branches.include?("integration")
375
+ end
376
+
377
+ # network
378
+ should "return network meta info for a repo" do
379
+ stub_get("https://github.com/schacon/simplegit/network_meta", "network_meta.json")
380
+ info = Octokit.network_meta(:username => "schacon", :repo => "simplegit")
381
+ info.users.first.name.should == 'schacon'
382
+ info.users.first.repo.should == 'simplegit'
383
+ end
384
+
385
+ should "return first 100 commits by branch" do
386
+ stub_get("https://github.com/schacon/simplegit/network_data_chunk?nethash=fa8fe264b926cdebaab36420b6501bd74402a6ff", "network_data.json")
387
+ info = Octokit.network_data({:username => "schacon", :repo => "simplegit"}, "fa8fe264b926cdebaab36420b6501bd74402a6ff")
388
+ assert info.is_a?(Array)
389
+ end
390
+
391
+ # trees
392
+ should "return contents of a tree by tree SHA" do
393
+ stub_get("tree/show/defunkt/facebox/a47803c9ba26213ff194f042ab686a7749b17476", "trees.json")
394
+ trees = Octokit.tree({:username => "defunkt", :repo => "facebox"}, "a47803c9ba26213ff194f042ab686a7749b17476")
395
+ trees.first.name.should == '.gitignore'
396
+ trees.first.sha.should == 'e43b0f988953ae3a84b00331d0ccf5f7d51cb3cf'
397
+ end
398
+
399
+ should "return data about a blob by tree SHA and path" do
400
+ stub_get("blob/show/defunkt/facebox/d4fc2d5e810d9b4bc1ce67702603080e3086a4ed/README.txt", "blob.json")
401
+ blob = Octokit.blob({:username => "defunkt", :repo => "facebox"}, "d4fc2d5e810d9b4bc1ce67702603080e3086a4ed", "README.txt")
402
+ blob.name.should == 'README.txt'
403
+ blob.sha.should == 'd4fc2d5e810d9b4bc1ce67702603080e3086a4ed'
404
+ end
405
+
406
+ should "return the contents of a blob with the blob's SHA" do
407
+ begin
408
+ Octokit.format = :yaml
409
+ stub_get("blob/show/defunkt/facebox/4bf7a39e8c4ec54f8b4cd594a3616d69004aba69", "raw_git_data.yaml")
410
+ raw_text = Octokit.raw({:username => "defunkt", :repo => "facebox"}, "4bf7a39e8c4ec54f8b4cd594a3616d69004aba69")
411
+ ensure
412
+ Octokit.format = :json
413
+ end
414
+ assert raw_text.include?("cd13d9a61288dceb0a7aa73b55ed2fd019f4f1f7")
415
+ end
416
+
417
+ #commits
418
+ should "list commits for a repo's master branch by default" do
419
+ stub_get("commits/list/defunkt/facebox/master", "commits.json")
420
+ commits_list = Octokit.list_commits({:username => "defunkt", :repo => "facebox"})
421
+ assert commits_list.any? { |c| c.message == "Fixed CSS expression, throwing errors in IE6." }
422
+ end
423
+
424
+ should "list commits for a repo on a given branch" do
425
+ stub_get("commits/list/schacon/simplegit/m/dev/cp", "branch_commits.json")
426
+ commits_list = Octokit.list_commits({:username => "schacon", :repo => "simplegit"}, "m/dev/cp")
427
+ assert commits_list.any? { |c| c.message == "removed unnecessary test code" }
428
+ end
429
+
430
+ should "show a specific commit for a repo given its SHA" do
431
+ sha = "1ff368f79b0f0aa0e1f1d78bcaa8691f94f9703e"
432
+ stub_get("commits/show/defunkt/facebox/#{sha}", "show_commit.json")
433
+ show_commit = Octokit.commit({:username => "defunkt", :repo => "facebox"}, sha)
434
+ assert show_commit.message == "Fixed CSS expression, throwing errors in IE6."
435
+ end
436
+
437
+ #timeline
438
+
439
+ should "fetch the public timeline" do
440
+ stub_get("https://github.com/timeline.json", "timeline.json")
441
+ events = Octokit.public_timeline
442
+ events.first['type'].should == 'FollowEvent'
443
+ events[1].repository.name.should == 'octokit'
444
+ end
445
+
446
+ should "fetch a user's public timeline" do
447
+ stub_get("https://github.com/pengwynn.json", "timeline.json")
448
+ events = Octokit.public_timeline('pengwynn')
449
+ events.first['type'].should == 'FollowEvent'
450
+ events[1].repository.name.should == 'octokit'
451
+ end
452
+
453
+ end
454
+
455
+ context "when Github responds with an error" do
456
+ {
457
+ ["400", "BadRequest"] => Octokit::BadRequest,
458
+ ["401", "Unauthorized"] => Octokit::Unauthorized,
459
+ ["403", "Forbidden"] => Octokit::Forbidden,
460
+ ["404", "NotFound"] => Octokit::NotFound,
461
+ ["406", "NotAcceptable"] => Octokit::NotAcceptable,
462
+ ["500", "InternalServerError"] => Octokit::InternalServerError,
463
+ ["501", "NotImplemented"] => Octokit::NotImplemented,
464
+ ["502", "BadGateway"] => Octokit::BadGateway,
465
+ ["503", "ServiceUnavailable"] => Octokit::ServiceUnavailable,
466
+ }.each do |status, exception|
467
+ context "#{status.first}, a get" do
468
+ should "raise an #{exception.name} error" do
469
+ stub_get("user/show/pengwynn", nil, status)
470
+ lambda { Octokit.user("pengwynn") }.should raise_error(exception)
471
+ end
472
+ end
473
+
474
+ context "#{status.first}, a post" do
475
+ should "raise an #{exception.name} error" do
476
+ @client = Octokit::Client.new(:login => 'pengwynn', :token => 'OU812')
477
+ stub_post("user/show/pengwynn", nil, status)
478
+ lambda { @client.update_user(:location => "Dallas, TX") }.should raise_error(exception)
479
+ end
480
+ end
481
+ end
482
+ end
483
+
484
+ context "when consuming feeds" do
485
+
486
+ should "should set user, title, and published time for the event" do
487
+ entry = Hashie::Mash.new({
488
+ :id => 'tag:github.com,2008:CreateEvent/110645788',
489
+ :published => '2009-12-12T11:24:14-08:00',
490
+ :updated => '2009-12-12T11:24:14-08:00',
491
+ :links => ['http://github.com/jnunemaker/twitter/tree/v0.7.10'],
492
+ :title => 'pengwynn created tag v0.7.10 at jnunemaker/twitter',
493
+ :author => 'pengwynn'
494
+ })
495
+
496
+ event = Octokit::Event.load_from_atom(entry)
497
+ event.user.should == 'pengwynn'
498
+ event.published.year.should == 2009
499
+ event.published.month.should == 12
500
+ event.id.should == 110645788
501
+ event.title.should == 'pengwynn created tag v0.7.10 at jnunemaker/twitter'
502
+ event.links.first.should == 'http://github.com/jnunemaker/twitter/tree/v0.7.10'
503
+ end
504
+
505
+ should "should create a repo event from an atom entry" do
506
+ entry = Hashie::Mash.new({
507
+ :id => 'tag:github.com,2008:CreateEvent/110645788',
508
+ :published => '2009-12-12T11:24:14-08:00',
509
+ :updated => '2009-12-12T11:24:14-08:00',
510
+ :links => ['http://github.com/Tanner/Team-1261---Java'],
511
+ :title => 'Tanner created repository Team-1261---Java',
512
+ :author => 'Tanner'
513
+ })
514
+
515
+ event = Octokit::Event.load_from_atom(entry)
516
+ event.event_type.should == 'repo'
517
+ event.repo.username.should == 'Tanner'
518
+ event.repo.name.should == 'Team-1261---Java'
519
+ end
520
+
521
+ should "should create a tag event from an atom entry" do
522
+ entry = Hashie::Mash.new({
523
+ :id => 'tag:github.com,2008:CreateEvent/110645788',
524
+ :published => '2009-12-12T11:24:14-08:00',
525
+ :updated => '2009-12-12T11:24:14-08:00',
526
+ :links => ['http://github.com/jnunemaker/twitter/tree/v0.7.10'],
527
+ :title => 'pengwynn created tag v0.7.10 at jnunemaker/twitter',
528
+ :author => 'pengwynn'
529
+ })
530
+
531
+ event = Octokit::Event.load_from_atom(entry)
532
+ event.event_type.should == 'tag'
533
+ event.repo.username.should == 'jnunemaker'
534
+ event.repo.name.should == 'twitter'
535
+ event.tag.should == 'v0.7.10'
536
+ end
537
+
538
+ should "should create a branch event from an atom entry" do
539
+ entry = Hashie::Mash.new({
540
+ :id => 'tag:github.com,2008:CreateEvent/110645788',
541
+ :published => '2009-12-12T11:24:14-08:00',
542
+ :updated => '2009-12-12T11:24:14-08:00',
543
+ :links => ['http://github.com/Fabi/cwcore/tree/cwcore-0.1'],
544
+ :title => 'cwcore created branch cwcore-0.1 at Fabi/cwcore',
545
+ :author => 'cwcore'
546
+ })
547
+
548
+ event = Octokit::Event.load_from_atom(entry)
549
+ event.event_type.should == 'branch'
550
+ event.repo.username.should == 'Fabi'
551
+ event.repo.name.should == 'cwcore'
552
+ event.user.should == 'cwcore'
553
+ event.branch.should == 'cwcore-0.1'
554
+ end
555
+
556
+ should "should create a push event from an atom entry" do
557
+ entry = Hashie::Mash.new({
558
+ :id => 'tag:github.com,2008:PushEvent/110645788',
559
+ :published => '2009-12-12T11:24:14-08:00',
560
+ :updated => '2009-12-12T11:24:14-08:00',
561
+ :links => ['http://github.com/jnunemaker/twitter/commits/master'],
562
+ :title => 'pengwynn pushed to master at jnunemaker/twitter',
563
+ :author => 'pengwynn'
564
+ })
565
+
566
+ event = Octokit::Event.load_from_atom(entry)
567
+ event.event_type.should == 'push'
568
+ event.repo.name.should == 'twitter'
569
+ event.branch.should == 'master'
570
+ end
571
+
572
+ should "should create a fork event from an atom entry" do
573
+ entry = Hashie::Mash.new({
574
+ :id => 'tag:github.com,2008:ForkEvent/110645788',
575
+ :published => '2009-12-12T11:24:14-08:00',
576
+ :updated => '2009-12-12T11:24:14-08:00',
577
+ :links => ['http://github.com/klauge/aeon/'],
578
+ :title => 'klauge forked djh/aeon',
579
+ :author => 'klauge'
580
+ })
581
+
582
+ event = Octokit::Event.load_from_atom(entry)
583
+ event.event_type.should == 'fork'
584
+ event.repo.username.should == 'klauge'
585
+ event.repo.name.should == 'aeon'
586
+ event.forked_from.username.should == 'djh'
587
+ end
588
+
589
+ should "should create a watch event from an atom entry" do
590
+ entry = Hashie::Mash.new({
591
+ :id => 'tag:github.com,2008:WatchEvent/110645788',
592
+ :published => '2009-12-12T11:24:14-08:00',
593
+ :updated => '2009-12-12T11:24:14-08:00',
594
+ :links => ['http://github.com/bogolisk/egg'],
595
+ :title => 'jpablobr started watching bogolisk/egg',
596
+ :author => 'jpablobr'
597
+ })
598
+
599
+ event = Octokit::Event.load_from_atom(entry)
600
+ event.event_type.should == 'watch'
601
+ event.repo.username.should == 'bogolisk'
602
+ event.repo.name.should == 'egg'
603
+ end
604
+
605
+ should "should create a follow event from an atom entry" do
606
+ entry = Hashie::Mash.new({
607
+ :id => 'tag:github.com,2008:FollowEvent/110645788',
608
+ :published => '2009-12-12T11:24:14-08:00',
609
+ :updated => '2009-12-12T11:24:14-08:00',
610
+ :links => ['http://github.com/swistak'],
611
+ :title => 'pengwynn started following swistak',
612
+ :author => 'pengwynn'
613
+ })
614
+
615
+ event = Octokit::Event.load_from_atom(entry)
616
+ event.event_type.should == 'follow'
617
+ event.repo.should == nil
618
+ event.target_user.should == 'swistak'
619
+ end
620
+
621
+ should "should create an issues event from an atom entry" do
622
+ entry = Hashie::Mash.new({
623
+ :id => 'tag:github.com,2008:IssuesEvent/110645788',
624
+ :published => '2009-12-12T11:24:14-08:00',
625
+ :updated => '2009-12-12T11:24:14-08:00',
626
+ :links => ['http://github.com/jnunemaker/twitter/issues/19/find'],
627
+ :title => 'pengwynn closed issue 19 on jnunemaker/twitter',
628
+ :author => 'pengwynn'
629
+ })
630
+
631
+ event = Octokit::Event.load_from_atom(entry)
632
+ event.event_type.should == 'issue'
633
+ event.repo.name.should == 'twitter'
634
+ event.action.should == 'closed'
635
+ event.issue_number.should == 19
636
+ end
637
+
638
+ should "should create a gist event from an atom entry" do
639
+ entry = Hashie::Mash.new({
640
+ :id => 'tag:github.com,2008:GistEvent/110645788',
641
+ :published => '2009-12-12T11:24:14-08:00',
642
+ :updated => '2009-12-12T11:24:14-08:00',
643
+ :links => ['http://gist.github.com/253987'],
644
+ :title => 'pengwynn created gist: 253987',
645
+ :author => 'pengwynn'
646
+ })
647
+
648
+ event = Octokit::Event.load_from_atom(entry)
649
+ event.event_type.should == 'gist'
650
+ event.repo.should == nil
651
+ event.gist_number.should == 253987
652
+ end
653
+
654
+ should "should create a member event from an atom entry" do
655
+ entry = Hashie::Mash.new({
656
+ :id => 'tag:github.com,2008:MemberEvent/110645788',
657
+ :published => '2009-12-12T11:24:14-08:00',
658
+ :updated => '2009-12-12T11:24:14-08:00',
659
+ :links => ['http://github.com/pengwynn/octokit'],
660
+ :title => 'pengwynn added adamstac to octokit',
661
+ :author => 'pengwynn'
662
+ })
663
+
664
+ event = Octokit::Event.load_from_atom(entry)
665
+ event.event_type.should == 'member'
666
+ event.repo.name.should == 'octokit'
667
+ event.target_user.should == 'adamstac'
668
+ end
669
+
670
+ should "should create a fork_apply event from an atom entry" do
671
+ entry = Hashie::Mash.new({
672
+ :id => 'tag:github.com,2008:ForkApplyEvent/110645788',
673
+ :published => '2009-12-12T11:24:14-08:00',
674
+ :updated => '2009-12-12T11:24:14-08:00',
675
+ :links => ['http://github.com/pengwynn/linkedin/tree/integration'],
676
+ :title => 'pengwynn applied fork commits to linkedin/integration',
677
+ :author => 'pengwynn'
678
+ })
679
+
680
+ event = Octokit::Event.load_from_atom(entry)
681
+ event.event_type.should == 'fork_apply'
682
+ event.repo.name.should == 'linkedin'
683
+ event.branch.should == 'integration'
684
+ end
685
+
686
+ should "should create a wiki event from an atom entry" do
687
+ entry = Hashie::Mash.new({
688
+ :id => 'tag:github.com,2008:WikiEvent/110645788',
689
+ :published => '2009-12-12T11:24:14-08:00',
690
+ :updated => '2009-12-12T11:24:14-08:00',
691
+ :links => ['http://github.com/dxw/Fammel/wikis/documentation'],
692
+ :title => 'dxw edited a page in the dxw/Fammel wiki',
693
+ :author => 'dxw'
694
+ })
695
+
696
+ event = Octokit::Event.load_from_atom(entry)
697
+ event.event_type.should == 'wiki'
698
+ event.repo.name.should == 'Fammel'
699
+ event.page.should == 'documentation'
700
+ end
701
+
702
+ should "should create a comment event from an atom entry" do
703
+ entry = Hashie::Mash.new({
704
+ :id => 'tag:github.com,2008:CommitCommentEvent/110645788',
705
+ :published => '2009-12-12T11:24:14-08:00',
706
+ :updated => '2009-12-12T11:24:14-08:00',
707
+ :links => ['http://github.com/fakechris/resque/commit/46f7ff1f73ae16ca8060fa3b051900562b51d5c2#-P0'],
708
+ :title => 'defunkt commented on fakechris/resque',
709
+ :author => 'defunkt'
710
+ })
711
+
712
+ event = Octokit::Event.load_from_atom(entry)
713
+ event.event_type.should == 'comment'
714
+ event.repo.name.should == 'resque'
715
+ end
716
+
717
+ should "should create a delete event from an atom entry" do
718
+ entry = Hashie::Mash.new({
719
+ :id => 'tag:github.com,2008:DeleteEvent/110645788',
720
+ :published => '2009-12-12T11:24:14-08:00',
721
+ :updated => '2009-12-12T11:24:14-08:00',
722
+ :links => ['http://github.com/jinzhu'],
723
+ :title => 'jinzhu deleted branch search at jinzhu/vimlike-smooziee',
724
+ :author => 'jinzhu'
725
+ })
726
+
727
+ event = Octokit::Event.load_from_atom(entry)
728
+ event.event_type.should == 'delete'
729
+ event.repo.name.should == 'vimlike-smooziee'
730
+ event.branch.should == 'search'
731
+ end
732
+
733
+ should "should create a public event from an atom entry" do
734
+ entry = Hashie::Mash.new({
735
+ :id => 'tag:github.com,2008:PublicEvent/110645788',
736
+ :published => '2009-12-12T11:24:14-08:00',
737
+ :updated => '2009-12-12T11:24:14-08:00',
738
+ :links => ['http://github.com/intalio'],
739
+ :title => 'intalio open sourced bpmn2',
740
+ :author => 'intalio'
741
+ })
742
+
743
+ event = Octokit::Event.load_from_atom(entry)
744
+ event.event_type.should == 'public'
745
+ event.repo.name.should == 'bpmn2'
746
+ end
747
+
748
+ should "should create a download event from an atom entry" do
749
+ entry = Hashie::Mash.new({
750
+ :id => 'tag:github.com,2008:DownloadEvent/110645788',
751
+ :published => '2009-12-12T11:24:14-08:00',
752
+ :updated => '2009-12-12T11:24:14-08:00',
753
+ :links => ['http://github.com/tobie'],
754
+ :title => 'tobie uploaded a file to sstephenson/prototype',
755
+ :author => 'tobie'
756
+ })
757
+
758
+ event = Octokit::Event.load_from_atom(entry)
759
+ event.event_type.should == 'download'
760
+ event.repo.name.should == 'prototype'
761
+ end
762
+
763
+ end
764
+
765
+ end