diff options
author | Nejc Habjan <hab.nejc@gmail.com> | 2020-04-17 02:26:28 +0200 |
---|---|---|
committer | Nejc Habjan <nejc.habjan@siemens.com> | 2020-08-22 20:09:52 +0200 |
commit | 76b2cadf1418e4ea2ac420ebba5a4b4f16fbd4c7 (patch) | |
tree | 4dbe6ae57c4f03e1351f7a49e590cbbc6d31121a /gitlab/tests/objects | |
parent | 11383e70f74c70e6fe8a56f18b5b170db982f402 (diff) | |
download | gitlab-76b2cadf1418e4ea2ac420ebba5a4b4f16fbd4c7.tar.gz |
refactor: split unit tests by GitLab API resources
Diffstat (limited to 'gitlab/tests/objects')
-rw-r--r-- | gitlab/tests/objects/test_application.py | 226 | ||||
-rw-r--r-- | gitlab/tests/objects/test_commits.py | 74 | ||||
-rw-r--r-- | gitlab/tests/objects/test_deploy_tokens.py | 44 | ||||
-rw-r--r-- | gitlab/tests/objects/test_deployments.py | 53 | ||||
-rw-r--r-- | gitlab/tests/objects/test_environments.py | 31 | ||||
-rw-r--r-- | gitlab/tests/objects/test_groups.py | 121 | ||||
-rw-r--r-- | gitlab/tests/objects/test_hooks.py | 23 | ||||
-rw-r--r-- | gitlab/tests/objects/test_issues.py | 42 | ||||
-rw-r--r-- | gitlab/tests/objects/test_pipeline_schedules.py | 71 | ||||
-rw-r--r-- | gitlab/tests/objects/test_project_import_export.py | 129 | ||||
-rw-r--r-- | gitlab/tests/objects/test_project_statistics.py | 29 | ||||
-rw-r--r-- | gitlab/tests/objects/test_projects.py | 718 | ||||
-rw-r--r-- | gitlab/tests/objects/test_remote_mirrors.py | 103 | ||||
-rw-r--r-- | gitlab/tests/objects/test_services.py | 134 | ||||
-rw-r--r-- | gitlab/tests/objects/test_snippets.py | 121 | ||||
-rw-r--r-- | gitlab/tests/objects/test_submodules.py | 58 | ||||
-rw-r--r-- | gitlab/tests/objects/test_todos.py | 58 | ||||
-rw-r--r-- | gitlab/tests/objects/test_users.py | 94 |
18 files changed, 1379 insertions, 750 deletions
diff --git a/gitlab/tests/objects/test_application.py b/gitlab/tests/objects/test_application.py index a10691b..356f0d3 100644 --- a/gitlab/tests/objects/test_application.py +++ b/gitlab/tests/objects/test_application.py @@ -1,120 +1,108 @@ -import unittest -import gitlab -import os -import pickle -import tempfile +""" +GitLab API: https://docs.gitlab.com/ce/api/applications.html +""" + import json -import unittest -import requests -from gitlab import * # noqa -from gitlab.v4.objects import * # noqa -from httmock import HTTMock, urlmatch, response # noqa - - -headers = {"content-type": "application/json"} - - -class TestApplicationAppearance(unittest.TestCase): - def setUp(self): - self.gl = Gitlab( - "http://localhost", - private_token="private_token", - ssl_verify=True, - api_version="4", - ) - self.title = "GitLab Test Instance" - self.new_title = "new-title" - self.description = "gitlab-test.example.com" - self.new_description = "new-description" - - def test_get_update_appearance(self): - @urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/application/appearance", - method="get", - ) - def resp_get_appearance(url, request): - content = """{ - "title": "%s", - "description": "%s", - "logo": "/uploads/-/system/appearance/logo/1/logo.png", - "header_logo": "/uploads/-/system/appearance/header_logo/1/header.png", - "favicon": "/uploads/-/system/appearance/favicon/1/favicon.png", - "new_project_guidelines": "Please read the FAQs for help.", - "header_message": "", - "footer_message": "", - "message_background_color": "#e75e40", - "message_font_color": "#ffffff", - "email_header_and_footer_enabled": false}""" % ( - self.title, - self.description, - ) - content = content.encode("utf-8") - return response(200, content, headers, None, 25, request) - - @urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/application/appearance", - method="put", - ) - def resp_update_appearance(url, request): - content = """{ - "title": "%s", - "description": "%s", - "logo": "/uploads/-/system/appearance/logo/1/logo.png", - "header_logo": "/uploads/-/system/appearance/header_logo/1/header.png", - "favicon": "/uploads/-/system/appearance/favicon/1/favicon.png", - "new_project_guidelines": "Please read the FAQs for help.", - "header_message": "", - "footer_message": "", - "message_background_color": "#e75e40", - "message_font_color": "#ffffff", - "email_header_and_footer_enabled": false}""" % ( - self.new_title, - self.new_description, - ) - content = content.encode("utf-8") - return response(200, content, headers, None, 25, request) - - with HTTMock(resp_get_appearance), HTTMock(resp_update_appearance): - appearance = self.gl.appearance.get() - assert appearance.title == self.title - assert appearance.description == self.description - appearance.title = self.new_title - appearance.description = self.new_description - appearance.save() - assert appearance.title == self.new_title - assert appearance.description == self.new_description - - def test_update_appearance(self): - @urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/application/appearance", - method="put", - ) - def resp_update_appearance(url, request): - content = """{ - "title": "%s", - "description": "%s", - "logo": "/uploads/-/system/appearance/logo/1/logo.png", - "header_logo": "/uploads/-/system/appearance/header_logo/1/header.png", - "favicon": "/uploads/-/system/appearance/favicon/1/favicon.png", - "new_project_guidelines": "Please read the FAQs for help.", - "header_message": "", - "footer_message": "", - "message_background_color": "#e75e40", - "message_font_color": "#ffffff", - "email_header_and_footer_enabled": false}""" % ( - self.new_title, - self.new_description, - ) - content = content.encode("utf-8") - return response(200, content, headers, None, 25, request) - - with HTTMock(resp_update_appearance): - resp = self.gl.appearance.update( - title=self.new_title, description=self.new_description - ) + +from httmock import urlmatch, response, with_httmock # noqa + +from .mocks import headers + + +title = "GitLab Test Instance" +description = "gitlab-test.example.com" +new_title = "new-title" +new_description = "new-description" + + +@urlmatch( + scheme="http", netloc="localhost", path="/api/v4/applications", method="post", +) +def resp_application_create(url, request): + content = '{"name": "test_app", "redirect_uri": "http://localhost:8080", "scopes": ["api", "email"]}' + json_content = json.loads(content) + return response(200, json_content, headers, None, 5, request) + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/application/appearance", + method="get", +) +def resp_get_appearance(url, request): + content = """{ + "title": "%s", + "description": "%s", + "logo": "/uploads/-/system/appearance/logo/1/logo.png", + "header_logo": "/uploads/-/system/appearance/header_logo/1/header.png", + "favicon": "/uploads/-/system/appearance/favicon/1/favicon.png", + "new_project_guidelines": "Please read the FAQs for help.", + "header_message": "", + "footer_message": "", + "message_background_color": "#e75e40", + "message_font_color": "#ffffff", + "email_header_and_footer_enabled": false}""" % ( + title, + description, + ) + content = content.encode("utf-8") + return response(200, content, headers, None, 25, request) + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/application/appearance", + method="put", +) +def resp_update_appearance(url, request): + content = """{ + "title": "%s", + "description": "%s", + "logo": "/uploads/-/system/appearance/logo/1/logo.png", + "header_logo": "/uploads/-/system/appearance/header_logo/1/header.png", + "favicon": "/uploads/-/system/appearance/favicon/1/favicon.png", + "new_project_guidelines": "Please read the FAQs for help.", + "header_message": "", + "footer_message": "", + "message_background_color": "#e75e40", + "message_font_color": "#ffffff", + "email_header_and_footer_enabled": false}""" % ( + new_title, + new_description, + ) + content = content.encode("utf-8") + return response(200, content, headers, None, 25, request) + + +@with_httmock(resp_application_create) +def test_create_application(gl): + application = gl.applications.create( + { + "name": "test_app", + "redirect_uri": "http://localhost:8080", + "scopes": ["api", "email"], + "confidential": False, + } + ) + assert application.name == "test_app" + assert application.redirect_uri == "http://localhost:8080" + assert application.scopes == ["api", "email"] + + +@with_httmock(resp_get_appearance, resp_update_appearance) +def test_get_update_appearance(gl): + appearance = gl.appearance.get() + assert appearance.title == title + assert appearance.description == description + appearance.title = new_title + appearance.description = new_description + appearance.save() + assert appearance.title == new_title + assert appearance.description == new_description + + +@with_httmock(resp_update_appearance) +def test_update_application_appearance(gl): + resp = gl.appearance.update(title=new_title, description=new_description) diff --git a/gitlab/tests/objects/test_commits.py b/gitlab/tests/objects/test_commits.py index bf7d5a8..eaa7b82 100644 --- a/gitlab/tests/objects/test_commits.py +++ b/gitlab/tests/objects/test_commits.py @@ -1,7 +1,10 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/commits.html +""" + from httmock import urlmatch, response, with_httmock from .mocks import headers -from .test_projects import TestProject @urlmatch( @@ -69,39 +72,36 @@ def resp_get_commit_gpg_signature(url, request): return response(200, content, headers, None, 5, request) -class TestCommit(TestProject): - """ - Base class for commit tests. Inherits from TestProject, - since currently all commit methods are under projects. - """ - - @with_httmock(resp_get_commit) - def test_get_commit(self): - commit = self.project.commits.get("6b2257ea") - assert commit.short_id == "6b2257ea" - assert commit.title == "Initial commit" - - @with_httmock(resp_create_commit) - def test_create_commit(self): - data = { - "branch": "master", - "commit_message": "Commit message", - "actions": [{"action": "create", "file_path": "README", "content": "",}], - } - commit = self.project.commits.create(data) - assert commit.short_id == "ed899a2f" - assert commit.title == data["commit_message"] - - @with_httmock(resp_revert_commit) - def test_revert_commit(self): - commit = self.project.commits.get("6b2257ea", lazy=True) - revert_commit = commit.revert(branch="master") - assert revert_commit["short_id"] == "8b090c1b" - assert revert_commit["title"] == 'Revert "Initial commit"' - - @with_httmock(resp_get_commit_gpg_signature) - def test_get_commit_gpg_signature(self): - commit = self.project.commits.get("6b2257ea", lazy=True) - signature = commit.signature() - assert signature["gpg_key_primary_keyid"] == "8254AAB3FBD54AC9" - assert signature["verification_status"] == "verified" +@with_httmock(resp_get_commit) +def test_get_commit(project): + commit = project.commits.get("6b2257ea") + assert commit.short_id == "6b2257ea" + assert commit.title == "Initial commit" + + +@with_httmock(resp_create_commit) +def test_create_commit(project): + data = { + "branch": "master", + "commit_message": "Commit message", + "actions": [{"action": "create", "file_path": "README", "content": "",}], + } + commit = project.commits.create(data) + assert commit.short_id == "ed899a2f" + assert commit.title == data["commit_message"] + + +@with_httmock(resp_revert_commit) +def test_revert_commit(project): + commit = project.commits.get("6b2257ea", lazy=True) + revert_commit = commit.revert(branch="master") + assert revert_commit["short_id"] == "8b090c1b" + assert revert_commit["title"] == 'Revert "Initial commit"' + + +@with_httmock(resp_get_commit_gpg_signature) +def test_get_commit_gpg_signature(project): + commit = project.commits.get("6b2257ea", lazy=True) + signature = commit.signature() + assert signature["gpg_key_primary_keyid"] == "8254AAB3FBD54AC9" + assert signature["verification_status"] == "verified" diff --git a/gitlab/tests/objects/test_deploy_tokens.py b/gitlab/tests/objects/test_deploy_tokens.py new file mode 100644 index 0000000..b98a670 --- /dev/null +++ b/gitlab/tests/objects/test_deploy_tokens.py @@ -0,0 +1,44 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/deploy_tokens.html +""" + +from httmock import response, urlmatch, with_httmock + +from gitlab.v4.objects import ProjectDeployToken + +from .mocks import headers + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/deploy_tokens", + method="post", +) +def resp_deploy_token_create(url, request): + content = """{ + "id": 1, + "name": "test_deploy_token", + "username": "custom-user", + "expires_at": "2022-01-01T00:00:00.000Z", + "token": "jMRvtPNxrn3crTAGukpZ", + "scopes": [ "read_repository" ]}""" + content = content.encode("utf-8") + return response(200, content, headers, None, 5, request) + + +@with_httmock(resp_deploy_token_create) +def test_deploy_tokens(gl): + deploy_token = gl.projects.get(1, lazy=True).deploytokens.create( + { + "name": "test_deploy_token", + "expires_at": "2022-01-01T00:00:00.000Z", + "username": "custom-user", + "scopes": ["read_repository"], + } + ) + assert isinstance(deploy_token, ProjectDeployToken) + assert deploy_token.id == 1 + assert deploy_token.expires_at == "2022-01-01T00:00:00.000Z" + assert deploy_token.username == "custom-user" + assert deploy_token.scopes == ["read_repository"] diff --git a/gitlab/tests/objects/test_deployments.py b/gitlab/tests/objects/test_deployments.py new file mode 100644 index 0000000..098251a --- /dev/null +++ b/gitlab/tests/objects/test_deployments.py @@ -0,0 +1,53 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/deployments.html +""" + +import json + +from httmock import response, urlmatch, with_httmock + +from .mocks import headers + +content = '{"id": 42, "status": "success", "ref": "master"}' +json_content = json.loads(content) + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/deployments", + method="post", +) +def resp_deployment_create(url, request): + return response(200, json_content, headers, None, 5, request) + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/deployments/42", + method="put", +) +def resp_deployment_update(url, request): + return response(200, json_content, headers, None, 5, request) + + +@with_httmock(resp_deployment_create, resp_deployment_update) +def test_deployment(project): + deployment = project.deployments.create( + { + "environment": "Test", + "sha": "1agf4gs", + "ref": "master", + "tag": False, + "status": "created", + } + ) + assert deployment.id == 42 + assert deployment.status == "success" + assert deployment.ref == "master" + + json_content["status"] = "failed" + deployment.status = "failed" + deployment.save() + assert deployment.status == "failed" diff --git a/gitlab/tests/objects/test_environments.py b/gitlab/tests/objects/test_environments.py new file mode 100644 index 0000000..3175c64 --- /dev/null +++ b/gitlab/tests/objects/test_environments.py @@ -0,0 +1,31 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/environments.html +""" + +from httmock import response, urlmatch, with_httmock + +from gitlab.v4.objects import ProjectEnvironment + +from .mocks import headers + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/environments/1", + method="get", +) +def resp_get_environment(url, request): + content = '{"name": "environment_name", "id": 1, "last_deployment": "sometime"}'.encode( + "utf-8" + ) + return response(200, content, headers, None, 5, request) + + +@with_httmock(resp_get_environment) +def test_project_environments(project): + environment = project.environments.get(1) + assert isinstance(environment, ProjectEnvironment) + assert environment.id == 1 + assert environment.last_deployment == "sometime" + assert environment.name == "environment_name" diff --git a/gitlab/tests/objects/test_groups.py b/gitlab/tests/objects/test_groups.py index 12ebdb2..b5464b5 100644 --- a/gitlab/tests/objects/test_groups.py +++ b/gitlab/tests/objects/test_groups.py @@ -1,4 +1,8 @@ -import unittest +""" +GitLab API: https://docs.gitlab.com/ce/api/groups.html +""" + +import pytest from httmock import response, urlmatch, with_httmock @@ -36,66 +40,55 @@ def resp_create_import(url, request): return response(202, content, headers, None, 25, request) -class TestGroup(unittest.TestCase): - def setUp(self): - self.gl = gitlab.Gitlab( - "http://localhost", - private_token="private_token", - ssl_verify=True, - api_version=4, - ) - - @with_httmock(resp_get_group) - def test_get_group(self): - data = self.gl.groups.get(1) - assert isinstance(data, gitlab.v4.objects.Group) - assert data.name == "name" - assert data.path == "path" - assert data.id == 1 - - @with_httmock(resp_create_group) - def test_create_group(self): - name, path = "name", "path" - data = self.gl.groups.create({"name": name, "path": path}) - assert isinstance(data, gitlab.v4.objects.Group) - assert data.name == name - assert data.path == path - - -class TestGroupExport(TestGroup): - def setUp(self): - super(TestGroupExport, self).setUp() - self.group = self.gl.groups.get(1, lazy=True) - - @with_httmock(resp_create_export) - def test_create_group_export(self): - export = self.group.exports.create() - assert export.message == "202 Accepted" - - @unittest.skip("GitLab API endpoint not implemented") - @with_httmock(resp_create_export) - def test_refresh_group_export_status(self): - export = self.group.exports.create() - export.refresh() - assert export.export_status == "finished" - - @with_httmock(resp_create_export, resp_download_export) - def test_download_group_export(self): - export = self.group.exports.create() - download = export.download() - assert isinstance(download, bytes) - assert download == binary_content - - -class TestGroupImport(TestGroup): - @with_httmock(resp_create_import) - def test_import_group(self): - group_import = self.gl.groups.import_group("file", "api-group", "API Group") - assert group_import["message"] == "202 Accepted" - - @unittest.skip("GitLab API endpoint not implemented") - @with_httmock(resp_create_import) - def test_refresh_group_import_status(self): - group_import = self.group.imports.get() - group_import.refresh() - assert group_import.import_status == "finished" +@with_httmock(resp_get_group) +def test_get_group(gl): + data = gl.groups.get(1) + assert isinstance(data, gitlab.v4.objects.Group) + assert data.name == "name" + assert data.path == "path" + assert data.id == 1 + + +@with_httmock(resp_create_group) +def test_create_group(gl): + name, path = "name", "path" + data = gl.groups.create({"name": name, "path": path}) + assert isinstance(data, gitlab.v4.objects.Group) + assert data.name == name + assert data.path == path + + +@with_httmock(resp_create_export) +def test_create_group_export(group): + export = group.exports.create() + assert export.message == "202 Accepted" + + +@pytest.mark.skip("GitLab API endpoint not implemented") +@with_httmock(resp_create_export) +def test_refresh_group_export_status(group): + export = group.exports.create() + export.refresh() + assert export.export_status == "finished" + + +@with_httmock(resp_create_export, resp_download_export) +def test_download_group_export(group): + export = group.exports.create() + download = export.download() + assert isinstance(download, bytes) + assert download == binary_content + + +@with_httmock(resp_create_import) +def test_import_group(gl): + group_import = gl.groups.import_group("file", "api-group", "API Group") + assert group_import["message"] == "202 Accepted" + + +@pytest.mark.skip("GitLab API endpoint not implemented") +@with_httmock(resp_create_import) +def test_refresh_group_import_status(group): + group_import = group.imports.get() + group_import.refresh() + assert group_import.import_status == "finished" diff --git a/gitlab/tests/objects/test_hooks.py b/gitlab/tests/objects/test_hooks.py new file mode 100644 index 0000000..45403c4 --- /dev/null +++ b/gitlab/tests/objects/test_hooks.py @@ -0,0 +1,23 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/system_hooks.html +""" + +from httmock import response, urlmatch, with_httmock + +from gitlab.v4.objects import Hook + +from .mocks import headers + + +@urlmatch(scheme="http", netloc="localhost", path="/api/v4/hooks/1", method="get") +def resp_get_hook(url, request): + content = '{"url": "testurl", "id": 1}'.encode("utf-8") + return response(200, content, headers, None, 5, request) + + +@with_httmock(resp_get_hook) +def test_hooks(gl): + data = gl.hooks.get(1) + assert isinstance(data, Hook) + assert data.url == "testurl" + assert data.id == 1 diff --git a/gitlab/tests/objects/test_issues.py b/gitlab/tests/objects/test_issues.py new file mode 100644 index 0000000..e094841 --- /dev/null +++ b/gitlab/tests/objects/test_issues.py @@ -0,0 +1,42 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/issues.html +""" + +from httmock import urlmatch, response, with_httmock + +from .mocks import headers +from gitlab.v4.objects import ProjectIssuesStatistics + + +@urlmatch(scheme="http", netloc="localhost", path="/api/v4/issues", method="get") +def resp_get_issue(url, request): + content = '[{"name": "name", "id": 1}, ' '{"name": "other_name", "id": 2}]' + content = content.encode("utf-8") + return response(200, content, headers, None, 5, request) + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/issues_statistics", + method="get", +) +def resp_get_environment(url, request): + content = """{"statistics": {"counts": {"all": 20, "closed": 5, "opened": 15}}}""".encode( + "utf-8" + ) + return response(200, content, headers, None, 5, request) + + +@with_httmock(resp_get_issue) +def test_issues(gl): + data = gl.issues.list() + assert data[1].id == 2 + assert data[1].name == "other_name" + + +@with_httmock(resp_get_environment) +def test_project_issues_statistics(project): + statistics = project.issuesstatistics.get() + assert isinstance(statistics, ProjectIssuesStatistics) + assert statistics.statistics["counts"]["all"] == 20 diff --git a/gitlab/tests/objects/test_pipeline_schedules.py b/gitlab/tests/objects/test_pipeline_schedules.py new file mode 100644 index 0000000..6b56304 --- /dev/null +++ b/gitlab/tests/objects/test_pipeline_schedules.py @@ -0,0 +1,71 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/pipeline_schedules.html +""" + +from httmock import response, urlmatch, with_httmock + +from .mocks import headers + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/pipeline_schedules$", + method="post", +) +def resp_create_project_pipeline_schedule(url, request): + """Mock for creating project pipeline Schedules POST response.""" + content = """{ + "id": 14, + "description": "Build packages", + "ref": "master", + "cron": "0 1 * * 5", + "cron_timezone": "UTC", + "next_run_at": "2017-05-26T01:00:00.000Z", + "active": true, + "created_at": "2017-05-19T13:43:08.169Z", + "updated_at": "2017-05-19T13:43:08.169Z", + "last_pipeline": null, + "owner": { + "name": "Administrator", + "username": "root", + "id": 1, + "state": "active", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "https://gitlab.example.com/root" + } +}""" + content = content.encode("utf-8") + return response(200, content, headers, None, 5, request) + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/pipeline_schedules/14/play", + method="post", +) +def resp_play_project_pipeline_schedule(url, request): + """Mock for playing a project pipeline schedule POST response.""" + content = """{"message": "201 Created"}""" + content = content.encode("utf-8") + return response(200, content, headers, None, 5, request) + + +@with_httmock( + resp_create_project_pipeline_schedule, resp_play_project_pipeline_schedule +) +def test_project_pipeline_schedule_play(project): + description = "Build packages" + cronline = "0 1 * * 5" + sched = project.pipelineschedules.create( + {"ref": "master", "description": description, "cron": cronline} + ) + assert sched is not None + assert description == sched.description + assert cronline == sched.cron + + play_result = sched.play() + assert play_result is not None + assert "message" in play_result + assert play_result["message"] == "201 Created" diff --git a/gitlab/tests/objects/test_project_import_export.py b/gitlab/tests/objects/test_project_import_export.py new file mode 100644 index 0000000..e5c37a8 --- /dev/null +++ b/gitlab/tests/objects/test_project_import_export.py @@ -0,0 +1,129 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/project_import_export.html +""" + +from httmock import response, urlmatch, with_httmock + +from .mocks import * + + +@urlmatch( + scheme="http", netloc="localhost", path="/api/v4/projects/1/export", method="get", +) +def resp_export_status(url, request): + """Mock for Project Export GET response.""" + content = """{ + "id": 1, + "description": "Itaque perspiciatis minima aspernatur", + "name": "Gitlab Test", + "name_with_namespace": "Gitlab Org / Gitlab Test", + "path": "gitlab-test", + "path_with_namespace": "gitlab-org/gitlab-test", + "created_at": "2017-08-29T04:36:44.383Z", + "export_status": "finished", + "_links": { + "api_url": "https://gitlab.test/api/v4/projects/1/export/download", + "web_url": "https://gitlab.test/gitlab-test/download_export" + } + } + """ + content = content.encode("utf-8") + return response(200, content, headers, None, 25, request) + + +@urlmatch( + scheme="http", netloc="localhost", path="/api/v4/projects/import", method="post", +) +def resp_import_project(url, request): + """Mock for Project Import POST response.""" + content = """{ + "id": 1, + "description": null, + "name": "api-project", + "name_with_namespace": "Administrator / api-project", + "path": "api-project", + "path_with_namespace": "root/api-project", + "created_at": "2018-02-13T09:05:58.023Z", + "import_status": "scheduled" + }""" + content = content.encode("utf-8") + return response(200, content, headers, None, 25, request) + + +@urlmatch( + scheme="http", netloc="localhost", path="/api/v4/projects/1/import", method="get", +) +def resp_import_status(url, request): + """Mock for Project Import GET response.""" + content = """{ + "id": 1, + "description": "Itaque perspiciatis minima aspernatur corporis consequatur.", + "name": "Gitlab Test", + "name_with_namespace": "Gitlab Org / Gitlab Test", + "path": "gitlab-test", + "path_with_namespace": "gitlab-org/gitlab-test", + "created_at": "2017-08-29T04:36:44.383Z", + "import_status": "finished" + }""" + content = content.encode("utf-8") + return response(200, content, headers, None, 25, request) + + +@urlmatch( + scheme="http", netloc="localhost", path="/api/v4/import/github", method="post", +) +def resp_import_github(url, request): + """Mock for GitHub Project Import POST response.""" + content = """{ + "id": 27, + "name": "my-repo", + "full_path": "/root/my-repo", + "full_name": "Administrator / my-repo" + }""" + content = content.encode("utf-8") + return response(200, content, headers, None, 25, request) + + +@with_httmock(resp_import_project) +def test_import_project(gl): + project_import = gl.projects.import_project("file", "api-project") + assert project_import["import_status"] == "scheduled" + + +@with_httmock(resp_import_status) +def test_refresh_project_import_status(project): + project_import = project.imports.get() + project_import.refresh() + assert project_import.import_status == "finished" + + +@with_httmock(resp_import_github) +def test_import_github(gl): + base_path = "/root" + name = "my-repo" + ret = gl.projects.import_github("githubkey", 1234, base_path, name) + assert isinstance(ret, dict) + assert ret["name"] == name + assert ret["full_path"] == "/".join((base_path, name)) + assert ret["full_name"].endswith(name) + + +@with_httmock(resp_create_export) +def test_create_project_export(project): + export = project.exports.create() + assert export.message == "202 Accepted" + + +@with_httmock(resp_create_export, resp_export_status) +def test_refresh_project_export_status(project): + export = project.exports.create() + export.refresh() + assert export.export_status == "finished" + + +@with_httmock(resp_create_export, resp_download_export) +def test_download_project_export(project): + export = project.exports.create() + download = export.download() + assert isinstance(download, bytes) + assert download == binary_content diff --git a/gitlab/tests/objects/test_project_statistics.py b/gitlab/tests/objects/test_project_statistics.py new file mode 100644 index 0000000..c2b194f --- /dev/null +++ b/gitlab/tests/objects/test_project_statistics.py @@ -0,0 +1,29 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/project_statistics.html +""" + +from httmock import response, urlmatch, with_httmock + +from gitlab.v4.objects import ProjectAdditionalStatistics + +from .mocks import headers + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/statistics", + method="get", +) +def resp_get_statistics(url, request): + content = """{"fetches": {"total": 50, "days": [{"count": 10, "date": "2018-01-10"}]}}""".encode( + "utf-8" + ) + return response(200, content, headers, None, 5, request) + + +@with_httmock(resp_get_statistics) +def test_project_additional_statistics(project): + statistics = project.additionalstatistics.get() + assert isinstance(statistics, ProjectAdditionalStatistics) + assert statistics.fetches["total"] == 50 diff --git a/gitlab/tests/objects/test_projects.py b/gitlab/tests/objects/test_projects.py index fa105ae..7fefe3f 100644 --- a/gitlab/tests/objects/test_projects.py +++ b/gitlab/tests/objects/test_projects.py @@ -1,547 +1,205 @@ -import unittest -import gitlab -import os -import pickle -import tempfile -import json -import unittest -import requests -from gitlab import * # noqa -from gitlab.v4.objects import * # noqa -from httmock import HTTMock, urlmatch, response, with_httmock # noqa - -from .mocks import * # noqa - - -@urlmatch( - scheme="http", netloc="localhost", path="/api/v4/projects/1/export", method="get", -) -def resp_export_status(url, request): - """Mock for Project Export GET response.""" - content = """{ - "id": 1, - "description": "Itaque perspiciatis minima aspernatur", - "name": "Gitlab Test", - "name_with_namespace": "Gitlab Org / Gitlab Test", - "path": "gitlab-test", - "path_with_namespace": "gitlab-org/gitlab-test", - "created_at": "2017-08-29T04:36:44.383Z", - "export_status": "finished", - "_links": { - "api_url": "https://gitlab.test/api/v4/projects/1/export/download", - "web_url": "https://gitlab.test/gitlab-test/download_export" - } - } - """ - content = content.encode("utf-8") - return response(200, content, headers, None, 25, request) - - -@urlmatch( - scheme="http", netloc="localhost", path="/api/v4/projects/import", method="post", -) -def resp_import_project(url, request): - """Mock for Project Import POST response.""" - content = """{ - "id": 1, - "description": null, - "name": "api-project", - "name_with_namespace": "Administrator / api-project", - "path": "api-project", - "path_with_namespace": "root/api-project", - "created_at": "2018-02-13T09:05:58.023Z", - "import_status": "scheduled" - }""" - content = content.encode("utf-8") - return response(200, content, headers, None, 25, request) - - -@urlmatch( - scheme="http", netloc="localhost", path="/api/v4/projects/1/import", method="get", -) -def resp_import_status(url, request): - """Mock for Project Import GET response.""" - content = """{ - "id": 1, - "description": "Itaque perspiciatis minima aspernatur corporis consequatur.", - "name": "Gitlab Test", - "name_with_namespace": "Gitlab Org / Gitlab Test", - "path": "gitlab-test", - "path_with_namespace": "gitlab-org/gitlab-test", - "created_at": "2017-08-29T04:36:44.383Z", - "import_status": "finished" - }""" - content = content.encode("utf-8") - return response(200, content, headers, None, 25, request) - - -@urlmatch( - scheme="http", netloc="localhost", path="/api/v4/import/github", method="post", -) -def resp_import_github(url, request): - """Mock for GitHub Project Import POST response.""" - content = """{ - "id": 27, - "name": "my-repo", - "full_path": "/root/my-repo", - "full_name": "Administrator / my-repo" - }""" - content = content.encode("utf-8") - return response(200, content, headers, None, 25, request) - - -@urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/projects/1/remote_mirrors", - method="get", -) -def resp_get_remote_mirrors(url, request): - """Mock for Project Remote Mirrors GET response.""" - content = """[ - { - "enabled": true, - "id": 101486, - "last_error": null, - "last_successful_update_at": "2020-01-06T17:32:02.823Z", - "last_update_at": "2020-01-06T17:32:02.823Z", - "last_update_started_at": "2020-01-06T17:31:55.864Z", - "only_protected_branches": true, - "update_status": "finished", - "url": "https://*****:*****@gitlab.com/gitlab-org/security/gitlab.git" - } - ]""" - content = content.encode("utf-8") - return response(200, content, headers, None, 5, request) +""" +GitLab API: https://docs.gitlab.com/ce/api/projects.html +""" +import pytest -@urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/projects/1/remote_mirrors", - method="post", -) -def resp_create_remote_mirror(url, request): - """Mock for Project Remote Mirrors POST response.""" - content = """{ - "enabled": false, - "id": 101486, - "last_error": null, - "last_successful_update_at": null, - "last_update_at": null, - "last_update_started_at": null, - "only_protected_branches": false, - "update_status": "none", - "url": "https://*****:*****@example.com/gitlab/example.git" - }""" - content = content.encode("utf-8") - return response(200, content, headers, None, 5, request) +from gitlab.v4.objects import Project +from httmock import urlmatch, response, with_httmock -@urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/projects/1/remote_mirrors/1", - method="put", -) -def resp_update_remote_mirror(url, request): - """Mock for Project Remote Mirrors PUT response.""" - content = """{ - "enabled": false, - "id": 101486, - "last_error": null, - "last_successful_update_at": "2020-01-06T17:32:02.823Z", - "last_update_at": "2020-01-06T17:32:02.823Z", - "last_update_started_at": "2020-01-06T17:31:55.864Z", - "only_protected_branches": true, - "update_status": "finished", - "url": "https://*****:*****@gitlab.com/gitlab-org/security/gitlab.git" - }""" - content = content.encode("utf-8") - return response(200, content, headers, None, 5, request) +from .mocks import headers -@urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/projects/1/services/pipelines-email", - method="put", -) -def resp_update_service(url, request): - """Mock for Service update PUT response.""" - content = """{ - "id": 100152, - "title": "Pipelines emails", - "slug": "pipelines-email", - "created_at": "2019-01-14T08:46:43.637+01:00", - "updated_at": "2019-07-01T14:10:36.156+02:00", - "active": true, - "commit_events": true, - "push_events": true, - "issues_events": true, - "confidential_issues_events": true, - "merge_requests_events": true, - "tag_push_events": true, - "note_events": true, - "confidential_note_events": true, - "pipeline_events": true, - "wiki_page_events": true, - "job_events": true, - "comment_on_event_enabled": true, - "project_id": 1 - }""" - content = content.encode("utf-8") +@urlmatch(scheme="http", netloc="localhost", path="/api/v4/projects/1", method="get") +def resp_get_project(url, request): + content = '{"name": "name", "id": 1}'.encode("utf-8") return response(200, content, headers, None, 5, request) -@urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/projects/1/services/pipelines-email", - method="get", -) -def resp_get_service(url, request): - """Mock for Service GET response.""" - content = """{ - "id": 100152, - "title": "Pipelines emails", - "slug": "pipelines-email", - "created_at": "2019-01-14T08:46:43.637+01:00", - "updated_at": "2019-07-01T14:10:36.156+02:00", - "active": true, - "commit_events": true, - "push_events": true, - "issues_events": true, - "confidential_issues_events": true, - "merge_requests_events": true, - "tag_push_events": true, - "note_events": true, - "confidential_note_events": true, - "pipeline_events": true, - "wiki_page_events": true, - "job_events": true, - "comment_on_event_enabled": true, - "project_id": 1 - }""" - content = content.encode("utf-8") - return response(200, content, headers, None, 5, request) +@with_httmock(resp_get_project) +def test_get_project(gl): + data = gl.projects.get(1) + assert isinstance(data, Project) + assert data.name == "name" + assert data.id == 1 -@urlmatch( - scheme="http", netloc="localhost", path="/api/v4/projects/1/services", method="get", -) -def resp_get_active_services(url, request): - """Mock for active Services GET response.""" - content = """[{ - "id": 100152, - "title": "Pipelines emails", - "slug": "pipelines-email", - "created_at": "2019-01-14T08:46:43.637+01:00", - "updated_at": "2019-07-01T14:10:36.156+02:00", - "active": true, - "commit_events": true, - "push_events": true, - "issues_events": true, - "confidential_issues_events": true, - "merge_requests_events": true, - "tag_push_events": true, - "note_events": true, - "confidential_note_events": true, - "pipeline_events": true, - "wiki_page_events": true, - "job_events": true, - "comment_on_event_enabled": true, - "project_id": 1 - }]""" - content = content.encode("utf-8") - return response(200, content, headers, None, 5, request) +@pytest.mark.skip(reason="missing test") +def test_list_projects(gl): + pass -@urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/projects/1/pipeline_schedules$", - method="post", -) -def resp_create_project_pipeline_schedule(url, request): - """Mock for creating project pipeline Schedules POST response.""" - content = """{ - "id": 14, - "description": "Build packages", - "ref": "master", - "cron": "0 1 * * 5", - "cron_timezone": "UTC", - "next_run_at": "2017-05-26T01:00:00.000Z", - "active": true, - "created_at": "2017-05-19T13:43:08.169Z", - "updated_at": "2017-05-19T13:43:08.169Z", - "last_pipeline": null, - "owner": { - "name": "Administrator", - "username": "root", - "id": 1, - "state": "active", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", - "web_url": "https://gitlab.example.com/root" - } -}""" - content = content.encode("utf-8") - return response(200, content, headers, None, 5, request) +@pytest.mark.skip(reason="missing test") +def test_list_user_projects(gl): + pass -@urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/projects/1/pipeline_schedules/14/play", - method="post", -) -def resp_play_project_pipeline_schedule(url, request): - """Mock for playing a project pipeline schedule POST response.""" - content = """{"message": "201 Created"}""" - content = content.encode("utf-8") - return response(200, content, headers, None, 5, request) +@pytest.mark.skip(reason="missing test") +def test_list_user_starred_projects(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_list_project_users(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_create_project(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_create_user_project(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_update_project(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_fork_project(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_list_project_forks(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_star_project(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_unstar_project(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_list_project_starrers(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_get_project_languages(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_archive_project(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_unarchive_project(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_remove_project(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_restore_project(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_upload_file(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_share_project(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_delete_shared_project_link(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_list_project_hooks(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_get_project_hook(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_create_project_hook(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_update_project_hook(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_delete_project_hook(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_create_forked_from_relationship(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_delete_forked_from_relationship(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_search_projects_by_name(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_project_housekeeping(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_get_project_push_rules(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_create_project_push_rule(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_update_project_push_rule(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_delete_project_push_rule(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_transfer_project(gl): + pass + + +@pytest.mark.skip(reason="missing test") +def test_project_pull_mirror(gl): + pass -class TestProject(unittest.TestCase): - """Base class for GitLab Project tests.""" - - def setUp(self): - self.gl = Gitlab( - "http://localhost", - private_token="private_token", - ssl_verify=True, - api_version="4", - ) - self.project = self.gl.projects.get(1, lazy=True) - - -class TestProjectSnippets(TestProject): - def test_list_project_snippets(self): - title = "Example Snippet Title" - visibility = "private" - - @urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/projects/1/snippets", - method="get", - ) - def resp_list_snippet(url, request): - content = """[{ - "title": "%s", - "description": "More verbose snippet description", - "file_name": "example.txt", - "content": "source code with multiple lines", - "visibility": "%s"}]""" % ( - title, - visibility, - ) - content = content.encode("utf-8") - return response(200, content, headers, None, 25, request) - - with HTTMock(resp_list_snippet): - snippets = self.project.snippets.list() - assert len(snippets) == 1 - assert snippets[0].title == title - assert snippets[0].visibility == visibility - - def test_get_project_snippets(self): - title = "Example Snippet Title" - visibility = "private" - - @urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/projects/1/snippets/1", - method="get", - ) - def resp_get_snippet(url, request): - content = """{ - "title": "%s", - "description": "More verbose snippet description", - "file_name": "example.txt", - "content": "source code with multiple lines", - "visibility": "%s"}""" % ( - title, - visibility, - ) - content = content.encode("utf-8") - return response(200, content, headers, None, 25, request) - - with HTTMock(resp_get_snippet): - snippet = self.project.snippets.get(1) - assert snippet.title == title - assert snippet.visibility == visibility - - def test_create_update_project_snippets(self): - title = "Example Snippet Title" - visibility = "private" - - @urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/projects/1/snippets", - method="put", - ) - def resp_update_snippet(url, request): - content = """{ - "title": "%s", - "description": "More verbose snippet description", - "file_name": "example.txt", - "content": "source code with multiple lines", - "visibility": "%s"}""" % ( - title, - visibility, - ) - content = content.encode("utf-8") - return response(200, content, headers, None, 25, request) - - @urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/projects/1/snippets", - method="post", - ) - def resp_create_snippet(url, request): - content = """{ - "title": "%s", - "description": "More verbose snippet description", - "file_name": "example.txt", - "content": "source code with multiple lines", - "visibility": "%s"}""" % ( - title, - visibility, - ) - content = content.encode("utf-8") - return response(200, content, headers, None, 25, request) - - with HTTMock(resp_create_snippet, resp_update_snippet): - snippet = self.project.snippets.create( - { - "title": title, - "file_name": title, - "content": title, - "visibility": visibility, - } - ) - assert snippet.title == title - assert snippet.visibility == visibility - title = "new-title" - snippet.title = title - snippet.save() - assert snippet.title == title - assert snippet.visibility == visibility - - -class TestProjectExport(TestProject): - @with_httmock(resp_create_export) - def test_create_project_export(self): - export = self.project.exports.create() - assert export.message == "202 Accepted" - - @with_httmock(resp_create_export, resp_export_status) - def test_refresh_project_export_status(self): - export = self.project.exports.create() - export.refresh() - assert export.export_status == "finished" - - @with_httmock(resp_create_export, resp_download_export) - def test_download_project_export(self): - export = self.project.exports.create() - download = export.download() - assert isinstance(download, bytes) - assert download == binary_content - - -class TestProjectImport(TestProject): - @with_httmock(resp_import_project) - def test_import_project(self): - project_import = self.gl.projects.import_project("file", "api-project") - assert project_import["import_status"] == "scheduled" - - @with_httmock(resp_import_status) - def test_refresh_project_import_status(self): - project_import = self.project.imports.get() - project_import.refresh() - assert project_import.import_status == "finished" - - @with_httmock(resp_import_github) - def test_import_github(self): - base_path = "/root" - name = "my-repo" - ret = self.gl.projects.import_github("githubkey", 1234, base_path, name) - assert isinstance(ret, dict) - assert ret["name"] == name - assert ret["full_path"] == "/".join((base_path, name)) - assert ret["full_name"].endswith(name) - - -class TestProjectRemoteMirrors(TestProject): - @with_httmock(resp_get_remote_mirrors) - def test_list_project_remote_mirrors(self): - mirrors = self.project.remote_mirrors.list() - assert isinstance(mirrors, list) - assert isinstance(mirrors[0], ProjectRemoteMirror) - assert mirrors[0].enabled - - @with_httmock(resp_create_remote_mirror) - def test_create_project_remote_mirror(self): - mirror = self.project.remote_mirrors.create({"url": "https://example.com"}) - assert isinstance(mirror, ProjectRemoteMirror) - assert mirror.update_status == "none" - - @with_httmock(resp_create_remote_mirror, resp_update_remote_mirror) - def test_update_project_remote_mirror(self): - mirror = self.project.remote_mirrors.create({"url": "https://example.com"}) - mirror.only_protected_branches = True - mirror.save() - assert mirror.update_status == "finished" - assert mirror.only_protected_branches - - -class TestProjectServices(TestProject): - @with_httmock(resp_get_active_services) - def test_list_active_services(self): - services = self.project.services.list() - assert isinstance(services, list) - assert isinstance(services[0], ProjectService) - assert services[0].active - assert services[0].push_events - - def test_list_available_services(self): - services = self.project.services.available() - assert isinstance(services, list) - assert isinstance(services[0], str) - - @with_httmock(resp_get_service) - def test_get_service(self): - service = self.project.services.get("pipelines-email") - assert isinstance(service, ProjectService) - assert service.push_events == True - - @with_httmock(resp_get_service, resp_update_service) - def test_update_service(self): - service = self.project.services.get("pipelines-email") - service.issues_events = True - service.save() - assert service.issues_events == True - - -class TestProjectPipelineSchedule(TestProject): - @with_httmock( - resp_create_project_pipeline_schedule, resp_play_project_pipeline_schedule - ) - def test_project_pipeline_schedule_play(self): - description = "Build packages" - cronline = "0 1 * * 5" - sched = self.project.pipelineschedules.create( - {"ref": "master", "description": description, "cron": cronline} - ) - self.assertIsNotNone(sched) - self.assertEqual(description, sched.description) - self.assertEqual(cronline, sched.cron) - - play_result = sched.play() - self.assertIsNotNone(play_result) - self.assertIn("message", play_result) - self.assertEqual("201 Created", play_result["message"]) +@pytest.mark.skip(reason="missing test") +def test_project_snapshot(gl): + pass diff --git a/gitlab/tests/objects/test_remote_mirrors.py b/gitlab/tests/objects/test_remote_mirrors.py new file mode 100644 index 0000000..e62a71e --- /dev/null +++ b/gitlab/tests/objects/test_remote_mirrors.py @@ -0,0 +1,103 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/remote_mirrors.html +""" + +from httmock import response, urlmatch, with_httmock + +from gitlab.v4.objects import ProjectRemoteMirror +from .mocks import headers + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/remote_mirrors", + method="get", +) +def resp_get_remote_mirrors(url, request): + """Mock for Project Remote Mirrors GET response.""" + content = """[ + { + "enabled": true, + "id": 101486, + "last_error": null, + "last_successful_update_at": "2020-01-06T17:32:02.823Z", + "last_update_at": "2020-01-06T17:32:02.823Z", + "last_update_started_at": "2020-01-06T17:31:55.864Z", + "only_protected_branches": true, + "update_status": "finished", + "url": "https://*****:*****@gitlab.com/gitlab-org/security/gitlab.git" + } + ]""" + content = content.encode("utf-8") + return response(200, content, headers, None, 5, request) + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/remote_mirrors", + method="post", +) +def resp_create_remote_mirror(url, request): + """Mock for Project Remote Mirrors POST response.""" + content = """{ + "enabled": false, + "id": 101486, + "last_error": null, + "last_successful_update_at": null, + "last_update_at": null, + "last_update_started_at": null, + "only_protected_branches": false, + "update_status": "none", + "url": "https://*****:*****@example.com/gitlab/example.git" + }""" + content = content.encode("utf-8") + return response(200, content, headers, None, 5, request) + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/remote_mirrors/1", + method="put", +) +def resp_update_remote_mirror(url, request): + """Mock for Project Remote Mirrors PUT response.""" + content = """{ + "enabled": false, + "id": 101486, + "last_error": null, + "last_successful_update_at": "2020-01-06T17:32:02.823Z", + "last_update_at": "2020-01-06T17:32:02.823Z", + "last_update_started_at": "2020-01-06T17:31:55.864Z", + "only_protected_branches": true, + "update_status": "finished", + "url": "https://*****:*****@gitlab.com/gitlab-org/security/gitlab.git" + }""" + content = content.encode("utf-8") + return response(200, content, headers, None, 5, request) + + +@with_httmock(resp_get_remote_mirrors) +def test_list_project_remote_mirrors(project): + mirrors = project.remote_mirrors.list() + assert isinstance(mirrors, list) + assert isinstance(mirrors[0], ProjectRemoteMirror) + assert mirrors[0].enabled + + +@with_httmock(resp_create_remote_mirror) +def test_create_project_remote_mirror(project): + mirror = project.remote_mirrors.create({"url": "https://example.com"}) + assert isinstance(mirror, ProjectRemoteMirror) + assert mirror.update_status == "none" + + +@with_httmock(resp_create_remote_mirror, resp_update_remote_mirror) +def test_update_project_remote_mirror(project): + mirror = project.remote_mirrors.create({"url": "https://example.com"}) + mirror.only_protected_branches = True + mirror.save() + assert mirror.update_status == "finished" + assert mirror.only_protected_branches diff --git a/gitlab/tests/objects/test_services.py b/gitlab/tests/objects/test_services.py new file mode 100644 index 0000000..a0cded7 --- /dev/null +++ b/gitlab/tests/objects/test_services.py @@ -0,0 +1,134 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/services.html +""" + +from httmock import urlmatch, response, with_httmock + +from gitlab.v4.objects import ProjectService +from .mocks import headers + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/services/pipelines-email", + method="put", +) +def resp_update_service(url, request): + """Mock for Service update PUT response.""" + content = """{ + "id": 100152, + "title": "Pipelines emails", + "slug": "pipelines-email", + "created_at": "2019-01-14T08:46:43.637+01:00", + "updated_at": "2019-07-01T14:10:36.156+02:00", + "active": true, + "commit_events": true, + "push_events": true, + "issues_events": true, + "confidential_issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "confidential_note_events": true, + "pipeline_events": true, + "wiki_page_events": true, + "job_events": true, + "comment_on_event_enabled": true, + "project_id": 1 + }""" + content = content.encode("utf-8") + return response(200, content, headers, None, 5, request) + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/services/pipelines-email", + method="get", +) +def resp_get_service(url, request): + """Mock for Service GET response.""" + content = """{ + "id": 100152, + "title": "Pipelines emails", + "slug": "pipelines-email", + "created_at": "2019-01-14T08:46:43.637+01:00", + "updated_at": "2019-07-01T14:10:36.156+02:00", + "active": true, + "commit_events": true, + "push_events": true, + "issues_events": true, + "confidential_issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "confidential_note_events": true, + "pipeline_events": true, + "wiki_page_events": true, + "job_events": true, + "comment_on_event_enabled": true, + "project_id": 1 + }""" + content = content.encode("utf-8") + return response(200, content, headers, None, 5, request) + + +@urlmatch( + scheme="http", netloc="localhost", path="/api/v4/projects/1/services", method="get", +) +def resp_get_active_services(url, request): + """Mock for active Services GET response.""" + content = """[{ + "id": 100152, + "title": "Pipelines emails", + "slug": "pipelines-email", + "created_at": "2019-01-14T08:46:43.637+01:00", + "updated_at": "2019-07-01T14:10:36.156+02:00", + "active": true, + "commit_events": true, + "push_events": true, + "issues_events": true, + "confidential_issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "confidential_note_events": true, + "pipeline_events": true, + "wiki_page_events": true, + "job_events": true, + "comment_on_event_enabled": true, + "project_id": 1 + }]""" + content = content.encode("utf-8") + return response(200, content, headers, None, 5, request) + + +@with_httmock(resp_get_active_services) +def test_list_active_services(project): + services = project.services.list() + assert isinstance(services, list) + assert isinstance(services[0], ProjectService) + assert services[0].active + assert services[0].push_events + + +def test_list_available_services(project): + services = project.services.available() + assert isinstance(services, list) + assert isinstance(services[0], str) + + +@with_httmock(resp_get_service) +def test_get_service(project): + service = project.services.get("pipelines-email") + assert isinstance(service, ProjectService) + assert service.push_events is True + + +@with_httmock(resp_get_service, resp_update_service) +def test_update_service(project): + service = project.services.get("pipelines-email") + service.issues_events = True + service.save() + assert service.issues_events is True diff --git a/gitlab/tests/objects/test_snippets.py b/gitlab/tests/objects/test_snippets.py new file mode 100644 index 0000000..86eb54c --- /dev/null +++ b/gitlab/tests/objects/test_snippets.py @@ -0,0 +1,121 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/project_snippets.html + https://docs.gitlab.com/ee/api/snippets.html (todo) +""" + +from httmock import response, urlmatch, with_httmock + +from .mocks import headers + + +title = "Example Snippet Title" +visibility = "private" +new_title = "new-title" + + +@urlmatch( + scheme="http", netloc="localhost", path="/api/v4/projects/1/snippets", method="get", +) +def resp_list_snippet(url, request): + content = """[{ + "title": "%s", + "description": "More verbose snippet description", + "file_name": "example.txt", + "content": "source code with multiple lines", + "visibility": "%s"}]""" % ( + title, + visibility, + ) + content = content.encode("utf-8") + return response(200, content, headers, None, 25, request) + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/snippets/1", + method="get", +) +def resp_get_snippet(url, request): + content = """{ + "title": "%s", + "description": "More verbose snippet description", + "file_name": "example.txt", + "content": "source code with multiple lines", + "visibility": "%s"}""" % ( + title, + visibility, + ) + content = content.encode("utf-8") + return response(200, content, headers, None, 25, request) + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/snippets", + method="post", +) +def resp_create_snippet(url, request): + content = """{ + "title": "%s", + "description": "More verbose snippet description", + "file_name": "example.txt", + "content": "source code with multiple lines", + "visibility": "%s"}""" % ( + title, + visibility, + ) + content = content.encode("utf-8") + return response(200, content, headers, None, 25, request) + + +@urlmatch( + scheme="http", netloc="localhost", path="/api/v4/projects/1/snippets", method="put", +) +def resp_update_snippet(url, request): + content = """{ + "title": "%s", + "description": "More verbose snippet description", + "file_name": "example.txt", + "content": "source code with multiple lines", + "visibility": "%s"}""" % ( + new_title, + visibility, + ) + content = content.encode("utf-8") + return response(200, content, headers, None, 25, request) + + +@with_httmock(resp_list_snippet) +def test_list_project_snippets(project): + snippets = project.snippets.list() + assert len(snippets) == 1 + assert snippets[0].title == title + assert snippets[0].visibility == visibility + + +@with_httmock(resp_get_snippet) +def test_get_project_snippets(project): + snippet = project.snippets.get(1) + assert snippet.title == title + assert snippet.visibility == visibility + + +@with_httmock(resp_create_snippet, resp_update_snippet) +def test_create_update_project_snippets(project): + snippet = project.snippets.create( + { + "title": title, + "file_name": title, + "content": title, + "visibility": visibility, + } + ) + assert snippet.title == title + assert snippet.visibility == visibility + + snippet.title = new_title + snippet.save() + assert snippet.title == new_title + assert snippet.visibility == visibility diff --git a/gitlab/tests/objects/test_submodules.py b/gitlab/tests/objects/test_submodules.py new file mode 100644 index 0000000..2e76302 --- /dev/null +++ b/gitlab/tests/objects/test_submodules.py @@ -0,0 +1,58 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/repository_submodules.html +""" + +from httmock import response, urlmatch, with_httmock + +from gitlab.v4.objects import Project + +from .mocks import headers + + +@urlmatch(scheme="http", netloc="localhost", path="/api/v4/projects/1$", method="get") +def resp_get_project(url, request): + content = '{"name": "name", "id": 1}'.encode("utf-8") + return response(200, content, headers, None, 5, request) + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/repository/submodules/foo%2Fbar", + method="put", +) +def resp_update_submodule(url, request): + content = """{ + "id": "ed899a2f4b50b4370feeea94676502b42383c746", + "short_id": "ed899a2f4b5", + "title": "Message", + "author_name": "Author", + "author_email": "author@example.com", + "committer_name": "Author", + "committer_email": "author@example.com", + "created_at": "2018-09-20T09:26:24.000-07:00", + "message": "Message", + "parent_ids": [ "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba" ], + "committed_date": "2018-09-20T09:26:24.000-07:00", + "authored_date": "2018-09-20T09:26:24.000-07:00", + "status": null}""" + content = content.encode("utf-8") + return response(200, content, headers, None, 5, request) + + +@with_httmock(resp_get_project, resp_update_submodule) +def test_update_submodule(gl): + project = gl.projects.get(1) + assert isinstance(project, Project) + assert project.name == "name" + assert project.id == 1 + + ret = project.update_submodule( + submodule="foo/bar", + branch="master", + commit_sha="4c3674f66071e30b3311dac9b9ccc90502a72664", + commit_message="Message", + ) + assert isinstance(ret, dict) + assert ret["message"] == "Message" + assert ret["id"] == "ed899a2f4b50b4370feeea94676502b42383c746" diff --git a/gitlab/tests/objects/test_todos.py b/gitlab/tests/objects/test_todos.py new file mode 100644 index 0000000..5b30dc9 --- /dev/null +++ b/gitlab/tests/objects/test_todos.py @@ -0,0 +1,58 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/todos.html +""" + +import json +import os + +from httmock import response, urlmatch, with_httmock + +from gitlab.v4.objects import Todo + +from .mocks import headers + + +with open(os.path.dirname(__file__) + "/../data/todo.json", "r") as json_file: + todo_content = json_file.read() + json_content = json.loads(todo_content) + encoded_content = todo_content.encode("utf-8") + + +@urlmatch(scheme="http", netloc="localhost", path="/api/v4/todos", method="get") +def resp_get_todo(url, request): + return response(200, encoded_content, headers, None, 5, request) + + +@urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/todos/102/mark_as_done", + method="post", +) +def resp_mark_as_done(url, request): + single_todo = json.dumps(json_content[0]) + content = single_todo.encode("utf-8") + return response(200, content, headers, None, 5, request) + + +@urlmatch( + scheme="http", netloc="localhost", path="/api/v4/todos/mark_as_done", method="post", +) +def resp_mark_all_as_done(url, request): + return response(204, {}, headers, None, 5, request) + + +@with_httmock(resp_get_todo, resp_mark_as_done) +def test_todo(gl): + todo = gl.todos.list()[0] + assert isinstance(todo, Todo) + assert todo.id == 102 + assert todo.target_type == "MergeRequest" + assert todo.target["assignee"]["username"] == "root" + + todo.mark_as_done() + + +@with_httmock(resp_mark_all_as_done) +def test_todo_mark_all_as_done(gl): + gl.todos.mark_all_as_done() diff --git a/gitlab/tests/objects/test_users.py b/gitlab/tests/objects/test_users.py new file mode 100644 index 0000000..88175d0 --- /dev/null +++ b/gitlab/tests/objects/test_users.py @@ -0,0 +1,94 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/users.html +""" + +from httmock import response, urlmatch, with_httmock + +from gitlab.v4.objects import User, UserMembership, UserStatus +from .mocks import headers + + +@urlmatch(scheme="http", netloc="localhost", path="/api/v4/users/1", method="get") +def resp_get_user(url, request): + content = ( + '{"name": "name", "id": 1, "password": "password", ' + '"username": "username", "email": "email"}' + ) + content = content.encode("utf-8") + return response(200, content, headers, None, 5, request) + + +@urlmatch( + scheme="http", netloc="localhost", path="/api/v4/users/1/memberships", method="get", +) +def resp_get_user_memberships(url, request): + content = """[ + { + "source_id": 1, + "source_name": "Project one", + "source_type": "Project", + "access_level": "20" + }, + { + "source_id": 3, + "source_name": "Group three", + "source_type": "Namespace", + "access_level": "20" + } + ]""" + content = content.encode("utf-8") + return response(200, content, headers, None, 5, request) + + +@urlmatch( + scheme="http", netloc="localhost", path="/api/v4/users/1/activate", method="post", +) +def resp_activate(url, request): + return response(201, {}, headers, None, 5, request) + + +@urlmatch( + scheme="http", netloc="localhost", path="/api/v4/users/1/deactivate", method="post", +) +def resp_deactivate(url, request): + return response(201, {}, headers, None, 5, request) + + +@urlmatch( + scheme="http", netloc="localhost", path="/api/v4/users/1/status", method="get", +) +def resp_get_user_status(url, request): + content = ( + '{"message": "test", "message_html": "<h1>Message</h1>", "emoji": "thumbsup"}' + ) + content = content.encode("utf-8") + return response(200, content, headers, None, 5, request) + + +@with_httmock(resp_get_user) +def test_get_user(gl): + user = gl.users.get(1) + assert isinstance(user, User) + assert user.name == "name" + assert user.id == 1 + + +@with_httmock(resp_get_user_memberships) +def test_user_memberships(user): + memberships = user.memberships.list() + assert isinstance(memberships[0], UserMembership) + assert memberships[0].source_type == "Project" + + +@with_httmock(resp_get_user_status) +def test_user_status(user): + status = user.status.get() + assert isinstance(status, UserStatus) + assert status.message == "test" + assert status.emoji == "thumbsup" + + +@with_httmock(resp_activate, resp_deactivate) +def test_user_activate_deactivate(user): + user.activate() + user.deactivate() |