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
.
github :: MockGithubAPI :: defaultinit
github :: MockGithubAPI :: has_response
Doesself
have a mock response for Github path
?
github :: MockGithubAPI :: response_code
Status code of a simulated errorgithub :: MockGithubAPI :: response_file
Returns the response file path for a Githubpath
github :: MockGithubAPI :: response_is_error
Is this response a simulated error?github :: MockGithubAPI :: response_string
Returns the response body string for a Githubpath
github :: MockGithubAPI :: responses_dir=
Root responses cache directorygithub :: MockGithubAPI :: update_responses_cache=
Activate cachinggithub $ MockGithubAPI :: SELF
Type of this instance, automatically specialized in every classcore :: Object :: class_factory
Implementation used byget_class
to create the specific class.
github :: MockGithubAPI :: defaultinit
core :: Object :: defaultinit
github :: GithubAPI :: defaultinit
github :: GithubAPI :: deserialize
Deserialize an objectgithub :: GithubAPI :: enable_cache=
Enable caching for this client.github :: GithubAPI :: get_auth_user
Get the Github logged user fromauth
token.
github :: GithubAPI :: get_branch
Get the Github branch withname
.
github :: GithubAPI :: get_commit
Get the Github commit withsha
.
github :: GithubAPI :: get_commit_comment
Get the Github commit comment withid
.
github :: GithubAPI :: get_commit_status
Get the status of a commitgithub :: GithubAPI :: get_issue_comment
Get the Github issue comment withid
.
github :: GithubAPI :: get_issue_comments
List of event on this issue.github :: GithubAPI :: get_issue_event
Get the Github issue event withid
.
github :: GithubAPI :: get_issue_events
List of events on this issue.github :: GithubAPI :: get_milestone
Get the Github milestone withid
.
github :: GithubAPI :: get_pull_comment
Get a specific pull request commentgithub :: GithubAPI :: get_pull_comments
List of comments on a pull requestgithub :: GithubAPI :: get_repo_branches
List of repo branches.github :: GithubAPI :: get_repo_contrib_stats
List of contributor related statistics.github :: GithubAPI :: get_repo_issues
List of issues associated with their ids.github :: GithubAPI :: get_repo_labels
List of labels associated with their names.github :: GithubAPI :: get_repo_milestones
List of milestones associated with their ids.github :: GithubAPI :: get_repo_pulls
List of pull-requests associated with their ids.github :: MockGithubAPI :: has_response
Doesself
have a mock response for Github path
?
core :: Object :: is_same_instance
Return true ifself
and other
are the same instance (i.e. same identity).
core :: Object :: is_same_serialized
Isself
the same as other
in a serialization context?
core :: Object :: is_same_type
Return true ifself
and other
have the same dynamic type.
github :: GithubAPI :: last_error
Last error occured during Github API communications.github :: GithubAPI :: last_error=
Last error occured during Github API communications.core :: Object :: output_class_name
Display class name on stdout (debug only).github :: MockGithubAPI :: response_code
Status code of a simulated errorgithub :: MockGithubAPI :: response_file
Returns the response file path for a Githubpath
github :: MockGithubAPI :: response_is_error
Is this response a simulated error?github :: MockGithubAPI :: response_string
Returns the response body string for a Githubpath
github :: MockGithubAPI :: responses_dir=
Root responses cache directorygithub :: GithubAPI :: search_repo_issues
Search issues in this repo form an advanced query.github :: MockGithubAPI :: update_responses_cache=
Activate cachinggithub :: GithubAPI :: user_agent=
User agent used for HTTP requests.github :: GithubAPI :: valid_tokens=
Tokens mocked as validgithub :: GithubAPI :: was_error=
Does the last request provoqued an error?
# 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 MockGithubAPI
super GithubAPI
# Mock so it returns the response from a file
#
# See `update_responses_cache`.
redef fun send(method, path, headers, body) do
print path # for debugging
assert has_response(path)
if update_responses_cache then
var file = response_file(path)
save_actual_response(path, file)
end
var response = response_string(path)
if response_is_error(path) then
last_error = new GithubAPIError(
response.parse_json.as(JsonObject)["message"].as(String),
response_code(path).to_i,
path
)
was_error = true
return null
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?page=1&per_page=3"] = "repo_labels_nit"
map["/repos/nitlang/nit/labels/ok_will_merge"] = "repo_labels_ok_will_merge"
map["/repos/nitlang/nit/milestones?page=1&per_page=3"] = "repo_milestones_nit"
map["/repos/nitlang/nit/milestones/4"] = "repo_milestones_4"
map["/repos/nitlang/nit/branches?page=1&per_page=2"] = "repo_branches_nit"
map["/repos/nitlang/nit/branches/master"] = "repo_branches_master"
map["/repos/nitlang/nit/issues?page=1&per_page=3"] = "repo_issues_nit"
map["/repos/nitlang/nit/issues/1000"] = "repo_issues_1000"
map["/repos/nitlang/nit/issues/1000/comments?page=1&per_page=3"] = "repo_issues_comments_nit"
map["/repos/nitlang/nit/issues/comments/6020149"] = "repo_issues_comments_6020149"
map["/repos/nitlang/nit/issues/1000/events?page=1&per_page=3"] = "repo_issues_events_nit"
map["/repos/nitlang/nit/issues/events/199674194"] = "repo_issues_events_199674194"
map["/repos/nitlang/nit/pulls?page=1&per_page=3"] = "repo_pulls_nit"
map["/repos/nitlang/nit/pulls/1000"] = "repo_pulls_1000"
map["/repos/nitlang/nit/pulls/945/comments?page=1&per_page=3"] = "repo_pulls_945_comments"
map["/repos/nitlang/nit/pulls/comments/21010363"] = "repo_pulls_comment_21010363"
map["/repos/nitlang/nit/commits/64ce1f"] = "repo_commits_64ce1f"
map["/repos/nitlang/nit/commits/4e3c688d/status"] = "repo_commits_4e3c68_status"
map["/repos/nitlang/nit/comments/8982707"] = "repo_comments_8982707"
map["/search/issues?q=foo repo:nitlang/nit&page=1&per_page=3"] = "repo_search_issues_nit"
map["/repos/nitlang/nit/stats/contributors"] = "repo_nit_contributors"
# 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("{api_url}{sanitize_uri(uri)}")
request.user_agent = actual_api.user_agent
request.headers = actual_api.new_headers
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_api = new GithubAPI(get_github_oauth, "nitunit")
end
lib/github/tests/test_api.nit:19,1--155,3