ci: do not error when nothing with nitunit_some
[nit.git] / lib / github / tests / test_api.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 module test_api is test
16
17 intrude import api
18
19 # GithubAPI testing
20 #
21 # To avoid test flakyness we test the GithubAPI against a mock of the real one.
22 # For each api request we return a cache file of the real API response body.
23 #
24 # Cache files can be automatically created and updated by setting
25 # `update_responses_cache` to `true` then running `nitunit`.
26 class MockGithubCurl
27 super GithubCurl
28
29 # Mock so it returns the response from a file
30 #
31 # See `update_responses_cache`.
32 redef fun get_and_parse(uri) do
33 print uri # for debugging
34
35 var path = uri.replace("https://api.github.com/", "/")
36 assert has_response(path)
37
38 if update_responses_cache then
39 var file = response_file(path)
40 save_actual_response(uri, file)
41 end
42
43 var response = response_string(path).parse_json
44 if response_is_error(path) then
45 var title = "GithubAPIError"
46 var msg = response.as(JsonObject)["message"].as(String)
47 var err = new GithubError(msg, title)
48 err.json["requested_uri"] = uri
49 err.json["status_code"] = response_code(path)
50 return err
51 end
52 return response
53 end
54
55 var test_responses: Map[String, String] do
56 var map = new HashMap[String, String]
57 map["/user"] = "user_Morriar"
58 map["/users/Morriar"] = "user_Morriar"
59 map["/repos/nitlang/nit"] = "repo_nit"
60 map["/repos/nitlang/nit/labels/ok_will_merge"] = "repo_labels_ok_will_merge"
61 map["/repos/nitlang/nit/milestones/4"] = "repo_milestones_4"
62 map["/repos/nitlang/nit/branches"] = "repo_branches_nit"
63 map["/repos/nitlang/nit/branches/master"] = "repo_branches_master"
64 map["/repos/nitlang/nit/issues/1000"] = "repo_issues_1000"
65 map["/repos/nitlang/nit/issues/comments/6020149"] = "repo_issues_comments_6020149"
66 map["/repos/nitlang/nit/issues/events/199674194"] = "repo_issues_events_199674194"
67 map["/repos/nitlang/nit/pulls/1000"] = "repo_pulls_1000"
68 map["/repos/nitlang/nit/commits/64ce1f"] = "repo_commits_64ce1f"
69 map["/repos/nitlang/nit/comments/8982707"] = "repo_comments_8982707"
70 map["/repos/nitlang/nit/pulls/comments/21010363"] = "repo_pulls_comment_21010363"
71 # errors
72 map["/users/not_found/not_found"] = "errors_404"
73 return map
74 end
75
76 # Does `self` have a mock response for Github `path`?
77 fun has_response(path: String): Bool do
78 return test_responses.has_key(path)
79 end
80
81 # Root responses cache directory
82 var responses_dir: String is lazy do
83 var path = "NIT_TESTING_PATH".environ.dirname / "mock"
84 path.mkdir
85 return path
86 end
87
88 # Returns the response file path for a Github `path`
89 fun response_file(path: String): String do
90 assert has_response(path)
91 return "{responses_dir / test_responses[path]}.res"
92 end
93
94 # Returns the response body string for a Github `path`
95 fun response_string(path: String): String do
96 var file = response_file(path)
97 assert file.file_exists
98 return file.to_path.read_all
99 end
100
101 # Is this response a simulated error?
102 fun response_is_error(path: String): Bool do
103 assert has_response(path)
104 return test_responses[path].has_prefix("errors_")
105 end
106
107 # Status code of a simulated error
108 #
109 # See `response_is_error`.
110 fun response_code(path: String): String do
111 assert response_is_error(path)
112 return test_responses[path].split("_").last
113 end
114
115 # Response caching
116
117 # Activate caching
118 #
119 # Change this value to `true` then run nitunit to cache the responses
120 # from the Github API.
121 #
122 # Default is `false`.
123 var update_responses_cache = false
124
125 # Save the actual Github API response body for `uri` to a `file`
126 private fun save_actual_response(uri, file: String) do
127 assert update_responses_cache
128
129 var request = new CurlHTTPRequest(uri)
130 request.user_agent = actual_curl.user_agent
131 request.headers = actual_curl.header
132 var response = request.execute
133
134 if response isa CurlResponseSuccess then
135 response.body_str.write_to_file(file)
136 else if response isa CurlResponseFailed then
137 response.error_msg.write_to_file(file)
138 else abort
139
140 print "Response to `{uri}` saved at `{file}`"
141 end
142
143 # Actual GithubCurl instance used for caching
144 private var actual_curl = new GithubCurl(get_github_oauth, "nitunit")
145 end
146
147 class TestGithubAPI
148 test
149
150 var mock = new MockGithubCurl("test", "test")
151
152 fun api: GithubAPI do
153 var api = new GithubAPI("test")
154 api.ghcurl = mock
155 return api
156 end
157
158 fun test_deserialize is test do
159 var response = mock.response_string("/users/Morriar")
160 var obj = api.deserialize(response)
161 assert obj isa User
162 assert obj.login == "Morriar"
163 end
164
165 fun test_sanitize_url is test do
166 # TODO better tests
167 assert api.sanitize_uri("/repos/Nit with spaces/") == "/repos/Nit%20with%20spaces/"
168 end
169
170 fun test_get is test do
171 var api = self.api
172 var obj = api.get("/users/Morriar")
173 assert not api.was_error
174 assert api.last_error == null
175 assert obj isa JsonObject
176 assert obj["login"] == "Morriar"
177 end
178
179 fun test_get_404 is test do
180 var api = self.api
181 var res = api.get("/users/not_found/not_found")
182 assert res == null
183 assert api.was_error
184 var err = api.last_error
185 assert err isa GithubError
186 assert err.name == "GithubAPIError"
187 assert err.message == "Not Found"
188 end
189
190 fun test_load_from_github is test do
191 var api = self.api
192 var obj = api.load_from_github("/users/Morriar")
193 assert not api.was_error
194 assert api.last_error == null
195 assert obj isa User
196 assert obj.login == "Morriar"
197 end
198
199 fun test_load_from_github_404 is test do
200 var api = self.api
201 var res = api.load_from_github("/users/not_found/not_found")
202 assert res == null
203 assert api.was_error
204 var err = api.last_error
205 assert err isa GithubError
206 assert err.name == "GithubAPIError"
207 assert err.message == "Not Found"
208 end
209
210 # TODO test more error cases
211
212 fun test_get_auth_user is test do
213 var user = api.load_auth_user
214 assert user isa User
215 assert user.login == "Morriar"
216 assert user.avatar_url == "https://avatars2.githubusercontent.com/u/583144?v=4"
217 assert user.name == "Alexandre Terrasa"
218 assert user.email == "alexandre@moz-code.org"
219 assert user.blog == "moz-code.org"
220 end
221
222 fun test_get_user is test do
223 var user = api.load_user("Morriar")
224 assert user isa User
225 assert user.login == "Morriar"
226 assert user.avatar_url == "https://avatars2.githubusercontent.com/u/583144?v=4"
227 assert user.name == "Alexandre Terrasa"
228 assert user.email == "alexandre@moz-code.org"
229 assert user.blog == "moz-code.org"
230 end
231
232 fun test_get_repo is test do
233 var repo = api.load_repo("nitlang/nit")
234 assert repo isa Repo
235 assert repo.full_name == "nitlang/nit"
236 assert repo.name == "nit"
237 assert repo.owner.login == "nitlang"
238 assert repo.default_branch == "master"
239 end
240
241 private var repo: Repo is lazy do return api.load_repo("nitlang/nit").as(not null)
242
243 fun test_get_branches is test do
244 var branches = api.load_repo_branches(repo)
245 assert branches.length == 2
246 assert branches.first.name == "master"
247 assert branches.last.name == "next"
248 end
249
250 # TODO issues
251 # TODO repo_last_issue
252 # TODO labels
253 # TODO milestones
254 # TODO pulls
255 # TODO contrib_stats
256
257 fun test_get_branch is test do
258 var branch = api.load_branch(repo, "master")
259 assert branch isa Branch
260 assert branch.name == "master"
261 end
262
263 # TODO branch commits
264
265 fun test_get_commit is test do
266 var commit = api.load_commit(repo, "64ce1f")
267 assert commit isa Commit
268 assert commit.sha == "64ce1f587209024f5de46d06c70526a569ff537f"
269 # TODO other fields
270 end
271
272 fun test_get_issue is test do
273 var issue = api.load_issue(repo, 1000)
274 assert issue isa Issue
275 assert issue.number == 1000
276 assert issue.title == "Raise nitc from the dead"
277 assert issue.user.as(User).login == "privat"
278 assert issue.comments == 7
279 assert issue.created_at == "2014-12-11T02:55:09Z"
280 assert issue.closed_at == "2014-12-13T15:38:09Z"
281 assert issue.closed_by.as(User).login == "privat"
282 assert issue.body == "Raise dead on `nitc`.\nIt's super effective...\n"
283 assert issue.is_pull_request
284 end
285
286 # TODO issue comments
287 # TODO issue events
288
289 fun test_get_pull is test do
290 var pull = api.load_pull(repo, 1000)
291 assert pull isa Issue
292 assert pull.number == 1000
293 assert pull.title == "Raise nitc from the dead"
294 assert pull.user.as(User).login == "privat"
295 assert pull.comments == 7
296 assert pull.created_at == "2014-12-11T02:55:09Z"
297 assert pull.closed_at == "2014-12-13T15:38:09Z"
298 assert pull.merged_by.as(User).login == "privat"
299 assert pull.body == "Raise dead on `nitc`.\nIt's super effective...\n"
300 end
301
302 fun test_get_label is test do
303 var labl = api.load_label(repo, "ok_will_merge")
304 assert labl isa Label
305 assert labl.name == "ok_will_merge"
306 end
307
308 fun test_get_milestone is test do
309 var milestone = api.load_milestone(repo, 4)
310 assert milestone isa Milestone
311 assert milestone.title == "v1.0prealpha"
312 # TODO other fields
313 end
314
315 fun test_get_issue_event is test do
316 var event = api.load_issue_event(repo, 199674194)
317 assert event isa IssueEvent
318 assert event.actor.login == "privat"
319 assert event.event == "labeled"
320 assert event.labl.as(Label).name == "need_review"
321 end
322
323 fun test_get_issue_comment is test do
324 var comment = api.load_issue_comment(repo, 6020149)
325 assert comment isa IssueComment
326 assert comment.user.login == "privat"
327 assert comment.created_at.to_s == "2012-05-30T20:16:54Z"
328 assert comment.issue_number == 10
329 end
330
331 fun test_get_comment is test do
332 var comment = api.load_commit_comment(repo, 8982707)
333 assert comment isa CommitComment
334 assert comment.user.login == "Morriar"
335 assert comment.body == "For testing purposes...\n"
336 assert comment.commit_id == "7eacb86d1e24b7e72bc9ac869bf7182c0300ceca"
337 end
338
339 fun test_get_review_comments is test do
340 var comment = api.load_review_comment(repo, 21010363)
341 assert comment isa ReviewComment
342 assert comment.path == "src/modelize/modelize_property.nit"
343 assert comment.original_position == 26
344 assert comment.pull_number == 945
345 end
346 end