Merge: Mock Github API tests
authorJean Privat <jean@pryen.org>
Wed, 3 Jul 2019 18:50:53 +0000 (14:50 -0400)
committerJean Privat <jean@pryen.org>
Wed, 3 Jul 2019 18:50:53 +0000 (14:50 -0400)
This PR adds a mock to GithubAPI so we can avoid sending requests to the API on CI.

For each API call we save the actual Github response body from the API and reuse it during the tests.
The attribute `update_responses_cache` can be set to `true` so the cache files are updated from the API when `nitunit` is called.

Pull-Request: #2753
Reviewed-by: Jean Privat <jean@pryen.org>

16 files changed:
lib/github/api.nit
lib/github/tests/mock/errors_404.res [new file with mode: 0644]
lib/github/tests/mock/repo_branches_master.res [new file with mode: 0644]
lib/github/tests/mock/repo_branches_nit.res [new file with mode: 0644]
lib/github/tests/mock/repo_comments_8982707.res [new file with mode: 0644]
lib/github/tests/mock/repo_commits_64ce1f.res [new file with mode: 0644]
lib/github/tests/mock/repo_issues_1000.res [new file with mode: 0644]
lib/github/tests/mock/repo_issues_comments_6020149.res [new file with mode: 0644]
lib/github/tests/mock/repo_issues_events_199674194.res [new file with mode: 0644]
lib/github/tests/mock/repo_labels_ok_will_merge.res [new file with mode: 0644]
lib/github/tests/mock/repo_milestones_4.res [new file with mode: 0644]
lib/github/tests/mock/repo_nit.res [new file with mode: 0644]
lib/github/tests/mock/repo_pulls_1000.res [new file with mode: 0644]
lib/github/tests/mock/repo_pulls_comment_21010363.res [new file with mode: 0644]
lib/github/tests/mock/user_Morriar.res [new file with mode: 0644]
lib/github/tests/test_api.nit [new file with mode: 0644]

index 4eb9a97..fb6fff9 100644 (file)
@@ -102,20 +102,24 @@ class GithubAPI
        # This method returns raw json data.
        # See other `load_*` methods to use more expressive types.
        #
-       #     var api = new GithubAPI(get_github_oauth)
-       #     var obj = api.get("/repos/nitlang/nit")
-       #     assert obj isa JsonObject
-       #     assert obj["name"] == "nit"
+       # ~~~nitish
+       # var api = new GithubAPI(get_github_oauth)
+       # var obj = api.get("/repos/nitlang/nit")
+       # assert obj isa JsonObject
+       # assert obj["name"] == "nit"
+       # ~~~
        #
        # Returns `null` in case of `error`.
        #
-       #     obj = api.get("/foo/bar/baz")
-       #     assert obj == null
-       #     assert api.was_error
-       #     var err = api.last_error
-       #     assert err isa GithubError
-       #     assert err.name == "GithubAPIError"
-       #     assert err.message == "Not Found"
+       # ~~~nitish
+       # obj = api.get("/foo/bar/baz")
+       # assert obj == null
+       # assert api.was_error
+       # var err = api.last_error
+       # assert err isa GithubError
+       # assert err.name == "GithubAPIError"
+       # assert err.message == "Not Found"
+       # ~~~
        fun get(path: String): nullable Serializable do
                path = sanitize_uri(path)
                var res = ghcurl.get_and_parse("{api_url}{path}")
@@ -173,10 +177,12 @@ class GithubAPI
        #
        # Loads the `User` from the API or returns `null` if the user cannot be found.
        #
-       #     var api = new GithubAPI(get_github_oauth)
-       #     var user = api.load_user("Morriar")
-       #     print user or else "null"
-       #     assert user.login == "Morriar"
+       # ~~~nitish
+       # var api = new GithubAPI(get_github_oauth)
+       # var user = api.load_user("Morriar")
+       # print user or else "null"
+       # assert user.login == "Morriar"
+       # ~~~
        fun load_user(login: String): nullable User do
                return load_from_github("/users/{login}").as(nullable User)
        end
@@ -185,11 +191,13 @@ class GithubAPI
        #
        # Loads the `Repo` from the API or returns `null` if the repo cannot be found.
        #
-       #     var api = new GithubAPI(get_github_oauth)
-       #     var repo = api.load_repo("nitlang/nit")
-       #     assert repo.name == "nit"
-       #     assert repo.owner.login == "nitlang"
-       #     assert repo.default_branch == "master"
+       # ~~~nitish
+       # var api = new GithubAPI(get_github_oauth)
+       # var repo = api.load_repo("nitlang/nit")
+       # assert repo.name == "nit"
+       # assert repo.owner.login == "nitlang"
+       # assert repo.default_branch == "master"
+       # ~~~
        fun load_repo(full_name: String): nullable Repo do
                return load_from_github("/repos/{full_name}").as(nullable Repo)
        end
@@ -201,8 +209,12 @@ class GithubAPI
                var res = new Array[Branch]
                if not array isa JsonArray then return res
                var deser = deserialize(array.to_json)
-               if deser isa Array[Object] then return res # empty array
-               return deser.as(Array[Branch])
+               if not deser isa Array[Object] then return res # empty array
+               for branch in deser do
+                       if not branch isa Branch then continue
+                       res.add branch
+               end
+               return res
        end
 
        # List of issues associated with their ids.
@@ -301,12 +313,14 @@ class GithubAPI
        #
        # Returns `null` if the branch cannot be found.
        #
-       #     var api = new GithubAPI(get_github_oauth)
-       #     var repo = api.load_repo("nitlang/nit")
-       #     assert repo != null
-       #     var branch = api.load_branch(repo, "master")
-       #     assert branch.name == "master"
-       #     assert branch.commit isa Commit
+       # ~~~nitish
+       # var api = new GithubAPI(get_github_oauth)
+       # var repo = api.load_repo("nitlang/nit")
+       # assert repo != null
+       # var branch = api.load_branch(repo, "master")
+       # assert branch.name == "master"
+       # assert branch.commit isa Commit
+       # ~~~
        fun load_branch(repo: Repo, name: String): nullable Branch do
                return load_from_github("/repos/{repo.full_name}/branches/{name}").as(nullable Branch)
        end
@@ -339,11 +353,13 @@ class GithubAPI
        #
        # Returns `null` if the commit cannot be found.
        #
-       #     var api = new GithubAPI(get_github_oauth)
-       #     var repo = api.load_repo("nitlang/nit")
-       #     assert repo != null
-       #     var commit = api.load_commit(repo, "64ce1f")
-       #     assert commit isa Commit
+       # ~~~nitish
+       # var api = new GithubAPI(get_github_oauth)
+       # var repo = api.load_repo("nitlang/nit")
+       # assert repo != null
+       # var commit = api.load_commit(repo, "64ce1f")
+       # assert commit isa Commit
+       # ~~~
        fun load_commit(repo: Repo, sha: String): nullable Commit do
                return load_from_github("/repos/{repo.full_name}/commits/{sha}").as(nullable Commit)
        end
@@ -352,11 +368,13 @@ class GithubAPI
        #
        # Returns `null` if the issue cannot be found.
        #
-       #     var api = new GithubAPI(get_github_oauth)
-       #     var repo = api.load_repo("nitlang/nit")
-       #     assert repo != null
-       #     var issue = api.load_issue(repo, 1)
-       #     assert issue.title == "Doc"
+       # ~~~nitish
+       # var api = new GithubAPI(get_github_oauth)
+       # var repo = api.load_repo("nitlang/nit")
+       # assert repo != null
+       # var issue = api.load_issue(repo, 1)
+       # assert issue.title == "Doc"
+       # ~~~
        fun load_issue(repo: Repo, number: Int): nullable Issue do
                return load_from_github("/repos/{repo.full_name}/issues/{number}").as(nullable Issue)
        end
@@ -406,12 +424,14 @@ class GithubAPI
        #
        # Returns `null` if the pull request cannot be found.
        #
-       #     var api = new GithubAPI(get_github_oauth)
-       #     var repo = api.load_repo("nitlang/nit")
-       #     assert repo != null
-       #     var pull = api.load_pull(repo, 1)
-       #     assert pull.title == "Doc"
-       #     assert pull.user.login == "Morriar"
+       # ~~~nitish
+       # var api = new GithubAPI(get_github_oauth)
+       # var repo = api.load_repo("nitlang/nit")
+       # assert repo != null
+       # var pull = api.load_pull(repo, 1)
+       # assert pull.title == "Doc"
+       # assert pull.user.login == "Morriar"
+       # ~~~
        fun load_pull(repo: Repo, number: Int): nullable PullRequest do
                return load_from_github("/repos/{repo.full_name}/pulls/{number}").as(nullable PullRequest)
        end
@@ -420,11 +440,13 @@ class GithubAPI
        #
        # Returns `null` if the label cannot be found.
        #
-       #     var api = new GithubAPI(get_github_oauth)
-       #     var repo = api.load_repo("nitlang/nit")
-       #     assert repo != null
-       #     var labl = api.load_label(repo, "ok_will_merge")
-       #     assert labl != null
+       # ~~~nitish
+       # var api = new GithubAPI(get_github_oauth)
+       # var repo = api.load_repo("nitlang/nit")
+       # assert repo != null
+       # var labl = api.load_label(repo, "ok_will_merge")
+       # assert labl != null
+       # ~~~
        fun load_label(repo: Repo, name: String): nullable Label do
                return load_from_github("/repos/{repo.full_name}/labels/{name}").as(nullable Label)
        end
@@ -433,11 +455,13 @@ class GithubAPI
        #
        # Returns `null` if the milestone cannot be found.
        #
-       #     var api = new GithubAPI(get_github_oauth)
-       #     var repo = api.load_repo("nitlang/nit")
-       #     assert repo != null
-       #     var stone = api.load_milestone(repo, 4)
-       #     assert stone.title == "v1.0prealpha"
+       # ~~~nitish
+       # var api = new GithubAPI(get_github_oauth)
+       # var repo = api.load_repo("nitlang/nit")
+       # assert repo != null
+       # var stone = api.load_milestone(repo, 4)
+       # assert stone.title == "v1.0prealpha"
+       # ~~~
        fun load_milestone(repo: Repo, id: Int): nullable Milestone do
                return load_from_github("/repos/{repo.full_name}/milestones/{id}").as(nullable Milestone)
        end
@@ -446,15 +470,17 @@ class GithubAPI
        #
        # Returns `null` if the event cannot be found.
        #
-       #     var api = new GithubAPI(get_github_oauth)
-       #     var repo = api.load_repo("nitlang/nit")
-       #     assert repo isa Repo
-       #     var event = api.load_issue_event(repo, 199674194)
-       #     assert event isa IssueEvent
-       #     assert event.actor.login == "privat"
-       #     assert event.event == "labeled"
-       #     assert event.labl isa Label
-       #     assert event.labl.name == "need_review"
+       # ~~~nitish
+       # var api = new GithubAPI(get_github_oauth)
+       # var repo = api.load_repo("nitlang/nit")
+       # assert repo isa Repo
+       # var event = api.load_issue_event(repo, 199674194)
+       # assert event isa IssueEvent
+       # assert event.actor.login == "privat"
+       # assert event.event == "labeled"
+       # assert event.labl isa Label
+       # assert event.labl.name == "need_review"
+       # ~~~
        fun load_issue_event(repo: Repo, id: Int): nullable IssueEvent do
                return load_from_github("/repos/{repo.full_name}/issues/events/{id}").as(nullable IssueEvent)
        end
@@ -463,13 +489,15 @@ class GithubAPI
        #
        # Returns `null` if the comment cannot be found.
        #
-       #     var api = new GithubAPI(get_github_oauth)
-       #     var repo = api.load_repo("nitlang/nit")
-       #     assert repo != null
-       #     var comment = api.load_commit_comment(repo, 8982707)
-       #     assert comment.user.login == "Morriar"
-       #     assert comment.body == "For testing purposes...\n"
-       #     assert comment.commit_id == "7eacb86d1e24b7e72bc9ac869bf7182c0300ceca"
+       # ~~~nitish
+       # var api = new GithubAPI(get_github_oauth)
+       # var repo = api.load_repo("nitlang/nit")
+       # assert repo != null
+       # var comment = api.load_commit_comment(repo, 8982707)
+       # assert comment.user.login == "Morriar"
+       # assert comment.body == "For testing purposes...\n"
+       # assert comment.commit_id == "7eacb86d1e24b7e72bc9ac869bf7182c0300ceca"
+       # ~~~
        fun load_commit_comment(repo: Repo, id: Int): nullable CommitComment do
                return load_from_github("/repos/{repo.full_name}/comments/{id}").as(nullable CommitComment)
        end
@@ -478,13 +506,15 @@ class GithubAPI
        #
        # Returns `null` if the comment cannot be found.
        #
-       #     var api = new GithubAPI(get_github_oauth)
-       #     var repo = api.load_repo("nitlang/nit")
-       #     assert repo != null
-       #     var comment = api.load_issue_comment(repo, 6020149)
-       #     assert comment.user.login == "privat"
-       #     assert comment.created_at.to_s == "2012-05-30T20:16:54Z"
-       #     assert comment.issue_number == 10
+       # ~~~nitish
+       # var api = new GithubAPI(get_github_oauth)
+       # var repo = api.load_repo("nitlang/nit")
+       # assert repo != null
+       # var comment = api.load_issue_comment(repo, 6020149)
+       # assert comment.user.login == "privat"
+       # assert comment.created_at.to_s == "2012-05-30T20:16:54Z"
+       # assert comment.issue_number == 10
+       # ~~~
        fun load_issue_comment(repo: Repo, id: Int): nullable IssueComment do
                return load_from_github("/repos/{repo.full_name}/issues/comments/{id}").as(nullable IssueComment)
        end
@@ -493,13 +523,15 @@ class GithubAPI
        #
        # Returns `null` if the comment cannot be found.
        #
-       #     var api = new GithubAPI(get_github_oauth)
-       #     var repo = api.load_repo("nitlang/nit")
-       #     assert repo != null
-       #     var comment = api.load_review_comment(repo, 21010363)
-       #     assert comment.path == "src/modelize/modelize_property.nit"
-       #     assert comment.original_position == 26
-       #     assert comment.pull_number == 945
+       # ~~~nitish
+       # var api = new GithubAPI(get_github_oauth)
+       # var repo = api.load_repo("nitlang/nit")
+       # assert repo != null
+       # var comment = api.load_review_comment(repo, 21010363)
+       # assert comment.path == "src/modelize/modelize_property.nit"
+       # assert comment.original_position == 26
+       # assert comment.pull_number == 945
+       # ~~~
        fun load_review_comment(repo: Repo, id: Int): nullable ReviewComment do
                return load_from_github("/repos/{repo.full_name}/pulls/comments/{id}").as(nullable ReviewComment)
        end
diff --git a/lib/github/tests/mock/errors_404.res b/lib/github/tests/mock/errors_404.res
new file mode 100644 (file)
index 0000000..e0a95cb
--- /dev/null
@@ -0,0 +1 @@
+{"message":"Not Found","documentation_url":"https://developer.github.com/v3"}
\ No newline at end of file
diff --git a/lib/github/tests/mock/repo_branches_master.res b/lib/github/tests/mock/repo_branches_master.res
new file mode 100644 (file)
index 0000000..dcb088a
--- /dev/null
@@ -0,0 +1 @@
+{"name":"master","commit":{"sha":"9248f1c81c08b6c0ec7785678dbb1d7440b885d9","node_id":"MDY6Q29tbWl0MzI4NTk3OjkyNDhmMWM4MWMwOGI2YzBlYzc3ODU2NzhkYmIxZDc0NDBiODg1ZDk=","commit":{"author":{"name":"Jean Privat","email":"jean@pryen.org","date":"2019-06-13T14:14:24Z"},"committer":{"name":"Jean Privat","email":"jean@pryen.org","date":"2019-06-13T14:14:24Z"},"message":"Merge: Some more small improvements on gitlab-ci\n\nPull-Request: #2744","tree":{"sha":"1c40bdc143d18c628fb7939b8258fa65f6ada2e7","url":"https://api.github.com/repos/nitlang/nit/git/trees/1c40bdc143d18c628fb7939b8258fa65f6ada2e7"},"url":"https://api.github.com/repos/nitlang/nit/git/commits/9248f1c81c08b6c0ec7785678dbb1d7440b885d9","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null}},"url":"https://api.github.com/repos/nitlang/nit/commits/9248f1c81c08b6c0ec7785678dbb1d7440b885d9","html_url":"https://github.com/nitlang/nit/commit/9248f1c81c08b6c0ec7785678dbb1d7440b885d9","comments_url":"https://api.github.com/repos/nitlang/nit/commits/9248f1c81c08b6c0ec7785678dbb1d7440b885d9/comments","author":{"login":"privat","id":135828,"node_id":"MDQ6VXNlcjEzNTgyOA==","avatar_url":"https://avatars1.githubusercontent.com/u/135828?v=4","gravatar_id":"","url":"https://api.github.com/users/privat","html_url":"https://github.com/privat","followers_url":"https://api.github.com/users/privat/followers","following_url":"https://api.github.com/users/privat/following{/other_user}","gists_url":"https://api.github.com/users/privat/gists{/gist_id}","starred_url":"https://api.github.com/users/privat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/privat/subscriptions","organizations_url":"https://api.github.com/users/privat/orgs","repos_url":"https://api.github.com/users/privat/repos","events_url":"https://api.github.com/users/privat/events{/privacy}","received_events_url":"https://api.github.com/users/privat/received_events","type":"User","site_admin":false},"committer":{"login":"privat","id":135828,"node_id":"MDQ6VXNlcjEzNTgyOA==","avatar_url":"https://avatars1.githubusercontent.com/u/135828?v=4","gravatar_id":"","url":"https://api.github.com/users/privat","html_url":"https://github.com/privat","followers_url":"https://api.github.com/users/privat/followers","following_url":"https://api.github.com/users/privat/following{/other_user}","gists_url":"https://api.github.com/users/privat/gists{/gist_id}","starred_url":"https://api.github.com/users/privat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/privat/subscriptions","organizations_url":"https://api.github.com/users/privat/orgs","repos_url":"https://api.github.com/users/privat/repos","events_url":"https://api.github.com/users/privat/events{/privacy}","received_events_url":"https://api.github.com/users/privat/received_events","type":"User","site_admin":false},"parents":[{"sha":"afc737008b2b10b9317f0e528dedf27dcf9926ab","url":"https://api.github.com/repos/nitlang/nit/commits/afc737008b2b10b9317f0e528dedf27dcf9926ab","html_url":"https://github.com/nitlang/nit/commit/afc737008b2b10b9317f0e528dedf27dcf9926ab"},{"sha":"61e9c7897630bfe23a2bf6c2a02803c1fc8dd51d","url":"https://api.github.com/repos/nitlang/nit/commits/61e9c7897630bfe23a2bf6c2a02803c1fc8dd51d","html_url":"https://github.com/nitlang/nit/commit/61e9c7897630bfe23a2bf6c2a02803c1fc8dd51d"}]},"_links":{"self":"https://api.github.com/repos/nitlang/nit/branches/master","html":"https://github.com/nitlang/nit/tree/master"},"protected":true,"protection":{"enabled":true,"required_status_checks":{"enforcement_level":"non_admins","contexts":[]}},"protection_url":"https://api.github.com/repos/nitlang/nit/branches/master/protection"}
\ No newline at end of file
diff --git a/lib/github/tests/mock/repo_branches_nit.res b/lib/github/tests/mock/repo_branches_nit.res
new file mode 100644 (file)
index 0000000..ff67214
--- /dev/null
@@ -0,0 +1 @@
+[{"name":"master","commit":{"sha":"9248f1c81c08b6c0ec7785678dbb1d7440b885d9","url":"https://api.github.com/repos/nitlang/nit/commits/9248f1c81c08b6c0ec7785678dbb1d7440b885d9"},"protected":true},{"name":"next","commit":{"sha":"9248f1c81c08b6c0ec7785678dbb1d7440b885d9","url":"https://api.github.com/repos/nitlang/nit/commits/9248f1c81c08b6c0ec7785678dbb1d7440b885d9"},"protected":false}]
\ No newline at end of file
diff --git a/lib/github/tests/mock/repo_comments_8982707.res b/lib/github/tests/mock/repo_comments_8982707.res
new file mode 100644 (file)
index 0000000..e8ec2f0
--- /dev/null
@@ -0,0 +1 @@
+{"url":"https://api.github.com/repos/nitlang/nit/comments/8982707","html_url":"https://github.com/nitlang/nit/commit/7eacb86d1e24b7e72bc9ac869bf7182c0300ceca#commitcomment-8982707","id":8982707,"node_id":"MDEzOkNvbW1pdENvbW1lbnQ4OTgyNzA3","user":{"login":"Morriar","id":583144,"node_id":"MDQ6VXNlcjU4MzE0NA==","avatar_url":"https://avatars2.githubusercontent.com/u/583144?v=4","gravatar_id":"","url":"https://api.github.com/users/Morriar","html_url":"https://github.com/Morriar","followers_url":"https://api.github.com/users/Morriar/followers","following_url":"https://api.github.com/users/Morriar/following{/other_user}","gists_url":"https://api.github.com/users/Morriar/gists{/gist_id}","starred_url":"https://api.github.com/users/Morriar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Morriar/subscriptions","organizations_url":"https://api.github.com/users/Morriar/orgs","repos_url":"https://api.github.com/users/Morriar/repos","events_url":"https://api.github.com/users/Morriar/events{/privacy}","received_events_url":"https://api.github.com/users/Morriar/received_events","type":"User","site_admin":false},"position":null,"line":null,"path":null,"commit_id":"7eacb86d1e24b7e72bc9ac869bf7182c0300ceca","created_at":"2014-12-16T00:37:24Z","updated_at":"2014-12-16T00:37:24Z","author_association":"MEMBER","body":"For testing purposes...\n"}
\ No newline at end of file
diff --git a/lib/github/tests/mock/repo_commits_64ce1f.res b/lib/github/tests/mock/repo_commits_64ce1f.res
new file mode 100644 (file)
index 0000000..e90dbfc
--- /dev/null
@@ -0,0 +1 @@
+{"sha":"64ce1f587209024f5de46d06c70526a569ff537f","node_id":"MDY6Q29tbWl0MzI4NTk3OjY0Y2UxZjU4NzIwOTAyNGY1ZGU0NmQwNmM3MDUyNmE1NjlmZjUzN2Y=","commit":{"author":{"name":"Jean Privat","email":"jean@pryen.org","date":"2014-12-03T15:16:13Z"},"committer":{"name":"Jean Privat","email":"jean@pryen.org","date":"2014-12-03T15:33:19Z"},"message":"lib/string: add `chomp`\n\nSigned-off-by: Jean Privat <jean@pryen.org>","tree":{"sha":"66ac4b2bd9247d98afbb5309db97dda06991ed77","url":"https://api.github.com/repos/nitlang/nit/git/trees/66ac4b2bd9247d98afbb5309db97dda06991ed77"},"url":"https://api.github.com/repos/nitlang/nit/git/commits/64ce1f587209024f5de46d06c70526a569ff537f","comment_count":0,"verification":{"verified":false,"reason":"unsigned","signature":null,"payload":null}},"url":"https://api.github.com/repos/nitlang/nit/commits/64ce1f587209024f5de46d06c70526a569ff537f","html_url":"https://github.com/nitlang/nit/commit/64ce1f587209024f5de46d06c70526a569ff537f","comments_url":"https://api.github.com/repos/nitlang/nit/commits/64ce1f587209024f5de46d06c70526a569ff537f/comments","author":{"login":"privat","id":135828,"node_id":"MDQ6VXNlcjEzNTgyOA==","avatar_url":"https://avatars1.githubusercontent.com/u/135828?v=4","gravatar_id":"","url":"https://api.github.com/users/privat","html_url":"https://github.com/privat","followers_url":"https://api.github.com/users/privat/followers","following_url":"https://api.github.com/users/privat/following{/other_user}","gists_url":"https://api.github.com/users/privat/gists{/gist_id}","starred_url":"https://api.github.com/users/privat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/privat/subscriptions","organizations_url":"https://api.github.com/users/privat/orgs","repos_url":"https://api.github.com/users/privat/repos","events_url":"https://api.github.com/users/privat/events{/privacy}","received_events_url":"https://api.github.com/users/privat/received_events","type":"User","site_admin":false},"committer":{"login":"privat","id":135828,"node_id":"MDQ6VXNlcjEzNTgyOA==","avatar_url":"https://avatars1.githubusercontent.com/u/135828?v=4","gravatar_id":"","url":"https://api.github.com/users/privat","html_url":"https://github.com/privat","followers_url":"https://api.github.com/users/privat/followers","following_url":"https://api.github.com/users/privat/following{/other_user}","gists_url":"https://api.github.com/users/privat/gists{/gist_id}","starred_url":"https://api.github.com/users/privat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/privat/subscriptions","organizations_url":"https://api.github.com/users/privat/orgs","repos_url":"https://api.github.com/users/privat/repos","events_url":"https://api.github.com/users/privat/events{/privacy}","received_events_url":"https://api.github.com/users/privat/received_events","type":"User","site_admin":false},"parents":[{"sha":"a882d5602264623f9275698b5abe73d95b127b9f","url":"https://api.github.com/repos/nitlang/nit/commits/a882d5602264623f9275698b5abe73d95b127b9f","html_url":"https://github.com/nitlang/nit/commit/a882d5602264623f9275698b5abe73d95b127b9f"}],"stats":{"total":13,"additions":13,"deletions":0},"files":[{"sha":"664ecbcb0652892b7659a98e5fb24c995211563c","filename":"lib/standard/string.nit","status":"modified","additions":13,"deletions":0,"changes":13,"blob_url":"https://github.com/nitlang/nit/blob/64ce1f587209024f5de46d06c70526a569ff537f/lib/standard/string.nit","raw_url":"https://github.com/nitlang/nit/raw/64ce1f587209024f5de46d06c70526a569ff537f/lib/standard/string.nit","contents_url":"https://api.github.com/repos/nitlang/nit/contents/lib/standard/string.nit?ref=64ce1f587209024f5de46d06c70526a569ff537f","patch":"@@ -385,6 +385,19 @@ abstract class Text\n \t#     assert \"\\na\\nb\\tc\\t\".trim          == \"a\\nb\\tc\"\n \tfun trim: SELFTYPE do return (self.l_trim).r_trim\n \n+\t# Returns `self` removed from its last `\\n` (if any).\n+\t#\n+\t#    assert \"Hello\\n\".chomp == \"Hello\"\n+\t#    assert \"Hello\".chomp   == \"Hello\"\n+\t#    assert \"\\n\\n\\n\".chomp  == \"\\n\\n\"\n+\t#\n+\t# This method is mainly used to remove the LINE_FEED character from lines of text.\n+\tfun chomp: SELFTYPE\n+\tdo\n+\t\tif self.chars.last != '\\n' then return self\n+\t\treturn substring(0, length-1)\n+\tend\n+\n \t# Justify a self in a space of `length`\n \t#\n \t# `left` is the space ratio on the left side."}]}
\ No newline at end of file
diff --git a/lib/github/tests/mock/repo_issues_1000.res b/lib/github/tests/mock/repo_issues_1000.res
new file mode 100644 (file)
index 0000000..24294cf
--- /dev/null
@@ -0,0 +1 @@
+{"url":"https://api.github.com/repos/nitlang/nit/issues/1000","repository_url":"https://api.github.com/repos/nitlang/nit","labels_url":"https://api.github.com/repos/nitlang/nit/issues/1000/labels{/name}","comments_url":"https://api.github.com/repos/nitlang/nit/issues/1000/comments","events_url":"https://api.github.com/repos/nitlang/nit/issues/1000/events","html_url":"https://github.com/nitlang/nit/pull/1000","id":51639845,"node_id":"MDExOlB1bGxSZXF1ZXN0MjU4NzM0Mzg=","number":1000,"title":"Raise nitc from the dead","user":{"login":"privat","id":135828,"node_id":"MDQ6VXNlcjEzNTgyOA==","avatar_url":"https://avatars1.githubusercontent.com/u/135828?v=4","gravatar_id":"","url":"https://api.github.com/users/privat","html_url":"https://github.com/privat","followers_url":"https://api.github.com/users/privat/followers","following_url":"https://api.github.com/users/privat/following{/other_user}","gists_url":"https://api.github.com/users/privat/gists{/gist_id}","starred_url":"https://api.github.com/users/privat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/privat/subscriptions","organizations_url":"https://api.github.com/users/privat/orgs","repos_url":"https://api.github.com/users/privat/repos","events_url":"https://api.github.com/users/privat/events{/privacy}","received_events_url":"https://api.github.com/users/privat/received_events","type":"User","site_admin":false},"labels":[{"id":81916206,"node_id":"MDU6TGFiZWw4MTkxNjIwNg==","url":"https://api.github.com/repos/nitlang/nit/labels/ok_will_merge","name":"ok_will_merge","color":"009800","default":false}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":7,"created_at":"2014-12-11T02:55:09Z","updated_at":"2014-12-18T14:14:33Z","closed_at":"2014-12-13T15:38:09Z","author_association":"MEMBER","pull_request":{"url":"https://api.github.com/repos/nitlang/nit/pulls/1000","html_url":"https://github.com/nitlang/nit/pull/1000","diff_url":"https://github.com/nitlang/nit/pull/1000.diff","patch_url":"https://github.com/nitlang/nit/pull/1000.patch"},"body":"Raise dead on `nitc`.\nIt's super effective...\n","closed_by":{"login":"privat","id":135828,"node_id":"MDQ6VXNlcjEzNTgyOA==","avatar_url":"https://avatars1.githubusercontent.com/u/135828?v=4","gravatar_id":"","url":"https://api.github.com/users/privat","html_url":"https://github.com/privat","followers_url":"https://api.github.com/users/privat/followers","following_url":"https://api.github.com/users/privat/following{/other_user}","gists_url":"https://api.github.com/users/privat/gists{/gist_id}","starred_url":"https://api.github.com/users/privat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/privat/subscriptions","organizations_url":"https://api.github.com/users/privat/orgs","repos_url":"https://api.github.com/users/privat/repos","events_url":"https://api.github.com/users/privat/events{/privacy}","received_events_url":"https://api.github.com/users/privat/received_events","type":"User","site_admin":false}}
\ No newline at end of file
diff --git a/lib/github/tests/mock/repo_issues_comments_6020149.res b/lib/github/tests/mock/repo_issues_comments_6020149.res
new file mode 100644 (file)
index 0000000..8b2f691
--- /dev/null
@@ -0,0 +1 @@
+{"url":"https://api.github.com/repos/nitlang/nit/issues/comments/6020149","html_url":"https://github.com/nitlang/nit/pull/10#issuecomment-6020149","issue_url":"https://api.github.com/repos/nitlang/nit/issues/10","id":6020149,"node_id":"MDEyOklzc3VlQ29tbWVudDYwMjAxNDk=","user":{"login":"privat","id":135828,"node_id":"MDQ6VXNlcjEzNTgyOA==","avatar_url":"https://avatars1.githubusercontent.com/u/135828?v=4","gravatar_id":"","url":"https://api.github.com/users/privat","html_url":"https://github.com/privat","followers_url":"https://api.github.com/users/privat/followers","following_url":"https://api.github.com/users/privat/following{/other_user}","gists_url":"https://api.github.com/users/privat/gists{/gist_id}","starred_url":"https://api.github.com/users/privat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/privat/subscriptions","organizations_url":"https://api.github.com/users/privat/orgs","repos_url":"https://api.github.com/users/privat/repos","events_url":"https://api.github.com/users/privat/events{/privacy}","received_events_url":"https://api.github.com/users/privat/received_events","type":"User","site_admin":false},"created_at":"2012-05-30T20:16:54Z","updated_at":"2012-05-30T20:16:54Z","author_association":"MEMBER","body":"Rebased e766cde to drop the ugly github merge commit 0e3a614.\nThe result is 8f221e3.\n"}
\ No newline at end of file
diff --git a/lib/github/tests/mock/repo_issues_events_199674194.res b/lib/github/tests/mock/repo_issues_events_199674194.res
new file mode 100644 (file)
index 0000000..5e6b941
--- /dev/null
@@ -0,0 +1 @@
+{"id":199674194,"node_id":"MDEyOkxhYmVsZWRFdmVudDE5OTY3NDE5NA==","url":"https://api.github.com/repos/nitlang/nit/issues/events/199674194","actor":{"login":"privat","id":135828,"node_id":"MDQ6VXNlcjEzNTgyOA==","avatar_url":"https://avatars1.githubusercontent.com/u/135828?v=4","gravatar_id":"","url":"https://api.github.com/users/privat","html_url":"https://github.com/privat","followers_url":"https://api.github.com/users/privat/followers","following_url":"https://api.github.com/users/privat/following{/other_user}","gists_url":"https://api.github.com/users/privat/gists{/gist_id}","starred_url":"https://api.github.com/users/privat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/privat/subscriptions","organizations_url":"https://api.github.com/users/privat/orgs","repos_url":"https://api.github.com/users/privat/repos","events_url":"https://api.github.com/users/privat/events{/privacy}","received_events_url":"https://api.github.com/users/privat/received_events","type":"User","site_admin":false},"event":"labeled","commit_id":null,"commit_url":null,"created_at":"2014-11-27T20:32:30Z","label":{"name":"need_review","color":"fbca04"},"issue":{"url":"https://api.github.com/repos/nitlang/nit/issues/945","repository_url":"https://api.github.com/repos/nitlang/nit","labels_url":"https://api.github.com/repos/nitlang/nit/issues/945/labels{/name}","comments_url":"https://api.github.com/repos/nitlang/nit/issues/945/comments","events_url":"https://api.github.com/repos/nitlang/nit/issues/945/events","html_url":"https://github.com/nitlang/nit/pull/945","id":50322007,"node_id":"MDExOlB1bGxSZXF1ZXN0MjUxNjg4ODY=","number":945,"title":"Useless type","user":{"login":"privat","id":135828,"node_id":"MDQ6VXNlcjEzNTgyOA==","avatar_url":"https://avatars1.githubusercontent.com/u/135828?v=4","gravatar_id":"","url":"https://api.github.com/users/privat","html_url":"https://github.com/privat","followers_url":"https://api.github.com/users/privat/followers","following_url":"https://api.github.com/users/privat/following{/other_user}","gists_url":"https://api.github.com/users/privat/gists{/gist_id}","starred_url":"https://api.github.com/users/privat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/privat/subscriptions","organizations_url":"https://api.github.com/users/privat/orgs","repos_url":"https://api.github.com/users/privat/repos","events_url":"https://api.github.com/users/privat/events{/privacy}","received_events_url":"https://api.github.com/users/privat/received_events","type":"User","site_admin":false},"labels":[{"id":81916206,"node_id":"MDU6TGFiZWw4MTkxNjIwNg==","url":"https://api.github.com/repos/nitlang/nit/labels/ok_will_merge","name":"ok_will_merge","color":"009800","default":false}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2014-11-27T20:32:27Z","updated_at":"2014-12-03T20:22:42Z","closed_at":"2014-12-01T13:53:03Z","author_association":"MEMBER","pull_request":{"url":"https://api.github.com/repos/nitlang/nit/pulls/945","html_url":"https://github.com/nitlang/nit/pull/945","diff_url":"https://github.com/nitlang/nit/pull/945.diff","patch_url":"https://github.com/nitlang/nit/pull/945.patch"},"body":"Fix a wrong `useless-type` warning for attributes.\nExtends the `useless-type` warning to local variables.\n"}}
\ No newline at end of file
diff --git a/lib/github/tests/mock/repo_labels_ok_will_merge.res b/lib/github/tests/mock/repo_labels_ok_will_merge.res
new file mode 100644 (file)
index 0000000..e75432c
--- /dev/null
@@ -0,0 +1 @@
+{"id":81916206,"node_id":"MDU6TGFiZWw4MTkxNjIwNg==","url":"https://api.github.com/repos/nitlang/nit/labels/ok_will_merge","name":"ok_will_merge","color":"009800","default":false}
\ No newline at end of file
diff --git a/lib/github/tests/mock/repo_milestones_4.res b/lib/github/tests/mock/repo_milestones_4.res
new file mode 100644 (file)
index 0000000..69abdc0
--- /dev/null
@@ -0,0 +1 @@
+{"url":"https://api.github.com/repos/nitlang/nit/milestones/4","html_url":"https://github.com/nitlang/nit/milestone/4","labels_url":"https://api.github.com/repos/nitlang/nit/milestones/4/labels","id":795157,"node_id":"MDk6TWlsZXN0b25lNzk1MTU3","number":4,"title":"v1.0prealpha","description":"The first public version that we are proud off and can be used sanely by non Nit people.","creator":{"login":"privat","id":135828,"node_id":"MDQ6VXNlcjEzNTgyOA==","avatar_url":"https://avatars1.githubusercontent.com/u/135828?v=4","gravatar_id":"","url":"https://api.github.com/users/privat","html_url":"https://github.com/privat","followers_url":"https://api.github.com/users/privat/followers","following_url":"https://api.github.com/users/privat/following{/other_user}","gists_url":"https://api.github.com/users/privat/gists{/gist_id}","starred_url":"https://api.github.com/users/privat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/privat/subscriptions","organizations_url":"https://api.github.com/users/privat/orgs","repos_url":"https://api.github.com/users/privat/repos","events_url":"https://api.github.com/users/privat/events{/privacy}","received_events_url":"https://api.github.com/users/privat/received_events","type":"User","site_admin":false},"open_issues":22,"closed_issues":22,"state":"open","created_at":"2014-09-19T00:16:45Z","updated_at":"2017-06-02T12:43:15Z","due_on":null,"closed_at":null}
\ No newline at end of file
diff --git a/lib/github/tests/mock/repo_nit.res b/lib/github/tests/mock/repo_nit.res
new file mode 100644 (file)
index 0000000..8acf396
--- /dev/null
@@ -0,0 +1 @@
+{"id":328597,"node_id":"MDEwOlJlcG9zaXRvcnkzMjg1OTc=","name":"nit","full_name":"nitlang/nit","private":false,"owner":{"login":"nitlang","id":5420298,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU0MjAyOTg=","avatar_url":"https://avatars1.githubusercontent.com/u/5420298?v=4","gravatar_id":"","url":"https://api.github.com/users/nitlang","html_url":"https://github.com/nitlang","followers_url":"https://api.github.com/users/nitlang/followers","following_url":"https://api.github.com/users/nitlang/following{/other_user}","gists_url":"https://api.github.com/users/nitlang/gists{/gist_id}","starred_url":"https://api.github.com/users/nitlang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nitlang/subscriptions","organizations_url":"https://api.github.com/users/nitlang/orgs","repos_url":"https://api.github.com/users/nitlang/repos","events_url":"https://api.github.com/users/nitlang/events{/privacy}","received_events_url":"https://api.github.com/users/nitlang/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/nitlang/nit","description":"Nit language","fork":false,"url":"https://api.github.com/repos/nitlang/nit","forks_url":"https://api.github.com/repos/nitlang/nit/forks","keys_url":"https://api.github.com/repos/nitlang/nit/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nitlang/nit/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nitlang/nit/teams","hooks_url":"https://api.github.com/repos/nitlang/nit/hooks","issue_events_url":"https://api.github.com/repos/nitlang/nit/issues/events{/number}","events_url":"https://api.github.com/repos/nitlang/nit/events","assignees_url":"https://api.github.com/repos/nitlang/nit/assignees{/user}","branches_url":"https://api.github.com/repos/nitlang/nit/branches{/branch}","tags_url":"https://api.github.com/repos/nitlang/nit/tags","blobs_url":"https://api.github.com/repos/nitlang/nit/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nitlang/nit/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nitlang/nit/git/refs{/sha}","trees_url":"https://api.github.com/repos/nitlang/nit/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nitlang/nit/statuses/{sha}","languages_url":"https://api.github.com/repos/nitlang/nit/languages","stargazers_url":"https://api.github.com/repos/nitlang/nit/stargazers","contributors_url":"https://api.github.com/repos/nitlang/nit/contributors","subscribers_url":"https://api.github.com/repos/nitlang/nit/subscribers","subscription_url":"https://api.github.com/repos/nitlang/nit/subscription","commits_url":"https://api.github.com/repos/nitlang/nit/commits{/sha}","git_commits_url":"https://api.github.com/repos/nitlang/nit/git/commits{/sha}","comments_url":"https://api.github.com/repos/nitlang/nit/comments{/number}","issue_comment_url":"https://api.github.com/repos/nitlang/nit/issues/comments{/number}","contents_url":"https://api.github.com/repos/nitlang/nit/contents/{+path}","compare_url":"https://api.github.com/repos/nitlang/nit/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nitlang/nit/merges","archive_url":"https://api.github.com/repos/nitlang/nit/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nitlang/nit/downloads","issues_url":"https://api.github.com/repos/nitlang/nit/issues{/number}","pulls_url":"https://api.github.com/repos/nitlang/nit/pulls{/number}","milestones_url":"https://api.github.com/repos/nitlang/nit/milestones{/number}","notifications_url":"https://api.github.com/repos/nitlang/nit/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nitlang/nit/labels{/name}","releases_url":"https://api.github.com/repos/nitlang/nit/releases{/id}","deployments_url":"https://api.github.com/repos/nitlang/nit/deployments","created_at":"2009-10-06T15:03:00Z","updated_at":"2019-06-17T13:13:03Z","pushed_at":"2019-06-19T00:02:11Z","git_url":"git://github.com/nitlang/nit.git","ssh_url":"git@github.com:nitlang/nit.git","clone_url":"https://github.com/nitlang/nit.git","svn_url":"https://github.com/nitlang/nit","homepage":"http://nitlanguage.org","size":123083,"stargazers_count":187,"watchers_count":187,"language":"C","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":56,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":171,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":56,"open_issues":171,"watchers":187,"default_branch":"master","permissions":{"admin":false,"push":true,"pull":true},"organization":{"login":"nitlang","id":5420298,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU0MjAyOTg=","avatar_url":"https://avatars1.githubusercontent.com/u/5420298?v=4","gravatar_id":"","url":"https://api.github.com/users/nitlang","html_url":"https://github.com/nitlang","followers_url":"https://api.github.com/users/nitlang/followers","following_url":"https://api.github.com/users/nitlang/following{/other_user}","gists_url":"https://api.github.com/users/nitlang/gists{/gist_id}","starred_url":"https://api.github.com/users/nitlang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nitlang/subscriptions","organizations_url":"https://api.github.com/users/nitlang/orgs","repos_url":"https://api.github.com/users/nitlang/repos","events_url":"https://api.github.com/users/nitlang/events{/privacy}","received_events_url":"https://api.github.com/users/nitlang/received_events","type":"Organization","site_admin":false},"network_count":56,"subscribers_count":18}
\ No newline at end of file
diff --git a/lib/github/tests/mock/repo_pulls_1000.res b/lib/github/tests/mock/repo_pulls_1000.res
new file mode 100644 (file)
index 0000000..76f6935
--- /dev/null
@@ -0,0 +1 @@
+{"url":"https://api.github.com/repos/nitlang/nit/pulls/1000","id":25873438,"node_id":"MDExOlB1bGxSZXF1ZXN0MjU4NzM0Mzg=","html_url":"https://github.com/nitlang/nit/pull/1000","diff_url":"https://github.com/nitlang/nit/pull/1000.diff","patch_url":"https://github.com/nitlang/nit/pull/1000.patch","issue_url":"https://api.github.com/repos/nitlang/nit/issues/1000","number":1000,"state":"closed","locked":false,"title":"Raise nitc from the dead","user":{"login":"privat","id":135828,"node_id":"MDQ6VXNlcjEzNTgyOA==","avatar_url":"https://avatars1.githubusercontent.com/u/135828?v=4","gravatar_id":"","url":"https://api.github.com/users/privat","html_url":"https://github.com/privat","followers_url":"https://api.github.com/users/privat/followers","following_url":"https://api.github.com/users/privat/following{/other_user}","gists_url":"https://api.github.com/users/privat/gists{/gist_id}","starred_url":"https://api.github.com/users/privat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/privat/subscriptions","organizations_url":"https://api.github.com/users/privat/orgs","repos_url":"https://api.github.com/users/privat/repos","events_url":"https://api.github.com/users/privat/events{/privacy}","received_events_url":"https://api.github.com/users/privat/received_events","type":"User","site_admin":false},"body":"Raise dead on `nitc`.\nIt's super effective...\n","created_at":"2014-12-11T02:55:09Z","updated_at":"2014-12-18T14:14:33Z","closed_at":"2014-12-13T15:38:09Z","merged_at":"2014-12-13T15:38:09Z","merge_commit_sha":"49af656d278987d3a09f8500bcbe019e3c0f6367","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":81916206,"node_id":"MDU6TGFiZWw4MTkxNjIwNg==","url":"https://api.github.com/repos/nitlang/nit/labels/ok_will_merge","name":"ok_will_merge","color":"009800","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/nitlang/nit/pulls/1000/commits","review_comments_url":"https://api.github.com/repos/nitlang/nit/pulls/1000/comments","review_comment_url":"https://api.github.com/repos/nitlang/nit/pulls/comments{/number}","comments_url":"https://api.github.com/repos/nitlang/nit/issues/1000/comments","statuses_url":"https://api.github.com/repos/nitlang/nit/statuses/273b078ecc1a395f260992ec9fb08a31e8c338d9","head":{"label":"nitlang:raise-nitc","ref":"raise-nitc","sha":"273b078ecc1a395f260992ec9fb08a31e8c338d9","user":{"login":"nitlang","id":5420298,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU0MjAyOTg=","avatar_url":"https://avatars1.githubusercontent.com/u/5420298?v=4","gravatar_id":"","url":"https://api.github.com/users/nitlang","html_url":"https://github.com/nitlang","followers_url":"https://api.github.com/users/nitlang/followers","following_url":"https://api.github.com/users/nitlang/following{/other_user}","gists_url":"https://api.github.com/users/nitlang/gists{/gist_id}","starred_url":"https://api.github.com/users/nitlang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nitlang/subscriptions","organizations_url":"https://api.github.com/users/nitlang/orgs","repos_url":"https://api.github.com/users/nitlang/repos","events_url":"https://api.github.com/users/nitlang/events{/privacy}","received_events_url":"https://api.github.com/users/nitlang/received_events","type":"Organization","site_admin":false},"repo":{"id":328597,"node_id":"MDEwOlJlcG9zaXRvcnkzMjg1OTc=","name":"nit","full_name":"nitlang/nit","private":false,"owner":{"login":"nitlang","id":5420298,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU0MjAyOTg=","avatar_url":"https://avatars1.githubusercontent.com/u/5420298?v=4","gravatar_id":"","url":"https://api.github.com/users/nitlang","html_url":"https://github.com/nitlang","followers_url":"https://api.github.com/users/nitlang/followers","following_url":"https://api.github.com/users/nitlang/following{/other_user}","gists_url":"https://api.github.com/users/nitlang/gists{/gist_id}","starred_url":"https://api.github.com/users/nitlang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nitlang/subscriptions","organizations_url":"https://api.github.com/users/nitlang/orgs","repos_url":"https://api.github.com/users/nitlang/repos","events_url":"https://api.github.com/users/nitlang/events{/privacy}","received_events_url":"https://api.github.com/users/nitlang/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/nitlang/nit","description":"Nit language","fork":false,"url":"https://api.github.com/repos/nitlang/nit","forks_url":"https://api.github.com/repos/nitlang/nit/forks","keys_url":"https://api.github.com/repos/nitlang/nit/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nitlang/nit/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nitlang/nit/teams","hooks_url":"https://api.github.com/repos/nitlang/nit/hooks","issue_events_url":"https://api.github.com/repos/nitlang/nit/issues/events{/number}","events_url":"https://api.github.com/repos/nitlang/nit/events","assignees_url":"https://api.github.com/repos/nitlang/nit/assignees{/user}","branches_url":"https://api.github.com/repos/nitlang/nit/branches{/branch}","tags_url":"https://api.github.com/repos/nitlang/nit/tags","blobs_url":"https://api.github.com/repos/nitlang/nit/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nitlang/nit/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nitlang/nit/git/refs{/sha}","trees_url":"https://api.github.com/repos/nitlang/nit/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nitlang/nit/statuses/{sha}","languages_url":"https://api.github.com/repos/nitlang/nit/languages","stargazers_url":"https://api.github.com/repos/nitlang/nit/stargazers","contributors_url":"https://api.github.com/repos/nitlang/nit/contributors","subscribers_url":"https://api.github.com/repos/nitlang/nit/subscribers","subscription_url":"https://api.github.com/repos/nitlang/nit/subscription","commits_url":"https://api.github.com/repos/nitlang/nit/commits{/sha}","git_commits_url":"https://api.github.com/repos/nitlang/nit/git/commits{/sha}","comments_url":"https://api.github.com/repos/nitlang/nit/comments{/number}","issue_comment_url":"https://api.github.com/repos/nitlang/nit/issues/comments{/number}","contents_url":"https://api.github.com/repos/nitlang/nit/contents/{+path}","compare_url":"https://api.github.com/repos/nitlang/nit/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nitlang/nit/merges","archive_url":"https://api.github.com/repos/nitlang/nit/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nitlang/nit/downloads","issues_url":"https://api.github.com/repos/nitlang/nit/issues{/number}","pulls_url":"https://api.github.com/repos/nitlang/nit/pulls{/number}","milestones_url":"https://api.github.com/repos/nitlang/nit/milestones{/number}","notifications_url":"https://api.github.com/repos/nitlang/nit/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nitlang/nit/labels{/name}","releases_url":"https://api.github.com/repos/nitlang/nit/releases{/id}","deployments_url":"https://api.github.com/repos/nitlang/nit/deployments","created_at":"2009-10-06T15:03:00Z","updated_at":"2019-06-17T13:13:03Z","pushed_at":"2019-06-19T00:02:11Z","git_url":"git://github.com/nitlang/nit.git","ssh_url":"git@github.com:nitlang/nit.git","clone_url":"https://github.com/nitlang/nit.git","svn_url":"https://github.com/nitlang/nit","homepage":"http://nitlanguage.org","size":123083,"stargazers_count":187,"watchers_count":187,"language":"C","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":56,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":171,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":56,"open_issues":171,"watchers":187,"default_branch":"master"}},"base":{"label":"nitlang:master","ref":"master","sha":"8bd95517ec64090da1356ee1a88af82a9ccf2847","user":{"login":"nitlang","id":5420298,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU0MjAyOTg=","avatar_url":"https://avatars1.githubusercontent.com/u/5420298?v=4","gravatar_id":"","url":"https://api.github.com/users/nitlang","html_url":"https://github.com/nitlang","followers_url":"https://api.github.com/users/nitlang/followers","following_url":"https://api.github.com/users/nitlang/following{/other_user}","gists_url":"https://api.github.com/users/nitlang/gists{/gist_id}","starred_url":"https://api.github.com/users/nitlang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nitlang/subscriptions","organizations_url":"https://api.github.com/users/nitlang/orgs","repos_url":"https://api.github.com/users/nitlang/repos","events_url":"https://api.github.com/users/nitlang/events{/privacy}","received_events_url":"https://api.github.com/users/nitlang/received_events","type":"Organization","site_admin":false},"repo":{"id":328597,"node_id":"MDEwOlJlcG9zaXRvcnkzMjg1OTc=","name":"nit","full_name":"nitlang/nit","private":false,"owner":{"login":"nitlang","id":5420298,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU0MjAyOTg=","avatar_url":"https://avatars1.githubusercontent.com/u/5420298?v=4","gravatar_id":"","url":"https://api.github.com/users/nitlang","html_url":"https://github.com/nitlang","followers_url":"https://api.github.com/users/nitlang/followers","following_url":"https://api.github.com/users/nitlang/following{/other_user}","gists_url":"https://api.github.com/users/nitlang/gists{/gist_id}","starred_url":"https://api.github.com/users/nitlang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nitlang/subscriptions","organizations_url":"https://api.github.com/users/nitlang/orgs","repos_url":"https://api.github.com/users/nitlang/repos","events_url":"https://api.github.com/users/nitlang/events{/privacy}","received_events_url":"https://api.github.com/users/nitlang/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/nitlang/nit","description":"Nit language","fork":false,"url":"https://api.github.com/repos/nitlang/nit","forks_url":"https://api.github.com/repos/nitlang/nit/forks","keys_url":"https://api.github.com/repos/nitlang/nit/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nitlang/nit/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nitlang/nit/teams","hooks_url":"https://api.github.com/repos/nitlang/nit/hooks","issue_events_url":"https://api.github.com/repos/nitlang/nit/issues/events{/number}","events_url":"https://api.github.com/repos/nitlang/nit/events","assignees_url":"https://api.github.com/repos/nitlang/nit/assignees{/user}","branches_url":"https://api.github.com/repos/nitlang/nit/branches{/branch}","tags_url":"https://api.github.com/repos/nitlang/nit/tags","blobs_url":"https://api.github.com/repos/nitlang/nit/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nitlang/nit/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nitlang/nit/git/refs{/sha}","trees_url":"https://api.github.com/repos/nitlang/nit/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nitlang/nit/statuses/{sha}","languages_url":"https://api.github.com/repos/nitlang/nit/languages","stargazers_url":"https://api.github.com/repos/nitlang/nit/stargazers","contributors_url":"https://api.github.com/repos/nitlang/nit/contributors","subscribers_url":"https://api.github.com/repos/nitlang/nit/subscribers","subscription_url":"https://api.github.com/repos/nitlang/nit/subscription","commits_url":"https://api.github.com/repos/nitlang/nit/commits{/sha}","git_commits_url":"https://api.github.com/repos/nitlang/nit/git/commits{/sha}","comments_url":"https://api.github.com/repos/nitlang/nit/comments{/number}","issue_comment_url":"https://api.github.com/repos/nitlang/nit/issues/comments{/number}","contents_url":"https://api.github.com/repos/nitlang/nit/contents/{+path}","compare_url":"https://api.github.com/repos/nitlang/nit/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nitlang/nit/merges","archive_url":"https://api.github.com/repos/nitlang/nit/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nitlang/nit/downloads","issues_url":"https://api.github.com/repos/nitlang/nit/issues{/number}","pulls_url":"https://api.github.com/repos/nitlang/nit/pulls{/number}","milestones_url":"https://api.github.com/repos/nitlang/nit/milestones{/number}","notifications_url":"https://api.github.com/repos/nitlang/nit/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nitlang/nit/labels{/name}","releases_url":"https://api.github.com/repos/nitlang/nit/releases{/id}","deployments_url":"https://api.github.com/repos/nitlang/nit/deployments","created_at":"2009-10-06T15:03:00Z","updated_at":"2019-06-17T13:13:03Z","pushed_at":"2019-06-19T00:02:11Z","git_url":"git://github.com/nitlang/nit.git","ssh_url":"git@github.com:nitlang/nit.git","clone_url":"https://github.com/nitlang/nit.git","svn_url":"https://github.com/nitlang/nit","homepage":"http://nitlanguage.org","size":123083,"stargazers_count":187,"watchers_count":187,"language":"C","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":56,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":171,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":56,"open_issues":171,"watchers":187,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/nitlang/nit/pulls/1000"},"html":{"href":"https://github.com/nitlang/nit/pull/1000"},"issue":{"href":"https://api.github.com/repos/nitlang/nit/issues/1000"},"comments":{"href":"https://api.github.com/repos/nitlang/nit/issues/1000/comments"},"review_comments":{"href":"https://api.github.com/repos/nitlang/nit/pulls/1000/comments"},"review_comment":{"href":"https://api.github.com/repos/nitlang/nit/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/nitlang/nit/pulls/1000/commits"},"statuses":{"href":"https://api.github.com/repos/nitlang/nit/statuses/273b078ecc1a395f260992ec9fb08a31e8c338d9"}},"author_association":"MEMBER","merged":true,"mergeable":null,"rebaseable":null,"mergeable_state":"unknown","merged_by":{"login":"privat","id":135828,"node_id":"MDQ6VXNlcjEzNTgyOA==","avatar_url":"https://avatars1.githubusercontent.com/u/135828?v=4","gravatar_id":"","url":"https://api.github.com/users/privat","html_url":"https://github.com/privat","followers_url":"https://api.github.com/users/privat/followers","following_url":"https://api.github.com/users/privat/following{/other_user}","gists_url":"https://api.github.com/users/privat/gists{/gist_id}","starred_url":"https://api.github.com/users/privat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/privat/subscriptions","organizations_url":"https://api.github.com/users/privat/orgs","repos_url":"https://api.github.com/users/privat/repos","events_url":"https://api.github.com/users/privat/events{/privacy}","received_events_url":"https://api.github.com/users/privat/received_events","type":"User","site_admin":false},"comments":7,"review_comments":0,"maintainer_can_modify":false,"commits":11,"additions":282,"deletions":268,"changed_files":67}
\ No newline at end of file
diff --git a/lib/github/tests/mock/repo_pulls_comment_21010363.res b/lib/github/tests/mock/repo_pulls_comment_21010363.res
new file mode 100644 (file)
index 0000000..c6f62ee
--- /dev/null
@@ -0,0 +1 @@
+{"url":"https://api.github.com/repos/nitlang/nit/pulls/comments/21010363","pull_request_review_id":null,"id":21010363,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxMDEwMzYz","diff_hunk":"@@ -981,11 +983,11 @@ redef class AAttrPropdef\n \n \t\t\t\tif mtype == null then return\n \t\t\tend\n-\t\telse if ntype != null then\n+\t\telse if ntype != null and inherited_type == mtype then\n \t\t\tif nexpr isa ANewExpr then\n \t\t\t\tvar xmtype = modelbuilder.resolve_mtype(mmodule, mclassdef, nexpr.n_type)\n \t\t\t\tif xmtype == mtype then\n-\t\t\t\t\tmodelbuilder.advice(ntype, \"useless-type\", \"Warning: useless type definition\")\n+\t\t\t\t\tmodelbuilder.advice(ntype, \"useless-type\", \"Warning: useless type definition {inherited_type or else \"?\"}\")","path":"src/modelize/modelize_property.nit","position":null,"original_position":26,"commit_id":"ce5e187a87ed5c41144ea5637188a0677d840fdc","original_commit_id":"5f0ab1c7f3c560a67867d5eb08f5c3082f251c20","user":{"login":"jcbrinfo","id":6044484,"node_id":"MDQ6VXNlcjYwNDQ0ODQ=","avatar_url":"https://avatars0.githubusercontent.com/u/6044484?v=4","gravatar_id":"","url":"https://api.github.com/users/jcbrinfo","html_url":"https://github.com/jcbrinfo","followers_url":"https://api.github.com/users/jcbrinfo/followers","following_url":"https://api.github.com/users/jcbrinfo/following{/other_user}","gists_url":"https://api.github.com/users/jcbrinfo/gists{/gist_id}","starred_url":"https://api.github.com/users/jcbrinfo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jcbrinfo/subscriptions","organizations_url":"https://api.github.com/users/jcbrinfo/orgs","repos_url":"https://api.github.com/users/jcbrinfo/repos","events_url":"https://api.github.com/users/jcbrinfo/events{/privacy}","received_events_url":"https://api.github.com/users/jcbrinfo/received_events","type":"User","site_admin":false},"body":"Warning: `inherited_type` is always non null here.\n","created_at":"2014-11-27T20:39:29Z","updated_at":"2014-11-28T01:05:12Z","html_url":"https://github.com/nitlang/nit/pull/945#discussion_r21010363","pull_request_url":"https://api.github.com/repos/nitlang/nit/pulls/945","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/nitlang/nit/pulls/comments/21010363"},"html":{"href":"https://github.com/nitlang/nit/pull/945#discussion_r21010363"},"pull_request":{"href":"https://api.github.com/repos/nitlang/nit/pulls/945"}}}
\ No newline at end of file
diff --git a/lib/github/tests/mock/user_Morriar.res b/lib/github/tests/mock/user_Morriar.res
new file mode 100644 (file)
index 0000000..5a491b1
--- /dev/null
@@ -0,0 +1 @@
+{"login":"Morriar","id":583144,"node_id":"MDQ6VXNlcjU4MzE0NA==","avatar_url":"https://avatars2.githubusercontent.com/u/583144?v=4","gravatar_id":"","url":"https://api.github.com/users/Morriar","html_url":"https://github.com/Morriar","followers_url":"https://api.github.com/users/Morriar/followers","following_url":"https://api.github.com/users/Morriar/following{/other_user}","gists_url":"https://api.github.com/users/Morriar/gists{/gist_id}","starred_url":"https://api.github.com/users/Morriar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Morriar/subscriptions","organizations_url":"https://api.github.com/users/Morriar/orgs","repos_url":"https://api.github.com/users/Morriar/repos","events_url":"https://api.github.com/users/Morriar/events{/privacy}","received_events_url":"https://api.github.com/users/Morriar/received_events","type":"User","site_admin":false,"name":"Alexandre Terrasa","company":null,"blog":"moz-code.org","location":null,"email":"alexandre@moz-code.org","hireable":null,"bio":null,"public_repos":96,"public_gists":1,"followers":42,"following":10,"created_at":"2011-01-25T17:50:36Z","updated_at":"2019-06-15T01:41:56Z"}
\ No newline at end of file
diff --git a/lib/github/tests/test_api.nit b/lib/github/tests/test_api.nit
new file mode 100644 (file)
index 0000000..7176aaa
--- /dev/null
@@ -0,0 +1,346 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module test_api is test
+
+intrude import api
+
+# GithubAPI testing
+#
+# To avoid test flakyness we test the GithubAPI against a mock of the real one.
+# For each api request we return a cache file of the real API response body.
+#
+# Cache files can be automatically created and updated by setting
+# `update_responses_cache` to `true` then running `nitunit`.
+class MockGithubCurl
+       super GithubCurl
+
+       # Mock so it returns the response from a file
+       #
+       # See `update_responses_cache`.
+       redef fun get_and_parse(uri) do
+               print uri # for debugging
+
+               var path = uri.replace("https://api.github.com/", "/")
+               assert has_response(path)
+
+               if update_responses_cache then
+                       var file = response_file(path)
+                       save_actual_response(uri, file)
+               end
+
+               var response = response_string(path).parse_json
+               if response_is_error(path) then
+                       var title = "GithubAPIError"
+                       var msg = response.as(JsonObject)["message"].as(String)
+                       var err = new GithubError(msg, title)
+                       err.json["requested_uri"] = uri
+                       err.json["status_code"] = response_code(path)
+                       return err
+               end
+               return response
+       end
+
+       var test_responses: Map[String, String] do
+               var map = new HashMap[String, String]
+               map["/user"] = "user_Morriar"
+               map["/users/Morriar"] = "user_Morriar"
+               map["/repos/nitlang/nit"] = "repo_nit"
+               map["/repos/nitlang/nit/labels/ok_will_merge"] = "repo_labels_ok_will_merge"
+               map["/repos/nitlang/nit/milestones/4"] = "repo_milestones_4"
+               map["/repos/nitlang/nit/branches"] = "repo_branches_nit"
+               map["/repos/nitlang/nit/branches/master"] = "repo_branches_master"
+               map["/repos/nitlang/nit/issues/1000"] = "repo_issues_1000"
+               map["/repos/nitlang/nit/issues/comments/6020149"] = "repo_issues_comments_6020149"
+               map["/repos/nitlang/nit/issues/events/199674194"] = "repo_issues_events_199674194"
+               map["/repos/nitlang/nit/pulls/1000"] = "repo_pulls_1000"
+               map["/repos/nitlang/nit/commits/64ce1f"] = "repo_commits_64ce1f"
+               map["/repos/nitlang/nit/comments/8982707"] = "repo_comments_8982707"
+               map["/repos/nitlang/nit/pulls/comments/21010363"] = "repo_pulls_comment_21010363"
+               # errors
+               map["/users/not_found/not_found"] = "errors_404"
+               return map
+       end
+
+       # Does `self` have a mock response for Github `path`?
+       fun has_response(path: String): Bool do
+               return test_responses.has_key(path)
+       end
+
+       # Root responses cache directory
+       var responses_dir: String is lazy do
+               var path = "NIT_TESTING_PATH".environ.dirname / "mock"
+               path.mkdir
+               return path
+       end
+
+       # Returns the response file path for a Github `path`
+       fun response_file(path: String): String do
+               assert has_response(path)
+               return "{responses_dir / test_responses[path]}.res"
+       end
+
+       # Returns the response body string for a Github `path`
+       fun response_string(path: String): String do
+               var file = response_file(path)
+               assert file.file_exists
+               return file.to_path.read_all
+       end
+
+       # Is this response a simulated error?
+       fun response_is_error(path: String): Bool do
+               assert has_response(path)
+               return test_responses[path].has_prefix("errors_")
+       end
+
+       # Status code of a simulated error
+       #
+       # See `response_is_error`.
+       fun response_code(path: String): String do
+               assert response_is_error(path)
+               return test_responses[path].split("_").last
+       end
+
+       # Response caching
+
+       # Activate caching
+       #
+       # Change this value to `true` then run nitunit to cache the responses
+       # from the Github API.
+       #
+       # Default is `false`.
+       var update_responses_cache = false
+
+       # Save the actual Github API response body for `uri` to a `file`
+       private fun save_actual_response(uri, file: String) do
+               assert update_responses_cache
+
+               var request = new CurlHTTPRequest(uri)
+               request.user_agent = actual_curl.user_agent
+               request.headers = actual_curl.header
+               var response = request.execute
+
+               if response isa CurlResponseSuccess then
+                       response.body_str.write_to_file(file)
+               else if response isa CurlResponseFailed then
+                       response.error_msg.write_to_file(file)
+               else abort
+
+               print "Response to `{uri}` saved at `{file}`"
+       end
+
+       # Actual GithubCurl instance used for caching
+       private var actual_curl = new GithubCurl(get_github_oauth, "nitunit")
+end
+
+class TestGithubAPI
+       test
+
+       var mock = new MockGithubCurl("test", "test")
+
+       fun api: GithubAPI do
+               var api = new GithubAPI("test")
+               api.ghcurl = mock
+               return api
+       end
+
+       fun test_deserialize is test do
+               var response = mock.response_string("/users/Morriar")
+               var obj = api.deserialize(response)
+               assert obj isa User
+               assert obj.login == "Morriar"
+       end
+
+       fun test_sanitize_url is test do
+               # TODO better tests
+               assert api.sanitize_uri("/repos/Nit with spaces/") == "/repos/Nit%20with%20spaces/"
+       end
+
+       fun test_get is test do
+               var api = self.api
+               var obj = api.get("/users/Morriar")
+               assert not api.was_error
+               assert api.last_error == null
+               assert obj isa JsonObject
+               assert obj["login"] == "Morriar"
+       end
+
+       fun test_get_404 is test do
+               var api = self.api
+               var res = api.get("/users/not_found/not_found")
+               assert res == null
+               assert api.was_error
+               var err = api.last_error
+               assert err isa GithubError
+               assert err.name == "GithubAPIError"
+               assert err.message == "Not Found"
+       end
+
+       fun test_load_from_github is test do
+               var api = self.api
+               var obj = api.load_from_github("/users/Morriar")
+               assert not api.was_error
+               assert api.last_error == null
+               assert obj isa User
+               assert obj.login == "Morriar"
+       end
+
+       fun test_load_from_github_404 is test do
+               var api = self.api
+               var res = api.load_from_github("/users/not_found/not_found")
+               assert res == null
+               assert api.was_error
+               var err = api.last_error
+               assert err isa GithubError
+               assert err.name == "GithubAPIError"
+               assert err.message == "Not Found"
+       end
+
+       # TODO test more error cases
+
+       fun test_get_auth_user is test do
+               var user = api.load_auth_user
+               assert user isa User
+               assert user.login == "Morriar"
+               assert user.avatar_url == "https://avatars2.githubusercontent.com/u/583144?v=4"
+               assert user.name == "Alexandre Terrasa"
+               assert user.email == "alexandre@moz-code.org"
+               assert user.blog == "moz-code.org"
+       end
+
+       fun test_get_user is test do
+               var user = api.load_user("Morriar")
+               assert user isa User
+               assert user.login == "Morriar"
+               assert user.avatar_url == "https://avatars2.githubusercontent.com/u/583144?v=4"
+               assert user.name == "Alexandre Terrasa"
+               assert user.email == "alexandre@moz-code.org"
+               assert user.blog == "moz-code.org"
+       end
+
+       fun test_get_repo is test do
+               var repo = api.load_repo("nitlang/nit")
+               assert repo isa Repo
+               assert repo.full_name == "nitlang/nit"
+               assert repo.name == "nit"
+               assert repo.owner.login == "nitlang"
+               assert repo.default_branch == "master"
+       end
+
+       private var repo: Repo is lazy do return api.load_repo("nitlang/nit").as(not null)
+
+       fun test_get_branches is test do
+               var branches = api.load_repo_branches(repo)
+               assert branches.length == 2
+               assert branches.first.name == "master"
+               assert branches.last.name == "next"
+       end
+
+       # TODO issues
+       # TODO repo_last_issue
+       # TODO labels
+       # TODO milestones
+       # TODO pulls
+       # TODO contrib_stats
+
+       fun test_get_branch is test do
+               var branch = api.load_branch(repo, "master")
+               assert branch isa Branch
+               assert branch.name == "master"
+       end
+
+       # TODO branch commits
+
+       fun test_get_commit is test do
+               var commit = api.load_commit(repo, "64ce1f")
+               assert commit isa Commit
+               assert commit.sha == "64ce1f587209024f5de46d06c70526a569ff537f"
+               # TODO other fields
+       end
+
+       fun test_get_issue is test do
+               var issue = api.load_issue(repo, 1000)
+               assert issue isa Issue
+               assert issue.number == 1000
+               assert issue.title == "Raise nitc from the dead"
+               assert issue.user.as(User).login == "privat"
+               assert issue.comments == 7
+               assert issue.created_at == "2014-12-11T02:55:09Z"
+               assert issue.closed_at == "2014-12-13T15:38:09Z"
+               assert issue.closed_by.as(User).login == "privat"
+               assert issue.body == "Raise dead on `nitc`.\nIt's super effective...\n"
+               assert issue.is_pull_request
+       end
+
+       # TODO issue comments
+       # TODO issue events
+
+       fun test_get_pull is test do
+               var pull = api.load_pull(repo, 1000)
+               assert pull isa Issue
+               assert pull.number == 1000
+               assert pull.title == "Raise nitc from the dead"
+               assert pull.user.as(User).login == "privat"
+               assert pull.comments == 7
+               assert pull.created_at == "2014-12-11T02:55:09Z"
+               assert pull.closed_at == "2014-12-13T15:38:09Z"
+               assert pull.merged_by.as(User).login == "privat"
+               assert pull.body == "Raise dead on `nitc`.\nIt's super effective...\n"
+       end
+
+       fun test_get_label is test do
+               var labl = api.load_label(repo, "ok_will_merge")
+               assert labl isa Label
+               assert labl.name == "ok_will_merge"
+       end
+
+       fun test_get_milestone is test do
+               var milestone = api.load_milestone(repo, 4)
+               assert milestone isa Milestone
+               assert milestone.title == "v1.0prealpha"
+               # TODO other fields
+       end
+
+       fun test_get_issue_event is test do
+               var event = api.load_issue_event(repo, 199674194)
+               assert event isa IssueEvent
+               assert event.actor.login == "privat"
+               assert event.event == "labeled"
+               assert event.labl.as(Label).name == "need_review"
+       end
+
+       fun test_get_issue_comment is test do
+               var comment = api.load_issue_comment(repo, 6020149)
+               assert comment isa IssueComment
+               assert comment.user.login == "privat"
+               assert comment.created_at.to_s == "2012-05-30T20:16:54Z"
+               assert comment.issue_number == 10
+       end
+
+       fun test_get_comment is test do
+               var comment = api.load_commit_comment(repo, 8982707)
+               assert comment isa CommitComment
+               assert comment.user.login == "Morriar"
+               assert comment.body == "For testing purposes...\n"
+               assert comment.commit_id == "7eacb86d1e24b7e72bc9ac869bf7182c0300ceca"
+       end
+
+       fun test_get_review_comments is test do
+               var comment = api.load_review_comment(repo, 21010363)
+               assert comment isa ReviewComment
+               assert comment.path == "src/modelize/modelize_property.nit"
+               assert comment.original_position == 26
+               assert comment.pull_number == 945
+       end
+end