diff options
Diffstat (limited to 'gitlab/tests/objects')
23 files changed, 1485 insertions, 895 deletions
diff --git a/gitlab/tests/objects/conftest.py b/gitlab/tests/objects/conftest.py new file mode 100644 index 0000000..76f76d1 --- /dev/null +++ b/gitlab/tests/objects/conftest.py @@ -0,0 +1,65 @@ +"""Common mocks for resources in gitlab.v4.objects""" + +import re + +import pytest +import responses + + +@pytest.fixture +def binary_content(): + return b"binary content" + + +@pytest.fixture +def accepted_content(): + return {"message": "202 Accepted"} + + +@pytest.fixture +def created_content(): + return {"message": "201 Created"} + + +@pytest.fixture +def resp_export(accepted_content, binary_content): + """Common fixture for group and project exports.""" + export_status_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", + }, + } + + with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: + rsps.add( + method=responses.POST, + url=re.compile(r".*/api/v4/(groups|projects)/1/export"), + json=accepted_content, + content_type="application/json", + status=202, + ) + rsps.add( + method=responses.GET, + url=re.compile(r".*/api/v4/(groups|projects)/1/export/download"), + body=binary_content, + content_type="application/octet-stream", + status=200, + ) + # Currently only project export supports status checks + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1/export", + json=export_status_content, + content_type="application/json", + status=200, + ) + yield rsps diff --git a/gitlab/tests/objects/mocks.py b/gitlab/tests/objects/mocks.py deleted file mode 100644 index e051339..0000000 --- a/gitlab/tests/objects/mocks.py +++ /dev/null @@ -1,35 +0,0 @@ -"""Common mocks for resources in gitlab.v4.objects""" - -from httmock import response, urlmatch - - -headers = {"content-type": "application/json"} -binary_content = b"binary content" - - -@urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/(groups|projects)/1/export", - method="post", -) -def resp_create_export(url, request): - """Common mock for Group/Project Export POST response.""" - content = """{ - "message": "202 Accepted" - }""" - content = content.encode("utf-8") - return response(202, content, headers, None, 25, request) - - -@urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/(groups|projects)/1/export/download", - method="get", -) -def resp_download_export(url, request): - """Common mock for Group/Project Export Download GET response.""" - headers = {"content-type": "application/octet-stream"} - content = binary_content - return response(200, content, headers, None, 25, request) diff --git a/gitlab/tests/objects/test_appearance.py b/gitlab/tests/objects/test_appearance.py new file mode 100644 index 0000000..7c52301 --- /dev/null +++ b/gitlab/tests/objects/test_appearance.py @@ -0,0 +1,66 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/appearance.html +""" + +import pytest +import responses + + +title = "GitLab Test Instance" +description = "gitlab-test.example.com" +new_title = "new-title" +new_description = "new-description" + + +@pytest.fixture +def resp_application_appearance(): + content = { + "title": title, + "description": description, + "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, + } + + with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/application/appearance", + json=content, + content_type="application/json", + status=200, + ) + + updated_content = dict(content) + updated_content["title"] = new_title + updated_content["description"] = new_description + + rsps.add( + method=responses.PUT, + url="http://localhost/api/v4/application/appearance", + json=updated_content, + content_type="application/json", + status=200, + ) + yield rsps + + +def test_get_update_appearance(gl, resp_application_appearance): + 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 + + +def test_update_appearance(gl, resp_application_appearance): + resp = gl.appearance.update(title=new_title, description=new_description) diff --git a/gitlab/tests/objects/test_application.py b/gitlab/tests/objects/test_application.py deleted file mode 100644 index 50ca1ad..0000000 --- a/gitlab/tests/objects/test_application.py +++ /dev/null @@ -1,120 +0,0 @@ -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 # 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() - self.assertEqual(appearance.title, self.title) - self.assertEqual(appearance.description, self.description) - appearance.title = self.new_title - appearance.description = self.new_description - appearance.save() - self.assertEqual(appearance.title, self.new_title) - self.assertEqual(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 - ) diff --git a/gitlab/tests/objects/test_applications.py b/gitlab/tests/objects/test_applications.py new file mode 100644 index 0000000..f8b5d88 --- /dev/null +++ b/gitlab/tests/objects/test_applications.py @@ -0,0 +1,45 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/applications.html +""" + +import pytest +import responses + + +title = "GitLab Test Instance" +description = "gitlab-test.example.com" +new_title = "new-title" +new_description = "new-description" + + +@pytest.fixture +def resp_application_create(): + content = { + "name": "test_app", + "redirect_uri": "http://localhost:8080", + "scopes": ["api", "email"], + } + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/applications", + json=content, + content_type="application/json", + status=200, + ) + yield rsps + + +def test_create_application(gl, resp_application_create): + 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"] diff --git a/gitlab/tests/objects/test_commits.py b/gitlab/tests/objects/test_commits.py index 7e7c3b4..9d11508 100644 --- a/gitlab/tests/objects/test_commits.py +++ b/gitlab/tests/objects/test_commits.py @@ -1,107 +1,109 @@ -from httmock import urlmatch, response, with_httmock - -from .mocks import headers -from .test_projects import TestProject - - -@urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/projects/1/repository/commits/6b2257ea", - method="get", -) -def resp_get_commit(url, request): - """Mock for commit GET response.""" - content = """{ - "id": "6b2257eabcec3db1f59dafbd84935e3caea04235", - "short_id": "6b2257ea", - "title": "Initial commit" - }""" - content = content.encode("utf-8") - return response(200, content, headers, None, 5, request) - - -@urlmatch( - scheme="http", path="/api/v4/projects/1/repository/commits", method="post", -) -def resp_create_commit(url, request): - """Mock for commit create POST response.""" - content = """{ - "id": "ed899a2f4b50b4370feeea94676502b42383c746", - "short_id": "ed899a2f", - "title": "Commit message" - }""" - content = content.encode("utf-8") - return response(200, content, headers, None, 5, request) - - -@urlmatch( - scheme="http", path="/api/v4/projects/1/repository/commits/6b2257ea", method="post", -) -def resp_revert_commit(url, request): - """Mock for commit revert POST response.""" - content = """{ - "id": "8b090c1b79a14f2bd9e8a738f717824ff53aebad", - "short_id": "8b090c1b", - "title":"Revert \\"Initial commit\\"" - }""" - content = content.encode("utf-8") - return response(200, content, headers, None, 5, request) - - -@urlmatch( - scheme="http", - netloc="localhost", - path="/api/v4/projects/1/repository/commits/6b2257ea/signature", - method="get", -) -def resp_get_commit_gpg_signature(url, request): - """Mock for commit GPG signature GET response.""" - content = """{ - "gpg_key_id": 1, - "gpg_key_primary_keyid": "8254AAB3FBD54AC9", - "gpg_key_user_name": "John Doe", - "gpg_key_user_email": "johndoe@example.com", - "verification_status": "verified", - "gpg_key_subkey_id": null - }""" - content = content.encode("utf-8") - 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") - self.assertEqual(commit.short_id, "6b2257ea") - self.assertEqual(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) - self.assertEqual(commit.short_id, "ed899a2f") - self.assertEqual(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") - self.assertEqual(revert_commit["short_id"], "8b090c1b") - self.assertEqual(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() - self.assertEqual(signature["gpg_key_primary_keyid"], "8254AAB3FBD54AC9") - self.assertEqual(signature["verification_status"], "verified") +""" +GitLab API: https://docs.gitlab.com/ce/api/commits.html +""" + +import pytest +import responses + + +@pytest.fixture +def resp_create_commit(): + content = { + "id": "ed899a2f4b50b4370feeea94676502b42383c746", + "short_id": "ed899a2f", + "title": "Commit message", + } + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/projects/1/repository/commits", + json=content, + content_type="application/json", + status=200, + ) + yield rsps + + +@pytest.fixture +def resp_commit(): + get_content = { + "id": "6b2257eabcec3db1f59dafbd84935e3caea04235", + "short_id": "6b2257ea", + "title": "Initial commit", + } + revert_content = { + "id": "8b090c1b79a14f2bd9e8a738f717824ff53aebad", + "short_id": "8b090c1b", + "title": 'Revert "Initial commit"', + } + + with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1/repository/commits/6b2257ea", + json=get_content, + content_type="application/json", + status=200, + ) + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/projects/1/repository/commits/6b2257ea/revert", + json=revert_content, + content_type="application/json", + status=200, + ) + yield rsps + + +@pytest.fixture +def resp_get_commit_gpg_signature(): + content = { + "gpg_key_id": 1, + "gpg_key_primary_keyid": "8254AAB3FBD54AC9", + "gpg_key_user_name": "John Doe", + "gpg_key_user_email": "johndoe@example.com", + "verification_status": "verified", + "gpg_key_subkey_id": None, + } + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1/repository/commits/6b2257ea/signature", + json=content, + content_type="application/json", + status=200, + ) + yield rsps + + +def test_get_commit(project, resp_commit): + commit = project.commits.get("6b2257ea") + assert commit.short_id == "6b2257ea" + assert commit.title == "Initial commit" + + +def test_create_commit(project, resp_create_commit): + 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"] + + +def test_revert_commit(project, resp_commit): + 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"' + + +def test_get_commit_gpg_signature(project, resp_get_commit_gpg_signature): + 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..9cfa598 --- /dev/null +++ b/gitlab/tests/objects/test_deploy_tokens.py @@ -0,0 +1,46 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/deploy_tokens.html +""" +import pytest +import responses + +from gitlab.v4.objects import ProjectDeployToken + + +create_content = { + "id": 1, + "name": "test_deploy_token", + "username": "custom-user", + "expires_at": "2022-01-01T00:00:00.000Z", + "token": "jMRvtPNxrn3crTAGukpZ", + "scopes": ["read_repository"], +} + + +@pytest.fixture +def resp_deploy_token_create(): + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/projects/1/deploy_tokens", + json=create_content, + content_type="application/json", + status=200, + ) + yield rsps + + +def test_deploy_tokens(gl, resp_deploy_token_create): + 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..3cde8fe --- /dev/null +++ b/gitlab/tests/objects/test_deployments.py @@ -0,0 +1,50 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/deployments.html +""" +import pytest +import responses + + +@pytest.fixture +def resp_deployment(): + content = {"id": 42, "status": "success", "ref": "master"} + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/projects/1/deployments", + json=content, + content_type="application/json", + status=200, + ) + + updated_content = dict(content) + updated_content["status"] = "failed" + + rsps.add( + method=responses.PUT, + url="http://localhost/api/v4/projects/1/deployments/42", + json=updated_content, + content_type="application/json", + status=200, + ) + yield rsps + + +def test_deployment(project, resp_deployment): + 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" + + 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..b49a1db --- /dev/null +++ b/gitlab/tests/objects/test_environments.py @@ -0,0 +1,30 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/environments.html +""" +import pytest +import responses + +from gitlab.v4.objects import ProjectEnvironment + + +@pytest.fixture +def resp_get_environment(): + content = {"name": "environment_name", "id": 1, "last_deployment": "sometime"} + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1/environments/1", + json=content, + content_type="application/json", + status=200, + ) + yield rsps + + +def test_project_environments(project, resp_get_environment): + 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 075d915..d4786f4 100644 --- a/gitlab/tests/objects/test_groups.py +++ b/gitlab/tests/objects/test_groups.py @@ -1,101 +1,97 @@ -import unittest +""" +GitLab API: https://docs.gitlab.com/ce/api/groups.html +""" -from httmock import response, urlmatch, with_httmock +import pytest +import responses import gitlab -from .mocks import * # noqa -@urlmatch(scheme="http", netloc="localhost", path="/api/v4/groups/1", method="get") -def resp_get_group(url, request): - content = '{"name": "name", "id": 1, "path": "path"}' - content = content.encode("utf-8") - return response(200, content, headers, None, 5, request) +@pytest.fixture +def resp_groups(): + content = {"name": "name", "id": 1, "path": "path"} + with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/groups/1", + json=content, + content_type="application/json", + status=200, + ) + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/groups", + json=[content], + content_type="application/json", + status=200, + ) + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/groups", + json=content, + content_type="application/json", + status=200, + ) + yield rsps + + +@pytest.fixture +def resp_create_import(accepted_content): + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/groups/import", + json=accepted_content, + content_type="application/json", + status=202, + ) + yield rsps -@urlmatch(scheme="http", netloc="localhost", path="/api/v4/groups", method="post") -def resp_create_group(url, request): - content = '{"name": "name", "id": 1, "path": "path"}' - content = content.encode("utf-8") - return response(200, content, headers, None, 5, request) +def test_get_group(gl, resp_groups): + data = gl.groups.get(1) + assert isinstance(data, gitlab.v4.objects.Group) + assert data.name == "name" + assert data.path == "path" + assert data.id == 1 -@urlmatch( - scheme="http", netloc="localhost", path="/api/v4/groups/import", method="post", -) -def resp_create_import(url, request): - """Mock for Group import tests. - GitLab does not respond with import status for group imports. - """ +def test_create_group(gl, resp_groups): + 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 - content = """{ - "message": "202 Accepted" - }""" - content = content.encode("utf-8") - return response(202, content, headers, None, 25, request) +def test_create_group_export(group, resp_export): + export = group.exports.create() + assert export.message == "202 Accepted" + + +@pytest.mark.skip("GitLab API endpoint not implemented") +def test_refresh_group_export_status(group, resp_export): + export = group.exports.create() + export.refresh() + assert export.export_status == "finished" + + +def test_download_group_export(group, resp_export, binary_content): + export = group.exports.create() + download = export.download() + assert isinstance(download, bytes) + assert download == binary_content + + +def test_import_group(gl, resp_create_import): + group_import = gl.groups.import_group("file", "api-group", "API Group") + assert group_import["message"] == "202 Accepted" -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) - self.assertIsInstance(data, gitlab.v4.objects.Group) - self.assertEqual(data.name, "name") - self.assertEqual(data.path, "path") - self.assertEqual(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}) - self.assertIsInstance(data, gitlab.v4.objects.Group) - self.assertEqual(data.name, name) - self.assertEqual(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() - self.assertEqual(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() - self.assertEqual(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() - self.assertIsInstance(download, bytes) - self.assertEqual(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") - self.assertEqual(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() - self.assertEqual(group_import.import_status, "finished") +@pytest.mark.skip("GitLab API endpoint not implemented") +def test_refresh_group_import_status(group, resp_groups): + 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..fe5c21c --- /dev/null +++ b/gitlab/tests/objects/test_hooks.py @@ -0,0 +1,29 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/system_hooks.html +""" +import pytest +import responses + +from gitlab.v4.objects import Hook + + +@pytest.fixture +def resp_get_hook(): + content = {"url": "testurl", "id": 1} + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/hooks/1", + json=content, + content_type="application/json", + status=200, + ) + yield rsps + + +def test_hooks(gl, resp_get_hook): + 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..f67d720 --- /dev/null +++ b/gitlab/tests/objects/test_issues.py @@ -0,0 +1,50 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/issues.html +""" + +import pytest +import responses + +from gitlab.v4.objects import ProjectIssuesStatistics + + +@pytest.fixture +def resp_issue(): + content = [{"name": "name", "id": 1}, {"name": "other_name", "id": 2}] + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/issues", + json=content, + content_type="application/json", + status=200, + ) + yield rsps + + +@pytest.fixture +def resp_issue_statistics(): + content = {"statistics": {"counts": {"all": 20, "closed": 5, "opened": 15}}} + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1/issues_statistics", + json=content, + content_type="application/json", + status=200, + ) + yield rsps + + +def test_issues(gl, resp_issue): + data = gl.issues.list() + assert data[1].id == 2 + assert data[1].name == "other_name" + + +def test_project_issues_statistics(project, resp_issue_statistics): + 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..c5dcc76 --- /dev/null +++ b/gitlab/tests/objects/test_pipeline_schedules.py @@ -0,0 +1,62 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/pipeline_schedules.html +""" +import pytest +import responses + + +@pytest.fixture +def resp_project_pipeline_schedule(created_content): + 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": None, + "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", + }, + } + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/projects/1/pipeline_schedules", + json=content, + content_type="application/json", + status=200, + ) + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/projects/1/pipeline_schedules/14/play", + json=created_content, + content_type="application/json", + status=201, + ) + yield rsps + + +def test_project_pipeline_schedule_play(project, resp_project_pipeline_schedule): + 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..78e51b1 --- /dev/null +++ b/gitlab/tests/objects/test_project_import_export.py @@ -0,0 +1,112 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/project_import_export.html +""" +import pytest +import responses + + +@pytest.fixture +def resp_import_project(): + content = { + "id": 1, + "description": None, + "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", + } + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/projects/import", + json=content, + content_type="application/json", + status=200, + ) + yield rsps + + +@pytest.fixture +def resp_import_status(): + 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", + } + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1/import", + json=content, + content_type="application/json", + status=200, + ) + yield rsps + + +@pytest.fixture +def resp_import_github(): + content = { + "id": 27, + "name": "my-repo", + "full_path": "/root/my-repo", + "full_name": "Administrator / my-repo", + } + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/import/github", + json=content, + content_type="application/json", + status=200, + ) + yield rsps + + +def test_import_project(gl, resp_import_project): + project_import = gl.projects.import_project("file", "api-project") + assert project_import["import_status"] == "scheduled" + + +def test_refresh_project_import_status(project, resp_import_status): + project_import = project.imports.get() + project_import.refresh() + assert project_import.import_status == "finished" + + +def test_import_github(gl, resp_import_github): + 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) + + +def test_create_project_export(project, resp_export): + export = project.exports.create() + assert export.message == "202 Accepted" + + +def test_refresh_project_export_status(project, resp_export): + export = project.exports.create() + export.refresh() + assert export.export_status == "finished" + + +def test_download_project_export(project, resp_export, binary_content): + 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..50d9a6d --- /dev/null +++ b/gitlab/tests/objects/test_project_statistics.py @@ -0,0 +1,28 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/project_statistics.html +""" +import pytest +import responses + +from gitlab.v4.objects import ProjectAdditionalStatistics + + +@pytest.fixture +def resp_project_statistics(): + content = {"fetches": {"total": 50, "days": [{"count": 10, "date": "2018-01-10"}]}} + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1/statistics", + json=content, + content_type="application/json", + status=200, + ) + yield rsps + + +def test_project_additional_statistics(project, resp_project_statistics): + 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 ca7e0c8..1e8b8b6 100644 --- a/gitlab/tests/objects/test_projects.py +++ b/gitlab/tests/objects/test_projects.py @@ -1,547 +1,225 @@ -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) - - -@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) - - -@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) - - -@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) - - -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) +""" +GitLab API: https://docs.gitlab.com/ce/api/projects.html +""" +import pytest +import responses -class TestProjectSnippets(TestProject): - def test_list_project_snippets(self): - title = "Example Snippet Title" - visibility = "private" +from gitlab.v4.objects import Project - @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() - self.assertEqual(len(snippets), 1) - self.assertEqual(snippets[0].title, title) - self.assertEqual(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) - self.assertEqual(snippet.title, title) - self.assertEqual(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", + +project_content = {"name": "name", "id": 1} + + +@pytest.fixture +def resp_get_project(): + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1", + json=project_content, + content_type="application/json", + status=200, ) - 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, - } - ) - self.assertEqual(snippet.title, title) - self.assertEqual(snippet.visibility, visibility) - title = "new-title" - snippet.title = title - snippet.save() - self.assertEqual(snippet.title, title) - self.assertEqual(snippet.visibility, visibility) - - -class TestProjectExport(TestProject): - @with_httmock(resp_create_export) - def test_create_project_export(self): - export = self.project.exports.create() - self.assertEqual(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() - self.assertEqual(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() - self.assertIsInstance(download, bytes) - self.assertEqual(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") - self.assertEqual(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() - self.assertEqual(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) - self.assertIsInstance(ret, dict) - self.assertEqual(ret["name"], name) - self.assertEqual(ret["full_path"], "/".join((base_path, name))) - self.assertTrue(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() - self.assertIsInstance(mirrors, list) - self.assertIsInstance(mirrors[0], ProjectRemoteMirror) - self.assertTrue(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"}) - self.assertIsInstance(mirror, ProjectRemoteMirror) - self.assertEqual(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() - self.assertEqual(mirror.update_status, "finished") - self.assertTrue(mirror.only_protected_branches) - - -class TestProjectServices(TestProject): - @with_httmock(resp_get_active_services) - def test_list_active_services(self): - services = self.project.services.list() - self.assertIsInstance(services, list) - self.assertIsInstance(services[0], ProjectService) - self.assertTrue(services[0].active) - self.assertTrue(services[0].push_events) - - def test_list_available_services(self): - services = self.project.services.available() - self.assertIsInstance(services, list) - self.assertIsInstance(services[0], str) - - @with_httmock(resp_get_service) - def test_get_service(self): - service = self.project.services.get("pipelines-email") - self.assertIsInstance(service, ProjectService) - self.assertEqual(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() - self.assertEqual(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} + yield rsps + + +@pytest.fixture +def resp_list_projects(): + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects", + json=[project_content], + content_type="application/json", + status=200, ) - 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"]) + yield rsps + + +def test_get_project(gl, resp_get_project): + data = gl.projects.get(1) + assert isinstance(data, Project) + assert data.name == "name" + assert data.id == 1 + + +def test_list_projects(gl, resp_list_projects): + projects = gl.projects.list() + assert isinstance(projects[0], Project) + assert projects[0].name == "name" + + +@pytest.mark.skip(reason="missing test") +def test_list_user_projects(gl): + pass + + +@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 + + +@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..1ac35a2 --- /dev/null +++ b/gitlab/tests/objects/test_remote_mirrors.py @@ -0,0 +1,72 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/remote_mirrors.html +""" + +import pytest +import responses + +from gitlab.v4.objects import ProjectRemoteMirror + + +@pytest.fixture +def resp_remote_mirrors(): + content = { + "enabled": True, + "id": 1, + "last_error": None, + "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": "none", + "url": "https://*****:*****@gitlab.com/gitlab-org/security/gitlab.git", + } + + with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1/remote_mirrors", + json=[content], + content_type="application/json", + status=200, + ) + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/projects/1/remote_mirrors", + json=content, + content_type="application/json", + status=200, + ) + + updated_content = dict(content) + updated_content["update_status"] = "finished" + + rsps.add( + method=responses.PUT, + url="http://localhost/api/v4/projects/1/remote_mirrors/1", + json=updated_content, + content_type="application/json", + status=200, + ) + yield rsps + + +def test_list_project_remote_mirrors(project, resp_remote_mirrors): + mirrors = project.remote_mirrors.list() + assert isinstance(mirrors, list) + assert isinstance(mirrors[0], ProjectRemoteMirror) + assert mirrors[0].enabled + + +def test_create_project_remote_mirror(project, resp_remote_mirrors): + mirror = project.remote_mirrors.create({"url": "https://example.com"}) + assert isinstance(mirror, ProjectRemoteMirror) + assert mirror.update_status == "none" + + +def test_update_project_remote_mirror(project, resp_remote_mirrors): + 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_runners.py b/gitlab/tests/objects/test_runners.py index 2f86bef..490ba36 100644 --- a/gitlab/tests/objects/test_runners.py +++ b/gitlab/tests/objects/test_runners.py @@ -1,9 +1,9 @@ -import unittest +import re + +import pytest import responses + import gitlab -import pytest -import re -from .mocks import * # noqa runner_detail = { diff --git a/gitlab/tests/objects/test_services.py b/gitlab/tests/objects/test_services.py new file mode 100644 index 0000000..5b2bcb8 --- /dev/null +++ b/gitlab/tests/objects/test_services.py @@ -0,0 +1,93 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/services.html +""" + +import pytest +import responses + +from gitlab.v4.objects import ProjectService + + +@pytest.fixture +def resp_service(): + 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, + } + + with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1/services", + json=[content], + content_type="application/json", + status=200, + ) + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1/services", + json=content, + content_type="application/json", + status=200, + ) + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1/services/pipelines-email", + json=content, + content_type="application/json", + status=200, + ) + updated_content = dict(content) + updated_content["issues_events"] = False + rsps.add( + method=responses.PUT, + url="http://localhost/api/v4/projects/1/services/pipelines-email", + json=updated_content, + content_type="application/json", + status=200, + ) + yield rsps + + +def test_list_active_services(project, resp_service): + 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, resp_service): + services = project.services.available() + assert isinstance(services, list) + assert isinstance(services[0], str) + + +def test_get_service(project, resp_service): + service = project.services.get("pipelines-email") + assert isinstance(service, ProjectService) + assert service.push_events is True + + +def test_update_service(project, resp_service): + service = project.services.get("pipelines-email") + service.issues_events = False + service.save() + assert service.issues_events is False diff --git a/gitlab/tests/objects/test_snippets.py b/gitlab/tests/objects/test_snippets.py new file mode 100644 index 0000000..7e8afc2 --- /dev/null +++ b/gitlab/tests/objects/test_snippets.py @@ -0,0 +1,90 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/project_snippets.html + https://docs.gitlab.com/ee/api/snippets.html (todo) +""" + +import pytest +import responses + + +title = "Example Snippet Title" +visibility = "private" +new_title = "new-title" + + +@pytest.fixture +def resp_snippet(): + content = { + "title": title, + "description": "More verbose snippet description", + "file_name": "example.txt", + "content": "source code with multiple lines", + "visibility": visibility, + } + + with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1/snippets", + json=[content], + content_type="application/json", + status=200, + ) + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1/snippets/1", + json=content, + content_type="application/json", + status=200, + ) + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/projects/1/snippets", + json=content, + content_type="application/json", + status=200, + ) + + updated_content = dict(content) + updated_content["title"] = new_title + updated_content["visibility"] = visibility + + rsps.add( + method=responses.PUT, + url="http://localhost/api/v4/projects/1/snippets", + json=updated_content, + content_type="application/json", + status=200, + ) + yield rsps + + +def test_list_project_snippets(project, resp_snippet): + snippets = project.snippets.list() + assert len(snippets) == 1 + assert snippets[0].title == title + assert snippets[0].visibility == visibility + + +def test_get_project_snippet(project, resp_snippet): + snippet = project.snippets.get(1) + assert snippet.title == title + assert snippet.visibility == visibility + + +def test_create_update_project_snippets(project, resp_snippet): + 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..539af7b --- /dev/null +++ b/gitlab/tests/objects/test_submodules.py @@ -0,0 +1,48 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/repository_submodules.html +""" +import pytest +import responses + +from gitlab.v4.objects import Project + + +@pytest.fixture +def resp_update_submodule(): + 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": None, + } + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.PUT, + url="http://localhost/api/v4/projects/1/repository/submodules/foo%2Fbar", + json=content, + content_type="application/json", + status=200, + ) + yield rsps + + +def test_update_submodule(project, resp_update_submodule): + 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..07bb680 --- /dev/null +++ b/gitlab/tests/objects/test_todos.py @@ -0,0 +1,63 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/todos.html +""" + +import json +import os + +import pytest +import responses + +from gitlab.v4.objects import Todo + + +with open(os.path.dirname(__file__) + "/../data/todo.json", "r") as json_file: + todo_content = json_file.read() + json_content = json.loads(todo_content) + + +@pytest.fixture +def resp_todo(): + with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/todos", + json=json_content, + content_type="application/json", + status=200, + ) + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/todos/102/mark_as_done", + json=json_content[0], + content_type="application/json", + status=200, + ) + yield rsps + + +@pytest.fixture +def resp_mark_all_as_done(): + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/todos/mark_as_done", + json={}, + content_type="application/json", + status=204, + ) + yield rsps + + +def test_todo(gl, resp_todo): + 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() + + +def test_todo_mark_all_as_done(gl, resp_mark_all_as_done): + 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..ec282cf --- /dev/null +++ b/gitlab/tests/objects/test_users.py @@ -0,0 +1,120 @@ +""" +GitLab API: https://docs.gitlab.com/ce/api/users.html +""" +import pytest +import responses + +from gitlab.v4.objects import User, UserMembership, UserStatus + + +@pytest.fixture +def resp_get_user(): + content = { + "name": "name", + "id": 1, + "password": "password", + "username": "username", + "email": "email", + } + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/users/1", + json=content, + content_type="application/json", + status=200, + ) + yield rsps + + +@pytest.fixture +def resp_get_user_memberships(): + 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", + }, + ] + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/users/1/memberships", + json=content, + content_type="application/json", + status=200, + ) + yield rsps + + +@pytest.fixture +def resp_activate(): + with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/users/1/activate", + json={}, + content_type="application/json", + status=201, + ) + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/users/1/deactivate", + json={}, + content_type="application/json", + status=201, + ) + yield rsps + + +@pytest.fixture +def resp_get_user_status(): + content = { + "message": "test", + "message_html": "<h1>Message</h1>", + "emoji": "thumbsup", + } + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/users/1/status", + json=content, + content_type="application/json", + status=200, + ) + yield rsps + + +def test_get_user(gl, resp_get_user): + user = gl.users.get(1) + assert isinstance(user, User) + assert user.name == "name" + assert user.id == 1 + + +def test_user_memberships(user, resp_get_user_memberships): + memberships = user.memberships.list() + assert isinstance(memberships[0], UserMembership) + assert memberships[0].source_type == "Project" + + +def test_user_status(user, resp_get_user_status): + status = user.status.get() + assert isinstance(status, UserStatus) + assert status.message == "test" + assert status.emoji == "thumbsup" + + +def test_user_activate_deactivate(user, resp_activate): + user.activate() + user.deactivate() |
