summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/__init__.py0
-rw-r--r--tests/functional/__init__.py0
-rw-r--r--tests/functional/api/__init__.py0
-rw-r--r--tests/functional/api/test_clusters.py46
-rw-r--r--tests/functional/api/test_current_user.py42
-rw-r--r--tests/functional/api/test_deploy_keys.py12
-rw-r--r--tests/functional/api/test_deploy_tokens.py36
-rw-r--r--tests/functional/api/test_gitlab.py183
-rw-r--r--tests/functional/api/test_groups.py223
-rw-r--r--tests/functional/api/test_import_export.py66
-rw-r--r--tests/functional/api/test_issues.py93
-rw-r--r--tests/functional/api/test_keys.py42
-rw-r--r--tests/functional/api/test_merge_requests.py205
-rw-r--r--tests/functional/api/test_packages.py62
-rw-r--r--tests/functional/api/test_projects.py268
-rw-r--r--tests/functional/api/test_releases.py63
-rw-r--r--tests/functional/api/test_repository.py126
-rw-r--r--tests/functional/api/test_snippets.py74
-rw-r--r--tests/functional/api/test_users.py170
-rw-r--r--tests/functional/api/test_variables.py48
-rw-r--r--tests/functional/cli/__init__.py0
-rw-r--r--tests/functional/cli/conftest.py21
-rw-r--r--tests/functional/cli/test_cli_artifacts.py49
-rw-r--r--tests/functional/cli/test_cli_packages.py60
-rw-r--r--tests/functional/cli/test_cli_v4.py715
-rw-r--r--tests/functional/cli/test_cli_variables.py19
-rw-r--r--tests/functional/conftest.py489
-rwxr-xr-xtests/functional/ee-test.py158
-rw-r--r--tests/functional/fixtures/.env2
-rw-r--r--tests/functional/fixtures/avatar.pngbin592 -> 0 bytes
-rw-r--r--tests/functional/fixtures/docker-compose.yml46
-rw-r--r--tests/functional/fixtures/set_token.rb9
-rw-r--r--tests/smoke/__init__.py0
-rw-r--r--tests/smoke/test_dists.py33
-rw-r--r--tests/unit/__init__.py0
-rw-r--r--tests/unit/conftest.py84
-rw-r--r--tests/unit/data/todo.json75
-rw-r--r--tests/unit/mixins/__init__.py0
-rw-r--r--tests/unit/mixins/test_meta_mixins.py58
-rw-r--r--tests/unit/mixins/test_mixin_methods.py300
-rw-r--r--tests/unit/mixins/test_object_mixins_attributes.py79
-rw-r--r--tests/unit/objects/__init__.py0
-rw-r--r--tests/unit/objects/conftest.py70
-rw-r--r--tests/unit/objects/test_appearance.py65
-rw-r--r--tests/unit/objects/test_applications.py44
-rw-r--r--tests/unit/objects/test_audit_events.py109
-rw-r--r--tests/unit/objects/test_badges.py210
-rw-r--r--tests/unit/objects/test_bridges.py109
-rw-r--r--tests/unit/objects/test_commits.py115
-rw-r--r--tests/unit/objects/test_deploy_tokens.py45
-rw-r--r--tests/unit/objects/test_deployments.py50
-rw-r--r--tests/unit/objects/test_environments.py30
-rw-r--r--tests/unit/objects/test_groups.py155
-rw-r--r--tests/unit/objects/test_hooks.py209
-rw-r--r--tests/unit/objects/test_issues.py88
-rw-r--r--tests/unit/objects/test_job_artifacts.py30
-rw-r--r--tests/unit/objects/test_jobs.py96
-rw-r--r--tests/unit/objects/test_keys.py54
-rw-r--r--tests/unit/objects/test_members.py58
-rw-r--r--tests/unit/objects/test_merge_request_pipelines.py53
-rw-r--r--tests/unit/objects/test_merge_requests.py56
-rw-r--r--tests/unit/objects/test_mro.py122
-rw-r--r--tests/unit/objects/test_packages.py252
-rw-r--r--tests/unit/objects/test_personal_access_tokens.py94
-rw-r--r--tests/unit/objects/test_pipeline_schedules.py62
-rw-r--r--tests/unit/objects/test_pipelines.py146
-rw-r--r--tests/unit/objects/test_project_access_tokens.py113
-rw-r--r--tests/unit/objects/test_project_import_export.py112
-rw-r--r--tests/unit/objects/test_project_merge_request_approvals.py317
-rw-r--r--tests/unit/objects/test_project_statistics.py28
-rw-r--r--tests/unit/objects/test_projects.py237
-rw-r--r--tests/unit/objects/test_releases.py170
-rw-r--r--tests/unit/objects/test_remote_mirrors.py72
-rw-r--r--tests/unit/objects/test_repositories.py49
-rw-r--r--tests/unit/objects/test_resource_label_events.py105
-rw-r--r--tests/unit/objects/test_resource_milestone_events.py73
-rw-r--r--tests/unit/objects/test_resource_state_events.py104
-rw-r--r--tests/unit/objects/test_runners.py282
-rw-r--r--tests/unit/objects/test_services.py93
-rw-r--r--tests/unit/objects/test_snippets.py89
-rw-r--r--tests/unit/objects/test_submodules.py46
-rw-r--r--tests/unit/objects/test_todos.py62
-rw-r--r--tests/unit/objects/test_users.py217
-rw-r--r--tests/unit/objects/test_variables.py192
-rw-r--r--tests/unit/test_base.py179
-rw-r--r--tests/unit/test_cli.py157
-rw-r--r--tests/unit/test_config.py317
-rw-r--r--tests/unit/test_exceptions.py18
-rw-r--r--tests/unit/test_gitlab.py196
-rw-r--r--tests/unit/test_gitlab_auth.py85
-rw-r--r--tests/unit/test_gitlab_http_methods.py406
-rw-r--r--tests/unit/test_types.py74
-rw-r--r--tests/unit/test_utils.py42
93 files changed, 0 insertions, 10113 deletions
diff --git a/tests/__init__.py b/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tests/__init__.py
+++ /dev/null
diff --git a/tests/functional/__init__.py b/tests/functional/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tests/functional/__init__.py
+++ /dev/null
diff --git a/tests/functional/api/__init__.py b/tests/functional/api/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tests/functional/api/__init__.py
+++ /dev/null
diff --git a/tests/functional/api/test_clusters.py b/tests/functional/api/test_clusters.py
deleted file mode 100644
index 8930aad..0000000
--- a/tests/functional/api/test_clusters.py
+++ /dev/null
@@ -1,46 +0,0 @@
-def test_project_clusters(project):
- project.clusters.create(
- {
- "name": "cluster1",
- "platform_kubernetes_attributes": {
- "api_url": "http://url",
- "token": "tokenval",
- },
- }
- )
- clusters = project.clusters.list()
- assert len(clusters) == 1
-
- cluster = clusters[0]
- cluster.platform_kubernetes_attributes = {"api_url": "http://newurl"}
- cluster.save()
-
- cluster = project.clusters.list()[0]
- assert cluster.platform_kubernetes["api_url"] == "http://newurl"
-
- cluster.delete()
- assert len(project.clusters.list()) == 0
-
-
-def test_group_clusters(group):
- group.clusters.create(
- {
- "name": "cluster1",
- "platform_kubernetes_attributes": {
- "api_url": "http://url",
- "token": "tokenval",
- },
- }
- )
- clusters = group.clusters.list()
- assert len(clusters) == 1
-
- cluster = clusters[0]
- cluster.platform_kubernetes_attributes = {"api_url": "http://newurl"}
- cluster.save()
-
- cluster = group.clusters.list()[0]
- assert cluster.platform_kubernetes["api_url"] == "http://newurl"
-
- cluster.delete()
- assert len(group.clusters.list()) == 0
diff --git a/tests/functional/api/test_current_user.py b/tests/functional/api/test_current_user.py
deleted file mode 100644
index 5802457..0000000
--- a/tests/functional/api/test_current_user.py
+++ /dev/null
@@ -1,42 +0,0 @@
-def test_current_user_email(gl):
- gl.auth()
- mail = gl.user.emails.create({"email": "current@user.com"})
- assert len(gl.user.emails.list()) == 1
-
- mail.delete()
- assert len(gl.user.emails.list()) == 0
-
-
-def test_current_user_gpg_keys(gl, GPG_KEY):
- gl.auth()
- gkey = gl.user.gpgkeys.create({"key": GPG_KEY})
- assert len(gl.user.gpgkeys.list()) == 1
-
- # Seems broken on the gitlab side
- gkey = gl.user.gpgkeys.get(gkey.id)
- gkey.delete()
- assert len(gl.user.gpgkeys.list()) == 0
-
-
-def test_current_user_ssh_keys(gl, SSH_KEY):
- gl.auth()
- key = gl.user.keys.create({"title": "testkey", "key": SSH_KEY})
- assert len(gl.user.keys.list()) == 1
-
- key.delete()
- assert len(gl.user.keys.list()) == 0
-
-
-def test_current_user_status(gl):
- gl.auth()
- message = "Test"
- emoji = "thumbsup"
- status = gl.user.status.get()
-
- status.message = message
- status.emoji = emoji
- status.save()
-
- new_status = gl.user.status.get()
- assert new_status.message == message
- assert new_status.emoji == emoji
diff --git a/tests/functional/api/test_deploy_keys.py b/tests/functional/api/test_deploy_keys.py
deleted file mode 100644
index 18828a2..0000000
--- a/tests/functional/api/test_deploy_keys.py
+++ /dev/null
@@ -1,12 +0,0 @@
-def test_project_deploy_keys(gl, project, DEPLOY_KEY):
- deploy_key = project.keys.create({"title": "foo@bar", "key": DEPLOY_KEY})
- project_keys = list(project.keys.list())
- assert len(project_keys) == 1
-
- project2 = gl.projects.create({"name": "deploy-key-project"})
- project2.keys.enable(deploy_key.id)
- assert len(project2.keys.list()) == 1
-
- project2.keys.delete(deploy_key.id)
- assert len(project2.keys.list()) == 0
- project2.delete()
diff --git a/tests/functional/api/test_deploy_tokens.py b/tests/functional/api/test_deploy_tokens.py
deleted file mode 100644
index efcf8b1..0000000
--- a/tests/functional/api/test_deploy_tokens.py
+++ /dev/null
@@ -1,36 +0,0 @@
-def test_project_deploy_tokens(gl, project):
- deploy_token = project.deploytokens.create(
- {
- "name": "foo",
- "username": "bar",
- "expires_at": "2022-01-01",
- "scopes": ["read_registry"],
- }
- )
- assert len(project.deploytokens.list()) == 1
- assert gl.deploytokens.list() == project.deploytokens.list()
-
- assert project.deploytokens.list()[0].name == "foo"
- assert project.deploytokens.list()[0].expires_at == "2022-01-01T00:00:00.000Z"
- assert project.deploytokens.list()[0].scopes == ["read_registry"]
- assert project.deploytokens.list()[0].username == "bar"
-
- deploy_token.delete()
- assert len(project.deploytokens.list()) == 0
- assert len(gl.deploytokens.list()) == 0
-
-
-def test_group_deploy_tokens(gl, group):
- deploy_token = group.deploytokens.create(
- {
- "name": "foo",
- "scopes": ["read_registry"],
- }
- )
-
- assert len(group.deploytokens.list()) == 1
- assert gl.deploytokens.list() == group.deploytokens.list()
-
- deploy_token.delete()
- assert len(group.deploytokens.list()) == 0
- assert len(gl.deploytokens.list()) == 0
diff --git a/tests/functional/api/test_gitlab.py b/tests/functional/api/test_gitlab.py
deleted file mode 100644
index 7a70a56..0000000
--- a/tests/functional/api/test_gitlab.py
+++ /dev/null
@@ -1,183 +0,0 @@
-import pytest
-
-import gitlab
-
-
-def test_auth_from_config(gl, temp_dir):
- """Test token authentication from config file"""
- test_gitlab = gitlab.Gitlab.from_config(
- config_files=[temp_dir / "python-gitlab.cfg"]
- )
- test_gitlab.auth()
- assert isinstance(test_gitlab.user, gitlab.v4.objects.CurrentUser)
-
-
-def test_broadcast_messages(gl):
- msg = gl.broadcastmessages.create({"message": "this is the message"})
- msg.color = "#444444"
- msg.save()
- msg_id = msg.id
-
- msg = gl.broadcastmessages.list(all=True)[0]
- assert msg.color == "#444444"
-
- msg = gl.broadcastmessages.get(msg_id)
- assert msg.color == "#444444"
-
- msg.delete()
- assert len(gl.broadcastmessages.list()) == 0
-
-
-def test_markdown(gl):
- html = gl.markdown("foo")
- assert "foo" in html
-
-
-def test_lint(gl):
- success, errors = gl.lint("Invalid")
- assert success is False
- assert errors
-
-
-def test_sidekiq_queue_metrics(gl):
- out = gl.sidekiq.queue_metrics()
- assert isinstance(out, dict)
- assert "pages" in out["queues"]
-
-
-def test_sidekiq_process_metrics(gl):
- out = gl.sidekiq.process_metrics()
- assert isinstance(out, dict)
- assert "hostname" in out["processes"][0]
-
-
-def test_sidekiq_job_stats(gl):
- out = gl.sidekiq.job_stats()
- assert isinstance(out, dict)
- assert "processed" in out["jobs"]
-
-
-def test_sidekiq_compound_metrics(gl):
- out = gl.sidekiq.compound_metrics()
- assert isinstance(out, dict)
- assert "jobs" in out
- assert "processes" in out
- assert "queues" in out
-
-
-def test_gitlab_settings(gl):
- settings = gl.settings.get()
- settings.default_projects_limit = 42
- settings.save()
- settings = gl.settings.get()
- assert settings.default_projects_limit == 42
-
-
-def test_template_dockerfile(gl):
- assert gl.dockerfiles.list()
-
- dockerfile = gl.dockerfiles.get("Node")
- assert dockerfile.content is not None
-
-
-def test_template_gitignore(gl):
- assert gl.gitignores.list()
- gitignore = gl.gitignores.get("Node")
- assert gitignore.content is not None
-
-
-def test_template_gitlabciyml(gl):
- assert gl.gitlabciymls.list()
- gitlabciyml = gl.gitlabciymls.get("Nodejs")
- assert gitlabciyml.content is not None
-
-
-def test_template_license(gl):
- assert gl.licenses.list()
- license = gl.licenses.get(
- "bsd-2-clause", project="mytestproject", fullname="mytestfullname"
- )
- assert "mytestfullname" in license.content
-
-
-def test_hooks(gl):
- hook = gl.hooks.create({"url": "http://whatever.com"})
- assert len(gl.hooks.list()) == 1
-
- hook.delete()
- assert len(gl.hooks.list()) == 0
-
-
-def test_namespaces(gl):
- namespace = gl.namespaces.list(all=True)
- assert namespace
-
- namespace = gl.namespaces.list(search="root", all=True)[0]
- assert namespace.kind == "user"
-
-
-def test_notification_settings(gl):
- settings = gl.notificationsettings.get()
- settings.level = gitlab.NOTIFICATION_LEVEL_WATCH
- settings.save()
-
- settings = gl.notificationsettings.get()
- assert settings.level == gitlab.NOTIFICATION_LEVEL_WATCH
-
-
-def test_user_activities(gl):
- activities = gl.user_activities.list(query_parameters={"from": "2019-01-01"})
- assert isinstance(activities, list)
-
-
-def test_events(gl):
- events = gl.events.list()
- assert isinstance(events, list)
-
-
-@pytest.mark.skip
-def test_features(gl):
- feat = gl.features.set("foo", 30)
- assert feat.name == "foo"
- assert len(gl.features.list()) == 1
-
- feat.delete()
- assert len(gl.features.list()) == 0
-
-
-def test_pagination(gl, project):
- project2 = gl.projects.create({"name": "project-page-2"})
-
- list1 = gl.projects.list(per_page=1, page=1)
- list2 = gl.projects.list(per_page=1, page=2)
- assert len(list1) == 1
- assert len(list2) == 1
- assert list1[0].id != list2[0].id
-
- project2.delete()
-
-
-def test_rate_limits(gl):
- settings = gl.settings.get()
- settings.throttle_authenticated_api_enabled = True
- settings.throttle_authenticated_api_requests_per_period = 1
- settings.throttle_authenticated_api_period_in_seconds = 3
- settings.save()
-
- projects = list()
- for i in range(0, 20):
- projects.append(gl.projects.create({"name": str(i) + "ok"}))
-
- with pytest.raises(gitlab.GitlabCreateError) as e:
- for i in range(20, 40):
- projects.append(
- gl.projects.create(
- {"name": str(i) + "shouldfail"}, obey_rate_limit=False
- )
- )
-
- assert "Retry later" in str(e.value)
-
- settings.throttle_authenticated_api_enabled = False
- settings.save()
- [project.delete() for project in projects]
diff --git a/tests/functional/api/test_groups.py b/tests/functional/api/test_groups.py
deleted file mode 100644
index 665c933..0000000
--- a/tests/functional/api/test_groups.py
+++ /dev/null
@@ -1,223 +0,0 @@
-import pytest
-
-import gitlab
-
-
-def test_groups(gl):
- # TODO: This one still needs lots of work
- user = gl.users.create(
- {
- "email": "user@test.com",
- "username": "user",
- "name": "user",
- "password": "user_pass",
- }
- )
- user2 = gl.users.create(
- {
- "email": "user2@test.com",
- "username": "user2",
- "name": "user2",
- "password": "user2_pass",
- }
- )
- group1 = gl.groups.create({"name": "group1", "path": "group1"})
- group2 = gl.groups.create({"name": "group2", "path": "group2"})
-
- p_id = gl.groups.list(search="group2")[0].id
- group3 = gl.groups.create({"name": "group3", "path": "group3", "parent_id": p_id})
- group4 = gl.groups.create({"name": "group4", "path": "group4"})
-
- assert len(gl.groups.list()) == 4
- assert len(gl.groups.list(search="oup1")) == 1
- assert group3.parent_id == p_id
- assert group2.subgroups.list()[0].id == group3.id
- assert group2.descendant_groups.list()[0].id == group3.id
-
- filtered_groups = gl.groups.list(skip_groups=[group3.id, group4.id])
- assert group3 not in filtered_groups
- assert group3 not in filtered_groups
-
- group1.members.create(
- {"access_level": gitlab.const.OWNER_ACCESS, "user_id": user.id}
- )
- group1.members.create(
- {"access_level": gitlab.const.GUEST_ACCESS, "user_id": user2.id}
- )
- group2.members.create(
- {"access_level": gitlab.const.OWNER_ACCESS, "user_id": user2.id}
- )
-
- group4.share(group1.id, gitlab.const.DEVELOPER_ACCESS)
- group4.share(group2.id, gitlab.const.MAINTAINER_ACCESS)
- # Reload group4 to have updated shared_with_groups
- group4 = gl.groups.get(group4.id)
- assert len(group4.shared_with_groups) == 2
- group4.unshare(group1.id)
- # Reload group4 to have updated shared_with_groups
- group4 = gl.groups.get(group4.id)
- assert len(group4.shared_with_groups) == 1
-
- # User memberships (admin only)
- memberships1 = user.memberships.list()
- assert len(memberships1) == 1
-
- memberships2 = user2.memberships.list()
- assert len(memberships2) == 2
-
- membership = memberships1[0]
- assert membership.source_type == "Namespace"
- assert membership.access_level == gitlab.const.OWNER_ACCESS
-
- project_memberships = user.memberships.list(type="Project")
- assert len(project_memberships) == 0
-
- group_memberships = user.memberships.list(type="Namespace")
- assert len(group_memberships) == 1
-
- with pytest.raises(gitlab.GitlabListError) as e:
- membership = user.memberships.list(type="Invalid")
- assert "type does not have a valid value" in str(e.value)
-
- with pytest.raises(gitlab.GitlabListError) as e:
- user.memberships.list(sudo=user.name)
- assert "403 Forbidden" in str(e.value)
-
- # Administrator belongs to the groups
- assert len(group1.members.list()) == 3
- assert len(group2.members.list()) == 2
-
- group1.members.delete(user.id)
- assert len(group1.members.list()) == 2
- assert len(group1.members_all.list())
- member = group1.members.get(user2.id)
- member.access_level = gitlab.const.OWNER_ACCESS
- member.save()
- member = group1.members.get(user2.id)
- assert member.access_level == gitlab.const.OWNER_ACCESS
-
- group2.members.delete(gl.user.id)
-
-
-@pytest.mark.skip(reason="Commented out in legacy test")
-def test_group_labels(group):
- group.labels.create({"name": "foo", "description": "bar", "color": "#112233"})
- label = group.labels.get("foo")
- assert label.description == "bar"
-
- label.description = "baz"
- label.save()
- label = group.labels.get("foo")
- assert label.description == "baz"
- assert len(group.labels.list()) == 1
-
- label.delete()
- assert len(group.labels.list()) == 0
-
-
-def test_group_notification_settings(group):
- settings = group.notificationsettings.get()
- settings.level = "disabled"
- settings.save()
-
- settings = group.notificationsettings.get()
- assert settings.level == "disabled"
-
-
-def test_group_badges(group):
- badge_image = "http://example.com"
- badge_link = "http://example/img.svg"
- badge = group.badges.create({"link_url": badge_link, "image_url": badge_image})
- assert len(group.badges.list()) == 1
-
- badge.image_url = "http://another.example.com"
- badge.save()
-
- badge = group.badges.get(badge.id)
- assert badge.image_url == "http://another.example.com"
-
- badge.delete()
- assert len(group.badges.list()) == 0
-
-
-def test_group_milestones(group):
- milestone = group.milestones.create({"title": "groupmilestone1"})
- assert len(group.milestones.list()) == 1
-
- milestone.due_date = "2020-01-01T00:00:00Z"
- milestone.save()
- milestone.state_event = "close"
- milestone.save()
-
- milestone = group.milestones.get(milestone.id)
- assert milestone.state == "closed"
- assert len(milestone.issues()) == 0
- assert len(milestone.merge_requests()) == 0
-
-
-def test_group_custom_attributes(gl, group):
- attrs = group.customattributes.list()
- assert len(attrs) == 0
-
- attr = group.customattributes.set("key", "value1")
- assert len(gl.groups.list(custom_attributes={"key": "value1"})) == 1
- assert attr.key == "key"
- assert attr.value == "value1"
- assert len(group.customattributes.list()) == 1
-
- attr = group.customattributes.set("key", "value2")
- attr = group.customattributes.get("key")
- assert attr.value == "value2"
- assert len(group.customattributes.list()) == 1
-
- attr.delete()
- assert len(group.customattributes.list()) == 0
-
-
-def test_group_subgroups_projects(gl, user):
- # TODO: fixture factories
- group1 = gl.groups.list(search="group1")[0]
- group2 = gl.groups.list(search="group2")[0]
-
- group3 = gl.groups.create(
- {"name": "subgroup1", "path": "subgroup1", "parent_id": group1.id}
- )
- group4 = gl.groups.create(
- {"name": "subgroup2", "path": "subgroup2", "parent_id": group2.id}
- )
-
- gr1_project = gl.projects.create({"name": "gr1_project", "namespace_id": group1.id})
- gr2_project = gl.projects.create({"name": "gr2_project", "namespace_id": group3.id})
-
- assert group3.parent_id == group1.id
- assert group4.parent_id == group2.id
- assert gr1_project.namespace["id"] == group1.id
- assert gr2_project.namespace["parent_id"] == group1.id
-
-
-@pytest.mark.skip
-def test_group_wiki(group):
- content = "Group Wiki page content"
- wiki = group.wikis.create({"title": "groupwikipage", "content": content})
- assert len(group.wikis.list()) == 1
-
- wiki = group.wikis.get(wiki.slug)
- assert wiki.content == content
-
- wiki.content = "new content"
- wiki.save()
- wiki.delete()
- assert len(group.wikis.list()) == 0
-
-
-@pytest.mark.skip(reason="EE feature")
-def test_group_hooks(group):
- hook = group.hooks.create({"url": "http://hook.url"})
- assert len(group.hooks.list()) == 1
-
- hook.note_events = True
- hook.save()
-
- hook = group.hooks.get(hook.id)
- assert hook.note_events is True
- hook.delete()
diff --git a/tests/functional/api/test_import_export.py b/tests/functional/api/test_import_export.py
deleted file mode 100644
index d4bdd19..0000000
--- a/tests/functional/api/test_import_export.py
+++ /dev/null
@@ -1,66 +0,0 @@
-import time
-
-import gitlab
-
-
-def test_group_import_export(gl, group, temp_dir):
- export = group.exports.create()
- assert export.message == "202 Accepted"
-
- # We cannot check for export_status with group export API
- time.sleep(10)
-
- import_archive = temp_dir / "gitlab-group-export.tgz"
- import_path = "imported_group"
- import_name = "Imported Group"
-
- with open(import_archive, "wb") as f:
- export.download(streamed=True, action=f.write)
-
- with open(import_archive, "rb") as f:
- output = gl.groups.import_group(f, import_path, import_name)
- assert output["message"] == "202 Accepted"
-
- # We cannot check for returned ID with group import API
- time.sleep(10)
- group_import = gl.groups.get(import_path)
-
- assert group_import.path == import_path
- assert group_import.name == import_name
-
-
-def test_project_import_export(gl, project, temp_dir):
- export = project.exports.create()
- assert export.message == "202 Accepted"
-
- export = project.exports.get()
- assert isinstance(export, gitlab.v4.objects.ProjectExport)
-
- count = 0
- while export.export_status != "finished":
- time.sleep(1)
- export.refresh()
- count += 1
- if count == 15:
- raise Exception("Project export taking too much time")
-
- with open(temp_dir / "gitlab-export.tgz", "wb") as f:
- export.download(streamed=True, action=f.write)
-
- output = gl.projects.import_project(
- open(temp_dir / "gitlab-export.tgz", "rb"),
- "imported_project",
- name="Imported Project",
- )
- project_import = gl.projects.get(output["id"], lazy=True).imports.get()
-
- assert project_import.path == "imported_project"
- assert project_import.name == "Imported Project"
-
- count = 0
- while project_import.import_status != "finished":
- time.sleep(1)
- project_import.refresh()
- count += 1
- if count == 15:
- raise Exception("Project import taking too much time")
diff --git a/tests/functional/api/test_issues.py b/tests/functional/api/test_issues.py
deleted file mode 100644
index 64db46e..0000000
--- a/tests/functional/api/test_issues.py
+++ /dev/null
@@ -1,93 +0,0 @@
-import gitlab
-
-
-def test_create_issue(project):
- issue = project.issues.create({"title": "my issue 1"})
- issue2 = project.issues.create({"title": "my issue 2"})
- issue_iids = [issue.iid for issue in project.issues.list()]
- assert len(issue_iids) == 2
-
- # Test 'iids' as a list
- assert len(project.issues.list(iids=issue_iids)) == 2
-
- issue2.state_event = "close"
- issue2.save()
- assert len(project.issues.list(state="closed")) == 1
- assert len(project.issues.list(state="opened")) == 1
-
- assert isinstance(issue.user_agent_detail(), dict)
- assert issue.user_agent_detail()["user_agent"]
- assert issue.participants()
- assert type(issue.closed_by()) == list
- assert type(issue.related_merge_requests()) == list
-
-
-def test_issue_notes(issue):
- size = len(issue.notes.list())
-
- note = issue.notes.create({"body": "This is an issue note"})
- assert len(issue.notes.list()) == size + 1
-
- emoji = note.awardemojis.create({"name": "tractor"})
- assert len(note.awardemojis.list()) == 1
-
- emoji.delete()
- assert len(note.awardemojis.list()) == 0
-
- note.delete()
- assert len(issue.notes.list()) == size
-
-
-def test_issue_labels(project, issue):
- project.labels.create({"name": "label2", "color": "#aabbcc"})
- issue.labels = ["label2"]
- issue.save()
-
- assert issue in project.issues.list(labels=["label2"])
- assert issue in project.issues.list(labels="label2")
- assert issue in project.issues.list(labels="Any")
- assert issue not in project.issues.list(labels="None")
-
-
-def test_issue_events(issue):
- events = issue.resourcelabelevents.list()
- assert isinstance(events, list)
-
- event = issue.resourcelabelevents.get(events[0].id)
- assert isinstance(event, gitlab.v4.objects.ProjectIssueResourceLabelEvent)
-
-
-def test_issue_milestones(project, milestone):
- data = {"title": "my issue 1", "milestone_id": milestone.id}
- issue = project.issues.create(data)
- assert milestone.issues().next().title == "my issue 1"
-
- milestone_events = issue.resourcemilestoneevents.list()
- assert isinstance(milestone_events, list)
-
- milestone_event = issue.resourcemilestoneevents.get(milestone_events[0].id)
- assert isinstance(
- milestone_event, gitlab.v4.objects.ProjectIssueResourceMilestoneEvent
- )
-
- milestone_issues = project.issues.list(milestone=milestone.title)
- assert len(milestone_issues) == 1
-
-
-def test_issue_discussions(issue):
- size = len(issue.discussions.list())
-
- discussion = issue.discussions.create({"body": "Discussion body"})
- assert len(issue.discussions.list()) == size + 1
-
- d_note = discussion.notes.create({"body": "first note"})
- d_note_from_get = discussion.notes.get(d_note.id)
- d_note_from_get.body = "updated body"
- d_note_from_get.save()
-
- discussion = issue.discussions.get(discussion.id)
- assert discussion.attributes["notes"][-1]["body"] == "updated body"
-
- d_note_from_get.delete()
- discussion = issue.discussions.get(discussion.id)
- assert len(discussion.attributes["notes"]) == 1
diff --git a/tests/functional/api/test_keys.py b/tests/functional/api/test_keys.py
deleted file mode 100644
index 82a75e5..0000000
--- a/tests/functional/api/test_keys.py
+++ /dev/null
@@ -1,42 +0,0 @@
-"""
-GitLab API:
-https://docs.gitlab.com/ce/api/keys.html
-"""
-import base64
-import hashlib
-
-
-def key_fingerprint(key):
- key_part = key.split()[1]
- decoded = base64.b64decode(key_part.encode("ascii"))
- digest = hashlib.sha256(decoded).digest()
- return "SHA256:" + base64.b64encode(digest).rstrip(b"=").decode("utf-8")
-
-
-def test_keys_ssh(gl, user, SSH_KEY):
- key = user.keys.create({"title": "foo@bar", "key": SSH_KEY})
-
- # Get key by ID (admin only).
- key_by_id = gl.keys.get(key.id)
- assert key_by_id.title == key.title
- assert key_by_id.key == key.key
-
- fingerprint = key_fingerprint(SSH_KEY)
- # Get key by fingerprint (admin only).
- key_by_fingerprint = gl.keys.get(fingerprint=fingerprint)
- assert key_by_fingerprint.title == key.title
- assert key_by_fingerprint.key == key.key
-
- key.delete()
-
-
-def test_keys_deploy(gl, project, DEPLOY_KEY):
- key = project.keys.create({"title": "foo@bar", "key": DEPLOY_KEY})
-
- fingerprint = key_fingerprint(DEPLOY_KEY)
- key_by_fingerprint = gl.keys.get(fingerprint=fingerprint)
- assert key_by_fingerprint.title == key.title
- assert key_by_fingerprint.key == key.key
- assert len(key_by_fingerprint.deploy_keys_projects) == 1
-
- key.delete()
diff --git a/tests/functional/api/test_merge_requests.py b/tests/functional/api/test_merge_requests.py
deleted file mode 100644
index b20b66a..0000000
--- a/tests/functional/api/test_merge_requests.py
+++ /dev/null
@@ -1,205 +0,0 @@
-import time
-
-import pytest
-
-import gitlab
-import gitlab.v4.objects
-
-
-def test_merge_requests(project):
- project.files.create(
- {
- "file_path": "README.rst",
- "branch": "master",
- "content": "Initial content",
- "commit_message": "Initial commit",
- }
- )
-
- source_branch = "branch1"
- project.branches.create({"branch": source_branch, "ref": "master"})
-
- project.files.create(
- {
- "file_path": "README2.rst",
- "branch": source_branch,
- "content": "Initial content",
- "commit_message": "New commit in new branch",
- }
- )
- project.mergerequests.create(
- {"source_branch": "branch1", "target_branch": "master", "title": "MR readme2"}
- )
-
-
-def test_merge_request_discussion(project):
- mr = project.mergerequests.list()[0]
- size = len(mr.discussions.list())
-
- discussion = mr.discussions.create({"body": "Discussion body"})
- assert len(mr.discussions.list()) == size + 1
-
- note = discussion.notes.create({"body": "first note"})
- note_from_get = discussion.notes.get(note.id)
- note_from_get.body = "updated body"
- note_from_get.save()
-
- discussion = mr.discussions.get(discussion.id)
- assert discussion.attributes["notes"][-1]["body"] == "updated body"
-
- note_from_get.delete()
- discussion = mr.discussions.get(discussion.id)
- assert len(discussion.attributes["notes"]) == 1
-
-
-def test_merge_request_labels(project):
- mr = project.mergerequests.list()[0]
- mr.labels = ["label2"]
- mr.save()
-
- events = mr.resourcelabelevents.list()
- assert events
-
- event = mr.resourcelabelevents.get(events[0].id)
- assert event
-
-
-def test_merge_request_milestone_events(project, milestone):
- mr = project.mergerequests.list()[0]
- mr.milestone_id = milestone.id
- mr.save()
-
- milestones = mr.resourcemilestoneevents.list()
- assert milestones
-
- milestone = mr.resourcemilestoneevents.get(milestones[0].id)
- assert milestone
-
-
-def test_merge_request_basic(project):
- mr = project.mergerequests.list()[0]
- # basic testing: only make sure that the methods exist
- mr.commits()
- mr.changes()
- assert mr.participants()
-
-
-def test_merge_request_rebase(project):
- mr = project.mergerequests.list()[0]
- assert mr.rebase()
-
-
-@pytest.mark.skip(reason="flaky test")
-def test_merge_request_merge(project):
- mr = project.mergerequests.list()[0]
- mr.merge()
- project.branches.delete(mr.source_branch)
-
- with pytest.raises(gitlab.GitlabMRClosedError):
- # Two merge attempts should raise GitlabMRClosedError
- mr.merge()
-
-
-def test_merge_request_should_remove_source_branch(
- project, merge_request, wait_for_sidekiq
-) -> None:
- """Test to ensure
- https://github.com/python-gitlab/python-gitlab/issues/1120 is fixed.
- Bug reported that they could not use 'should_remove_source_branch' in
- mr.merge() call"""
-
- source_branch = "remove_source_branch"
- mr = merge_request(source_branch=source_branch)
-
- mr.merge(should_remove_source_branch=True)
-
- result = wait_for_sidekiq(timeout=60)
- assert result is True, "sidekiq process should have terminated but did not"
-
- # Wait until it is merged
- mr_iid = mr.iid
- for _ in range(60):
- mr = project.mergerequests.get(mr_iid)
- if mr.merged_at is not None:
- break
- time.sleep(0.5)
- assert mr.merged_at is not None
- time.sleep(0.5)
- result = wait_for_sidekiq(timeout=60)
- assert result is True, "sidekiq process should have terminated but did not"
-
- # Ensure we can NOT get the MR branch
- with pytest.raises(gitlab.exceptions.GitlabGetError):
- result = project.branches.get(source_branch)
- # Help to debug in case the expected exception doesn't happen.
- import pprint
-
- print("mr:", pprint.pformat(mr))
- print("mr.merged_at:", pprint.pformat(mr.merged_at))
- print("result:", pprint.pformat(result))
-
-
-def test_merge_request_large_commit_message(
- project, merge_request, wait_for_sidekiq
-) -> None:
- """Test to ensure https://github.com/python-gitlab/python-gitlab/issues/1452
- is fixed.
- Bug reported that very long 'merge_commit_message' in mr.merge() would
- cause an error: 414 Request too large
- """
-
- source_branch = "large_commit_message"
- mr = merge_request(source_branch=source_branch)
-
- merge_commit_message = "large_message\r\n" * 1_000
- assert len(merge_commit_message) > 10_000
-
- mr.merge(merge_commit_message=merge_commit_message)
-
- result = wait_for_sidekiq(timeout=60)
- assert result is True, "sidekiq process should have terminated but did not"
-
- # Wait until it is merged
- mr_iid = mr.iid
- for _ in range(60):
- mr = project.mergerequests.get(mr_iid)
- if mr.merged_at is not None:
- break
- time.sleep(0.5)
- assert mr.merged_at is not None
- time.sleep(0.5)
-
- # Ensure we can get the MR branch
- project.branches.get(source_branch)
-
-
-def test_merge_request_merge_ref(merge_request) -> None:
- source_branch = "merge_ref_test"
- mr = merge_request(source_branch=source_branch)
-
- response = mr.merge_ref()
- assert response and "commit_id" in response
-
-
-def test_merge_request_merge_ref_should_fail(
- project, merge_request, wait_for_sidekiq
-) -> None:
- source_branch = "merge_ref_test2"
- mr = merge_request(source_branch=source_branch)
-
- # Create conflict
- project.files.create(
- {
- "file_path": f"README.{source_branch}",
- "branch": project.default_branch,
- "content": "Different initial content",
- "commit_message": "Another commit in main branch",
- }
- )
- result = wait_for_sidekiq(timeout=60)
- assert result is True, "sidekiq process should have terminated but did not"
-
- # Check for non-existing merge_ref for MR with conflicts
- with pytest.raises(gitlab.exceptions.GitlabGetError):
- response = mr.merge_ref()
- assert "commit_id" not in response
diff --git a/tests/functional/api/test_packages.py b/tests/functional/api/test_packages.py
deleted file mode 100644
index 64b57b8..0000000
--- a/tests/functional/api/test_packages.py
+++ /dev/null
@@ -1,62 +0,0 @@
-"""
-GitLab API:
-https://docs.gitlab.com/ce/api/packages.html
-https://docs.gitlab.com/ee/user/packages/generic_packages
-"""
-from gitlab.v4.objects import GenericPackage
-
-package_name = "hello-world"
-package_version = "v1.0.0"
-file_name = "hello.tar.gz"
-file_content = "package content"
-
-
-def test_list_project_packages(project):
- packages = project.packages.list()
- assert isinstance(packages, list)
-
-
-def test_list_group_packages(group):
- packages = group.packages.list()
- assert isinstance(packages, list)
-
-
-def test_upload_generic_package(tmp_path, project):
- path = tmp_path / file_name
- path.write_text(file_content)
- package = project.generic_packages.upload(
- package_name=package_name,
- package_version=package_version,
- file_name=file_name,
- path=path,
- )
-
- assert isinstance(package, GenericPackage)
- assert package.message == "201 Created"
-
-
-def test_download_generic_package(project):
- package = project.generic_packages.download(
- package_name=package_name,
- package_version=package_version,
- file_name=file_name,
- )
-
- assert isinstance(package, bytes)
- assert package.decode("utf-8") == file_content
-
-
-def test_download_generic_package_to_file(tmp_path, project):
- path = tmp_path / file_name
-
- with open(path, "wb") as f:
- project.generic_packages.download(
- package_name=package_name,
- package_version=package_version,
- file_name=file_name,
- streamed=True,
- action=f.write,
- )
-
- with open(path, "r") as f:
- assert f.read() == file_content
diff --git a/tests/functional/api/test_projects.py b/tests/functional/api/test_projects.py
deleted file mode 100644
index 88b274c..0000000
--- a/tests/functional/api/test_projects.py
+++ /dev/null
@@ -1,268 +0,0 @@
-import pytest
-
-import gitlab
-
-
-def test_create_project(gl, user):
- # Moved from group tests chunk in legacy tests, TODO cleanup
- admin_project = gl.projects.create({"name": "admin_project"})
- assert isinstance(admin_project, gitlab.v4.objects.Project)
- assert len(gl.projects.list(search="admin")) == 1
-
- sudo_project = gl.projects.create({"name": "sudo_project"}, sudo=user.id)
-
- created = gl.projects.list()
- created_gen = gl.projects.list(as_list=False)
- owned = gl.projects.list(owned=True)
-
- assert admin_project in created and sudo_project in created
- assert admin_project in owned and sudo_project not in owned
- assert len(created) == len(list(created_gen))
-
- admin_project.delete()
- sudo_project.delete()
-
-
-def test_project_badges(project):
- badge_image = "http://example.com"
- badge_link = "http://example/img.svg"
-
- badge = project.badges.create({"link_url": badge_link, "image_url": badge_image})
- assert len(project.badges.list()) == 1
-
- badge.image_url = "http://another.example.com"
- badge.save()
-
- badge = project.badges.get(badge.id)
- assert badge.image_url == "http://another.example.com"
-
- badge.delete()
- assert len(project.badges.list()) == 0
-
-
-@pytest.mark.skip(reason="Commented out in legacy test")
-def test_project_boards(project):
- boards = project.boards.list()
- assert len(boards)
-
- board = boards[0]
- lists = board.lists.list()
- begin_size = len(lists)
- last_list = lists[-1]
- last_list.position = 0
- last_list.save()
- last_list.delete()
- lists = board.lists.list()
- assert len(lists) == begin_size - 1
-
-
-def test_project_custom_attributes(gl, project):
- attrs = project.customattributes.list()
- assert len(attrs) == 0
-
- attr = project.customattributes.set("key", "value1")
- assert attr.key == "key"
- assert attr.value == "value1"
- assert len(project.customattributes.list()) == 1
- assert len(gl.projects.list(custom_attributes={"key": "value1"})) == 1
-
- attr = project.customattributes.set("key", "value2")
- attr = project.customattributes.get("key")
- assert attr.value == "value2"
- assert len(project.customattributes.list()) == 1
-
- attr.delete()
- assert len(project.customattributes.list()) == 0
-
-
-def test_project_environments(project):
- project.environments.create(
- {"name": "env1", "external_url": "http://fake.env/whatever"}
- )
- environments = project.environments.list()
- assert len(environments) == 1
-
- environment = environments[0]
- environment.external_url = "http://new.env/whatever"
- environment.save()
-
- environment = project.environments.list()[0]
- assert environment.external_url == "http://new.env/whatever"
-
- environment.stop()
- environment.delete()
- assert len(project.environments.list()) == 0
-
-
-def test_project_events(project):
- events = project.events.list()
- assert isinstance(events, list)
-
-
-def test_project_file_uploads(project):
- filename = "test.txt"
- file_contents = "testing contents"
-
- uploaded_file = project.upload(filename, file_contents)
- assert uploaded_file["alt"] == filename
- assert uploaded_file["url"].startswith("/uploads/")
- assert uploaded_file["url"].endswith("/" + filename)
- assert uploaded_file["markdown"] == "[{}]({})".format(
- uploaded_file["alt"], uploaded_file["url"]
- )
-
-
-def test_project_forks(gl, project, user):
- fork = project.forks.create({"namespace": user.username})
- fork_project = gl.projects.get(fork.id)
- assert fork_project.forked_from_project["id"] == project.id
-
- forks = project.forks.list()
- assert fork.id in map(lambda fork_project: fork_project.id, forks)
-
-
-def test_project_hooks(project):
- hook = project.hooks.create({"url": "http://hook.url"})
- assert len(project.hooks.list()) == 1
-
- hook.note_events = True
- hook.save()
-
- hook = project.hooks.get(hook.id)
- assert hook.note_events is True
- hook.delete()
-
-
-def test_project_housekeeping(project):
- project.housekeeping()
-
-
-def test_project_labels(project):
- label = project.labels.create({"name": "label", "color": "#778899"})
- labels = project.labels.list()
- assert len(labels) == 1
-
- label = project.labels.get("label")
- assert label == labels[0]
-
- label.new_name = "labelupdated"
- label.save()
- assert label.name == "labelupdated"
-
- label.subscribe()
- assert label.subscribed is True
-
- label.unsubscribe()
- assert label.subscribed is False
-
- label.delete()
- assert len(project.labels.list()) == 0
-
-
-def test_project_milestones(project):
- milestone = project.milestones.create({"title": "milestone1"})
- assert len(project.milestones.list()) == 1
-
- milestone.due_date = "2020-01-01T00:00:00Z"
- milestone.save()
-
- milestone.state_event = "close"
- milestone.save()
-
- milestone = project.milestones.get(milestone.id)
- assert milestone.state == "closed"
- assert len(milestone.issues()) == 0
- assert len(milestone.merge_requests()) == 0
-
-
-def test_project_pages_domains(gl, project):
- domain = project.pagesdomains.create({"domain": "foo.domain.com"})
- assert len(project.pagesdomains.list()) == 1
- assert len(gl.pagesdomains.list()) == 1
-
- domain = project.pagesdomains.get("foo.domain.com")
- assert domain.domain == "foo.domain.com"
-
- domain.delete()
- assert len(project.pagesdomains.list()) == 0
-
-
-def test_project_protected_branches(project):
- p_b = project.protectedbranches.create({"name": "*-stable"})
- assert p_b.name == "*-stable"
- assert len(project.protectedbranches.list()) == 1
-
- p_b = project.protectedbranches.get("*-stable")
- p_b.delete()
- assert len(project.protectedbranches.list()) == 0
-
-
-def test_project_remote_mirrors(project):
- mirror_url = "http://gitlab.test/root/mirror.git"
-
- mirror = project.remote_mirrors.create({"url": mirror_url})
- assert mirror.url == mirror_url
-
- mirror.enabled = True
- mirror.save()
-
- mirror = project.remote_mirrors.list()[0]
- assert isinstance(mirror, gitlab.v4.objects.ProjectRemoteMirror)
- assert mirror.url == mirror_url
- assert mirror.enabled is True
-
-
-def test_project_services(project):
- # Use 'update' to create a service as we don't have a 'create' method and
- # to add one is somewhat complicated so it hasn't been done yet.
- project.services.update("asana", api_key="foo")
-
- service = project.services.get("asana")
- assert service.active is True
- service.api_key = "whatever"
- service.save()
-
- service = project.services.get("asana")
- assert service.active is True
-
- service.delete()
-
- service = project.services.get("asana")
- assert service.active is False
-
-
-def test_project_stars(project):
- project.star()
- assert project.star_count == 1
-
- project.unstar()
- assert project.star_count == 0
-
-
-def test_project_tags(project, project_file):
- tag = project.tags.create({"tag_name": "v1.0", "ref": "master"})
- assert len(project.tags.list()) == 1
-
- tag.delete()
- assert len(project.tags.list()) == 0
-
-
-def test_project_triggers(project):
- trigger = project.triggers.create({"description": "trigger1"})
- assert len(project.triggers.list()) == 1
- trigger.delete()
-
-
-def test_project_wiki(project):
- content = "Wiki page content"
- wiki = project.wikis.create({"title": "wikipage", "content": content})
- assert len(project.wikis.list()) == 1
-
- wiki = project.wikis.get(wiki.slug)
- assert wiki.content == content
-
- # update and delete seem broken
- wiki.content = "new content"
- wiki.save()
- wiki.delete()
- assert len(project.wikis.list()) == 0
diff --git a/tests/functional/api/test_releases.py b/tests/functional/api/test_releases.py
deleted file mode 100644
index f409c23..0000000
--- a/tests/functional/api/test_releases.py
+++ /dev/null
@@ -1,63 +0,0 @@
-release_name = "Demo Release"
-release_tag_name = "v1.2.3"
-release_description = "release notes go here"
-
-link_data = {"url": "https://example.com", "name": "link_name"}
-
-
-def test_create_project_release(project, project_file):
- project.refresh() # Gets us the current default branch
- release = project.releases.create(
- {
- "name": release_name,
- "tag_name": release_tag_name,
- "description": release_description,
- "ref": project.default_branch,
- }
- )
-
- assert len(project.releases.list()) == 1
- assert project.releases.get(release_tag_name)
- assert release.name == release_name
- assert release.tag_name == release_tag_name
- assert release.description == release_description
-
-
-def test_create_project_release_no_name(project, project_file):
- unnamed_release_tag_name = "v2.3.4"
-
- project.refresh() # Gets us the current default branch
- release = project.releases.create(
- {
- "tag_name": unnamed_release_tag_name,
- "description": release_description,
- "ref": project.default_branch,
- }
- )
-
- assert len(project.releases.list()) >= 1
- assert project.releases.get(unnamed_release_tag_name)
- assert release.tag_name == unnamed_release_tag_name
- assert release.description == release_description
-
-
-def test_update_save_project_release(project, release):
- updated_description = f"{release.description} updated"
- release.description = updated_description
- release.save()
-
- release = project.releases.get(release.tag_name)
- assert release.description == updated_description
-
-
-def test_delete_project_release(project, release):
- project.releases.delete(release.tag_name)
- assert release not in project.releases.list()
-
-
-def test_create_project_release_links(project, release):
- release.links.create(link_data)
-
- release = project.releases.get(release.tag_name)
- assert release.assets["links"][0]["url"] == link_data["url"]
- assert release.assets["links"][0]["name"] == link_data["name"]
diff --git a/tests/functional/api/test_repository.py b/tests/functional/api/test_repository.py
deleted file mode 100644
index 7ba84ea..0000000
--- a/tests/functional/api/test_repository.py
+++ /dev/null
@@ -1,126 +0,0 @@
-import base64
-import time
-
-import pytest
-
-import gitlab
-
-
-def test_repository_files(project):
- project.files.create(
- {
- "file_path": "README",
- "branch": "master",
- "content": "Initial content",
- "commit_message": "Initial commit",
- }
- )
- readme = project.files.get(file_path="README", ref="master")
- readme.content = base64.b64encode(b"Improved README").decode()
-
- time.sleep(2)
- readme.save(branch="master", commit_message="new commit")
- readme.delete(commit_message="Removing README", branch="master")
-
- project.files.create(
- {
- "file_path": "README.rst",
- "branch": "master",
- "content": "Initial content",
- "commit_message": "New commit",
- }
- )
- readme = project.files.get(file_path="README.rst", ref="master")
- # The first decode() is the ProjectFile method, the second one is the bytes
- # object method
- assert readme.decode().decode() == "Initial content"
-
- blame = project.files.blame(file_path="README.rst", ref="master")
- assert blame
-
-
-def test_repository_tree(project):
- tree = project.repository_tree()
- assert tree
- assert tree[0]["name"] == "README.rst"
-
- blob_id = tree[0]["id"]
- blob = project.repository_raw_blob(blob_id)
- assert blob.decode() == "Initial content"
-
- archive = project.repository_archive()
- assert isinstance(archive, bytes)
-
- archive2 = project.repository_archive("master")
- assert archive == archive2
-
- snapshot = project.snapshot()
- assert isinstance(snapshot, bytes)
-
-
-def test_create_commit(project):
- data = {
- "branch": "master",
- "commit_message": "blah blah blah",
- "actions": [{"action": "create", "file_path": "blah", "content": "blah"}],
- }
- commit = project.commits.create(data)
-
- assert "@@" in project.commits.list()[0].diff()[0]["diff"]
- assert isinstance(commit.refs(), list)
- assert isinstance(commit.merge_requests(), list)
-
-
-def test_create_commit_status(project):
- commit = project.commits.list()[0]
- size = len(commit.statuses.list())
- commit.statuses.create({"state": "success", "sha": commit.id})
- assert len(commit.statuses.list()) == size + 1
-
-
-def test_commit_signature(project):
- commit = project.commits.list()[0]
-
- with pytest.raises(gitlab.GitlabGetError) as e:
- commit.signature()
-
- assert "404 Signature Not Found" in str(e.value)
-
-
-def test_commit_comment(project):
- commit = project.commits.list()[0]
-
- commit.comments.create({"note": "This is a commit comment"})
- assert len(commit.comments.list()) == 1
-
-
-def test_commit_discussion(project):
- commit = project.commits.list()[0]
- count = len(commit.discussions.list())
-
- discussion = commit.discussions.create({"body": "Discussion body"})
- assert len(commit.discussions.list()) == (count + 1)
-
- note = discussion.notes.create({"body": "first note"})
- note_from_get = discussion.notes.get(note.id)
- note_from_get.body = "updated body"
- note_from_get.save()
- discussion = commit.discussions.get(discussion.id)
- # assert discussion.attributes["notes"][-1]["body"] == "updated body"
- note_from_get.delete()
- discussion = commit.discussions.get(discussion.id)
- # assert len(discussion.attributes["notes"]) == 1
-
-
-def test_revert_commit(project):
- commit = project.commits.list()[0]
- revert_commit = commit.revert(branch="master")
-
- expected_message = 'Revert "{}"\n\nThis reverts commit {}'.format(
- commit.message, commit.id
- )
- assert revert_commit["message"] == expected_message
-
- with pytest.raises(gitlab.GitlabRevertError):
- # Two revert attempts should raise GitlabRevertError
- commit.revert(branch="master")
diff --git a/tests/functional/api/test_snippets.py b/tests/functional/api/test_snippets.py
deleted file mode 100644
index 9e0f833..0000000
--- a/tests/functional/api/test_snippets.py
+++ /dev/null
@@ -1,74 +0,0 @@
-import gitlab
-
-
-def test_snippets(gl):
- snippets = gl.snippets.list(all=True)
- assert len(snippets) == 0
-
- snippet = gl.snippets.create(
- {"title": "snippet1", "file_name": "snippet1.py", "content": "import gitlab"}
- )
- snippet = gl.snippets.get(snippet.id)
- snippet.title = "updated_title"
- snippet.save()
-
- snippet = gl.snippets.get(snippet.id)
- assert snippet.title == "updated_title"
-
- content = snippet.content()
- assert content.decode() == "import gitlab"
- assert snippet.user_agent_detail()["user_agent"]
-
- snippet.delete()
- snippets = gl.snippets.list(all=True)
- assert len(snippets) == 0
-
-
-def test_project_snippets(project):
- project.snippets_enabled = True
- project.save()
-
- snippet = project.snippets.create(
- {
- "title": "snip1",
- "file_name": "foo.py",
- "content": "initial content",
- "visibility": gitlab.VISIBILITY_PRIVATE,
- }
- )
-
- assert snippet.user_agent_detail()["user_agent"]
-
-
-def test_project_snippet_discussion(project):
- snippet = project.snippets.list()[0]
- size = len(snippet.discussions.list())
-
- discussion = snippet.discussions.create({"body": "Discussion body"})
- assert len(snippet.discussions.list()) == size + 1
-
- note = discussion.notes.create({"body": "first note"})
- note_from_get = discussion.notes.get(note.id)
- note_from_get.body = "updated body"
- note_from_get.save()
-
- discussion = snippet.discussions.get(discussion.id)
- assert discussion.attributes["notes"][-1]["body"] == "updated body"
-
- note_from_get.delete()
- discussion = snippet.discussions.get(discussion.id)
- assert len(discussion.attributes["notes"]) == 1
-
-
-def test_project_snippet_file(project):
- snippet = project.snippets.list()[0]
- snippet.file_name = "bar.py"
- snippet.save()
-
- snippet = project.snippets.get(snippet.id)
- assert snippet.content().decode() == "initial content"
- assert snippet.file_name == "bar.py"
-
- size = len(project.snippets.list())
- snippet.delete()
- assert len(project.snippets.list()) == (size - 1)
diff --git a/tests/functional/api/test_users.py b/tests/functional/api/test_users.py
deleted file mode 100644
index 1ef237c..0000000
--- a/tests/functional/api/test_users.py
+++ /dev/null
@@ -1,170 +0,0 @@
-"""
-GitLab API:
-https://docs.gitlab.com/ee/api/users.html
-https://docs.gitlab.com/ee/api/users.html#delete-authentication-identity-from-user
-"""
-import pytest
-import requests
-
-
-@pytest.fixture(scope="session")
-def avatar_path(test_dir):
- return test_dir / "fixtures" / "avatar.png"
-
-
-def test_create_user(gl, avatar_path):
- user = gl.users.create(
- {
- "email": "foo@bar.com",
- "username": "foo",
- "name": "foo",
- "password": "foo_password",
- "avatar": open(avatar_path, "rb"),
- }
- )
-
- created_user = gl.users.list(username="foo")[0]
- assert created_user.username == user.username
- assert created_user.email == user.email
-
- avatar_url = user.avatar_url.replace("gitlab.test", "localhost:8080")
- uploaded_avatar = requests.get(avatar_url).content
- assert uploaded_avatar == open(avatar_path, "rb").read()
-
-
-def test_block_user(gl, user):
- user.block()
- users = gl.users.list(blocked=True)
- assert user in users
-
- user.unblock()
- users = gl.users.list(blocked=False)
- assert user in users
-
-
-def test_delete_user(gl, wait_for_sidekiq):
- new_user = gl.users.create(
- {
- "email": "delete-user@test.com",
- "username": "delete-user",
- "name": "delete-user",
- "password": "delete-user-pass",
- }
- )
-
- new_user.delete()
- result = wait_for_sidekiq(timeout=60)
- assert result is True, "sidekiq process should have terminated but did not"
-
- assert new_user.id not in [user.id for user in gl.users.list()]
-
-
-def test_user_projects_list(gl, user):
- projects = user.projects.list()
- assert isinstance(projects, list)
- assert not projects
-
-
-def test_user_events_list(gl, user):
- events = user.events.list()
- assert isinstance(events, list)
- assert not events
-
-
-def test_user_bio(gl, user):
- user.bio = "This is the user bio"
- user.save()
-
-
-def test_list_multiple_users(gl, user):
- second_email = f"{user.email}.2"
- second_username = f"{user.username}_2"
- second_user = gl.users.create(
- {
- "email": second_email,
- "username": second_username,
- "name": "Foo Bar",
- "password": "foobar_password",
- }
- )
- assert gl.users.list(search=second_user.username)[0].id == second_user.id
-
- expected = [user, second_user]
- actual = list(gl.users.list(search=user.username))
-
- assert len(expected) == len(actual)
- assert len(gl.users.list(search="asdf")) == 0
-
-
-def test_user_gpg_keys(gl, user, GPG_KEY):
- gkey = user.gpgkeys.create({"key": GPG_KEY})
- assert len(user.gpgkeys.list()) == 1
-
- # Seems broken on the gitlab side
- # gkey = user.gpgkeys.get(gkey.id)
-
- gkey.delete()
- assert len(user.gpgkeys.list()) == 0
-
-
-def test_user_ssh_keys(gl, user, SSH_KEY):
- key = user.keys.create({"title": "testkey", "key": SSH_KEY})
- assert len(user.keys.list()) == 1
-
- key.delete()
- assert len(user.keys.list()) == 0
-
-
-def test_user_email(gl, user):
- email = user.emails.create({"email": "foo2@bar.com"})
- assert len(user.emails.list()) == 1
-
- email.delete()
- assert len(user.emails.list()) == 0
-
-
-def test_user_custom_attributes(gl, user):
- attrs = user.customattributes.list()
- assert len(attrs) == 0
-
- attr = user.customattributes.set("key", "value1")
- assert len(gl.users.list(custom_attributes={"key": "value1"})) == 1
- assert attr.key == "key"
- assert attr.value == "value1"
- assert len(user.customattributes.list()) == 1
-
- attr = user.customattributes.set("key", "value2")
- attr = user.customattributes.get("key")
- assert attr.value == "value2"
- assert len(user.customattributes.list()) == 1
-
- attr.delete()
- assert len(user.customattributes.list()) == 0
-
-
-def test_user_impersonation_tokens(gl, user):
- token = user.impersonationtokens.create(
- {"name": "token1", "scopes": ["api", "read_user"]}
- )
-
- tokens = user.impersonationtokens.list(state="active")
- assert len(tokens) == 1
-
- token.delete()
- tokens = user.impersonationtokens.list(state="active")
- assert len(tokens) == 0
- tokens = user.impersonationtokens.list(state="inactive")
- assert len(tokens) == 1
-
-
-def test_user_identities(gl, user):
- provider = "test_provider"
-
- user.provider = provider
- user.extern_uid = "1"
- user.save()
- assert provider in [item["provider"] for item in user.identities]
-
- user.identityproviders.delete(provider)
- user = gl.users.get(user.id)
- assert provider not in [item["provider"] for item in user.identities]
diff --git a/tests/functional/api/test_variables.py b/tests/functional/api/test_variables.py
deleted file mode 100644
index d20ebba..0000000
--- a/tests/functional/api/test_variables.py
+++ /dev/null
@@ -1,48 +0,0 @@
-"""
-GitLab API:
-https://docs.gitlab.com/ee/api/instance_level_ci_variables.html
-https://docs.gitlab.com/ee/api/project_level_variables.html
-https://docs.gitlab.com/ee/api/group_level_variables.html
-"""
-
-
-def test_instance_variables(gl):
- variable = gl.variables.create({"key": "key1", "value": "value1"})
- assert variable.value == "value1"
- assert len(gl.variables.list()) == 1
-
- variable.value = "new_value1"
- variable.save()
- variable = gl.variables.get(variable.key)
- assert variable.value == "new_value1"
-
- variable.delete()
- assert len(gl.variables.list()) == 0
-
-
-def test_group_variables(group):
- variable = group.variables.create({"key": "key1", "value": "value1"})
- assert variable.value == "value1"
- assert len(group.variables.list()) == 1
-
- variable.value = "new_value1"
- variable.save()
- variable = group.variables.get(variable.key)
- assert variable.value == "new_value1"
-
- variable.delete()
- assert len(group.variables.list()) == 0
-
-
-def test_project_variables(project):
- variable = project.variables.create({"key": "key1", "value": "value1"})
- assert variable.value == "value1"
- assert len(project.variables.list()) == 1
-
- variable.value = "new_value1"
- variable.save()
- variable = project.variables.get(variable.key)
- assert variable.value == "new_value1"
-
- variable.delete()
- assert len(project.variables.list()) == 0
diff --git a/tests/functional/cli/__init__.py b/tests/functional/cli/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tests/functional/cli/__init__.py
+++ /dev/null
diff --git a/tests/functional/cli/conftest.py b/tests/functional/cli/conftest.py
deleted file mode 100644
index ba94dcb..0000000
--- a/tests/functional/cli/conftest.py
+++ /dev/null
@@ -1,21 +0,0 @@
-import pytest
-
-
-@pytest.fixture
-def gitlab_cli(script_runner, gitlab_config):
- """Wrapper fixture to help make test cases less verbose."""
-
- def _gitlab_cli(subcommands):
- """
- Return a script_runner.run method that takes a default gitlab
- command, and subcommands passed as arguments inside test cases.
- """
- command = ["gitlab", "--config-file", gitlab_config]
-
- for subcommand in subcommands:
- # ensure we get strings (e.g from IDs)
- command.append(str(subcommand))
-
- return script_runner.run(*command)
-
- return _gitlab_cli
diff --git a/tests/functional/cli/test_cli_artifacts.py b/tests/functional/cli/test_cli_artifacts.py
deleted file mode 100644
index aab0546..0000000
--- a/tests/functional/cli/test_cli_artifacts.py
+++ /dev/null
@@ -1,49 +0,0 @@
-import subprocess
-import textwrap
-import time
-from io import BytesIO
-from zipfile import is_zipfile
-
-content = textwrap.dedent(
- """\
- test-artifact:
- script: echo "test" > artifact.txt
- artifacts:
- untracked: true
- """
-)
-data = {
- "file_path": ".gitlab-ci.yml",
- "branch": "master",
- "content": content,
- "commit_message": "Initial commit",
-}
-
-
-def test_cli_artifacts(capsysbinary, gitlab_config, gitlab_runner, project):
- project.files.create(data)
-
- jobs = None
- while not jobs:
- jobs = project.jobs.list(scope="success")
- time.sleep(0.5)
-
- job = project.jobs.get(jobs[0].id)
- cmd = [
- "gitlab",
- "--config-file",
- gitlab_config,
- "project-job",
- "artifacts",
- "--id",
- str(job.id),
- "--project-id",
- str(project.id),
- ]
-
- with capsysbinary.disabled():
- artifacts = subprocess.check_output(cmd)
- assert isinstance(artifacts, bytes)
-
- artifacts_zip = BytesIO(artifacts)
- assert is_zipfile(artifacts_zip)
diff --git a/tests/functional/cli/test_cli_packages.py b/tests/functional/cli/test_cli_packages.py
deleted file mode 100644
index d7cdd18..0000000
--- a/tests/functional/cli/test_cli_packages.py
+++ /dev/null
@@ -1,60 +0,0 @@
-package_name = "hello-world"
-package_version = "v1.0.0"
-file_name = "hello.tar.gz"
-file_content = "package content"
-
-
-def test_list_project_packages(gitlab_cli, project):
- cmd = ["project-package", "list", "--project-id", project.id]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_list_group_packages(gitlab_cli, group):
- cmd = ["group-package", "list", "--group-id", group.id]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_upload_generic_package(tmp_path, gitlab_cli, project):
- path = tmp_path / file_name
- path.write_text(file_content)
-
- cmd = [
- "-v",
- "generic-package",
- "upload",
- "--project-id",
- project.id,
- "--package-name",
- package_name,
- "--path",
- path,
- "--package-version",
- package_version,
- "--file-name",
- file_name,
- ]
- ret = gitlab_cli(cmd)
-
- assert "201 Created" in ret.stdout
-
-
-def test_download_generic_package(gitlab_cli, project):
- cmd = [
- "generic-package",
- "download",
- "--project-id",
- project.id,
- "--package-name",
- package_name,
- "--package-version",
- package_version,
- "--file-name",
- file_name,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.stdout == file_content
diff --git a/tests/functional/cli/test_cli_v4.py b/tests/functional/cli/test_cli_v4.py
deleted file mode 100644
index a63c1b1..0000000
--- a/tests/functional/cli/test_cli_v4.py
+++ /dev/null
@@ -1,715 +0,0 @@
-import os
-import time
-
-
-def test_create_project(gitlab_cli):
- name = "test-project1"
-
- cmd = ["project", "create", "--name", name]
- ret = gitlab_cli(cmd)
-
- assert ret.success
- assert name in ret.stdout
-
-
-def test_update_project(gitlab_cli, project):
- description = "My New Description"
-
- cmd = ["project", "update", "--id", project.id, "--description", description]
- ret = gitlab_cli(cmd)
-
- assert ret.success
- assert description in ret.stdout
-
-
-def test_create_group(gitlab_cli):
- name = "test-group1"
- path = "group1"
-
- cmd = ["group", "create", "--name", name, "--path", path]
- ret = gitlab_cli(cmd)
-
- assert ret.success
- assert name in ret.stdout
- assert path in ret.stdout
-
-
-def test_update_group(gitlab_cli, gl, group):
- description = "My New Description"
-
- cmd = ["group", "update", "--id", group.id, "--description", description]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
- group = gl.groups.get(group.id)
- assert group.description == description
-
-
-def test_create_user(gitlab_cli, gl):
- email = "fake@email.com"
- username = "user1"
- name = "User One"
- password = "fakepassword"
-
- cmd = [
- "user",
- "create",
- "--email",
- email,
- "--username",
- username,
- "--name",
- name,
- "--password",
- password,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
- user = gl.users.list(username=username)[0]
-
- assert user.email == email
- assert user.username == username
- assert user.name == name
-
-
-def test_get_user_by_id(gitlab_cli, user):
- cmd = ["user", "get", "--id", user.id]
- ret = gitlab_cli(cmd)
-
- assert ret.success
- assert str(user.id) in ret.stdout
-
-
-def test_list_users_verbose_output(gitlab_cli):
- cmd = ["-v", "user", "list"]
- ret = gitlab_cli(cmd)
-
- assert ret.success
- assert "avatar-url" in ret.stdout
-
-
-def test_cli_args_not_in_output(gitlab_cli):
- cmd = ["-v", "user", "list"]
- ret = gitlab_cli(cmd)
-
- assert "config-file" not in ret.stdout
-
-
-def test_add_member_to_project(gitlab_cli, project, user):
- access_level = "40"
-
- cmd = [
- "project-member",
- "create",
- "--project-id",
- project.id,
- "--user-id",
- user.id,
- "--access-level",
- access_level,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_list_user_memberships(gitlab_cli, user):
- cmd = ["user-membership", "list", "--user-id", user.id]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_project_create_file(gitlab_cli, project):
- file_path = "README"
- branch = "master"
- content = "CONTENT"
- commit_message = "Initial commit"
-
- cmd = [
- "project-file",
- "create",
- "--project-id",
- project.id,
- "--file-path",
- file_path,
- "--branch",
- branch,
- "--content",
- content,
- "--commit-message",
- commit_message,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_create_project_issue(gitlab_cli, project):
- title = "my issue"
- description = "my issue description"
-
- cmd = [
- "project-issue",
- "create",
- "--project-id",
- project.id,
- "--title",
- title,
- "--description",
- description,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
- assert title in ret.stdout
-
-
-def test_create_issue_note(gitlab_cli, issue):
- body = "body"
-
- cmd = [
- "project-issue-note",
- "create",
- "--project-id",
- issue.project_id,
- "--issue-iid",
- issue.iid,
- "--body",
- body,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_create_branch(gitlab_cli, project):
- branch = "branch1"
-
- cmd = [
- "project-branch",
- "create",
- "--project-id",
- project.id,
- "--branch",
- branch,
- "--ref",
- "master",
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_create_merge_request(gitlab_cli, project):
- branch = "branch1"
-
- cmd = [
- "project-merge-request",
- "create",
- "--project-id",
- project.id,
- "--source-branch",
- branch,
- "--target-branch",
- "master",
- "--title",
- "Update README",
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_accept_request_merge(gitlab_cli, project):
- # MR needs at least 1 commit before we can merge
- mr = project.mergerequests.list()[0]
- file_data = {
- "branch": mr.source_branch,
- "file_path": "README2",
- "content": "Content",
- "commit_message": "Pre-merge commit",
- }
- project.files.create(file_data)
- time.sleep(2)
-
- cmd = [
- "project-merge-request",
- "merge",
- "--project-id",
- project.id,
- "--iid",
- mr.iid,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_revert_commit(gitlab_cli, project):
- commit = project.commits.list()[0]
-
- cmd = [
- "project-commit",
- "revert",
- "--project-id",
- project.id,
- "--id",
- commit.id,
- "--branch",
- "master",
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_get_commit_signature_not_found(gitlab_cli, project):
- commit = project.commits.list()[0]
-
- cmd = ["project-commit", "signature", "--project-id", project.id, "--id", commit.id]
- ret = gitlab_cli(cmd)
-
- assert not ret.success
- assert "404 Signature Not Found" in ret.stderr
-
-
-def test_create_project_label(gitlab_cli, project):
- name = "prjlabel1"
- description = "prjlabel1 description"
- color = "#112233"
-
- cmd = [
- "-v",
- "project-label",
- "create",
- "--project-id",
- project.id,
- "--name",
- name,
- "--description",
- description,
- "--color",
- color,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_list_project_labels(gitlab_cli, project):
- cmd = ["-v", "project-label", "list", "--project-id", project.id]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_update_project_label(gitlab_cli, label):
- new_label = "prjlabel2"
- new_description = "prjlabel2 description"
- new_color = "#332211"
-
- cmd = [
- "-v",
- "project-label",
- "update",
- "--project-id",
- label.project_id,
- "--name",
- label.name,
- "--new-name",
- new_label,
- "--description",
- new_description,
- "--color",
- new_color,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_delete_project_label(gitlab_cli, label):
- # TODO: due to update above, we'd need a function-scope label fixture
- label_name = "prjlabel2"
-
- cmd = [
- "-v",
- "project-label",
- "delete",
- "--project-id",
- label.project_id,
- "--name",
- label_name,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_create_group_label(gitlab_cli, group):
- name = "grouplabel1"
- description = "grouplabel1 description"
- color = "#112233"
-
- cmd = [
- "-v",
- "group-label",
- "create",
- "--group-id",
- group.id,
- "--name",
- name,
- "--description",
- description,
- "--color",
- color,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_list_group_labels(gitlab_cli, group):
- cmd = ["-v", "group-label", "list", "--group-id", group.id]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_update_group_label(gitlab_cli, group_label):
- new_label = "grouplabel2"
- new_description = "grouplabel2 description"
- new_color = "#332211"
-
- cmd = [
- "-v",
- "group-label",
- "update",
- "--group-id",
- group_label.group_id,
- "--name",
- group_label.name,
- "--new-name",
- new_label,
- "--description",
- new_description,
- "--color",
- new_color,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_delete_group_label(gitlab_cli, group_label):
- # TODO: due to update above, we'd need a function-scope label fixture
- new_label = "grouplabel2"
-
- cmd = [
- "-v",
- "group-label",
- "delete",
- "--group-id",
- group_label.group_id,
- "--name",
- new_label,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_create_project_variable(gitlab_cli, project):
- key = "junk"
- value = "car"
-
- cmd = [
- "-v",
- "project-variable",
- "create",
- "--project-id",
- project.id,
- "--key",
- key,
- "--value",
- value,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_get_project_variable(gitlab_cli, variable):
- cmd = [
- "-v",
- "project-variable",
- "get",
- "--project-id",
- variable.project_id,
- "--key",
- variable.key,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_update_project_variable(gitlab_cli, variable):
- new_value = "bus"
-
- cmd = [
- "-v",
- "project-variable",
- "update",
- "--project-id",
- variable.project_id,
- "--key",
- variable.key,
- "--value",
- new_value,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_list_project_variables(gitlab_cli, project):
- cmd = ["-v", "project-variable", "list", "--project-id", project.id]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_delete_project_variable(gitlab_cli, variable):
- cmd = [
- "-v",
- "project-variable",
- "delete",
- "--project-id",
- variable.project_id,
- "--key",
- variable.key,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_delete_branch(gitlab_cli, project):
- # TODO: branch fixture
- branch = "branch1"
-
- cmd = ["project-branch", "delete", "--project-id", project.id, "--name", branch]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_project_upload_file(gitlab_cli, project):
- cmd = [
- "project",
- "upload",
- "--id",
- project.id,
- "--filename",
- __file__,
- "--filepath",
- os.path.realpath(__file__),
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_get_application_settings(gitlab_cli):
- cmd = ["application-settings", "get"]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_update_application_settings(gitlab_cli):
- cmd = ["application-settings", "update", "--signup-enabled", "false"]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_create_project_with_values_from_file(gitlab_cli, tmpdir):
- name = "gitlab-project-from-file"
- description = "Multiline\n\nData\n"
- from_file = tmpdir.join(name)
- from_file.write(description)
- from_file_path = f"@{str(from_file)}"
-
- cmd = [
- "-v",
- "project",
- "create",
- "--name",
- name,
- "--description",
- from_file_path,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
- assert description in ret.stdout
-
-
-def test_create_project_deploy_token(gitlab_cli, project):
- name = "project-token"
- username = "root"
- expires_at = "2021-09-09"
- scopes = "read_registry"
-
- cmd = [
- "-v",
- "project-deploy-token",
- "create",
- "--project-id",
- project.id,
- "--name",
- name,
- "--username",
- username,
- "--expires-at",
- expires_at,
- "--scopes",
- scopes,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
- assert name in ret.stdout
- assert username in ret.stdout
- assert expires_at in ret.stdout
- assert scopes in ret.stdout
-
-
-def test_list_all_deploy_tokens(gitlab_cli, deploy_token):
- cmd = ["-v", "deploy-token", "list"]
- ret = gitlab_cli(cmd)
-
- assert ret.success
- assert deploy_token.name in ret.stdout
- assert str(deploy_token.id) in ret.stdout
- assert deploy_token.username in ret.stdout
- assert deploy_token.expires_at in ret.stdout
- assert deploy_token.scopes[0] in ret.stdout
-
-
-def test_list_project_deploy_tokens(gitlab_cli, deploy_token):
- cmd = [
- "-v",
- "project-deploy-token",
- "list",
- "--project-id",
- deploy_token.project_id,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
- assert deploy_token.name in ret.stdout
- assert str(deploy_token.id) in ret.stdout
- assert deploy_token.username in ret.stdout
- assert deploy_token.expires_at in ret.stdout
- assert deploy_token.scopes[0] in ret.stdout
-
-
-def test_delete_project_deploy_token(gitlab_cli, deploy_token):
- cmd = [
- "-v",
- "project-deploy-token",
- "delete",
- "--project-id",
- deploy_token.project_id,
- "--id",
- deploy_token.id,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
- # TODO assert not in list
-
-
-def test_create_group_deploy_token(gitlab_cli, group):
- name = "group-token"
- username = "root"
- expires_at = "2021-09-09"
- scopes = "read_registry"
-
- cmd = [
- "-v",
- "group-deploy-token",
- "create",
- "--group-id",
- group.id,
- "--name",
- name,
- "--username",
- username,
- "--expires-at",
- expires_at,
- "--scopes",
- scopes,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
- assert name in ret.stdout
- assert username in ret.stdout
- assert expires_at in ret.stdout
- assert scopes in ret.stdout
-
-
-def test_list_group_deploy_tokens(gitlab_cli, group_deploy_token):
- cmd = [
- "-v",
- "group-deploy-token",
- "list",
- "--group-id",
- group_deploy_token.group_id,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
- assert group_deploy_token.name in ret.stdout
- assert str(group_deploy_token.id) in ret.stdout
- assert group_deploy_token.username in ret.stdout
- assert group_deploy_token.expires_at in ret.stdout
- assert group_deploy_token.scopes[0] in ret.stdout
-
-
-def test_delete_group_deploy_token(gitlab_cli, group_deploy_token):
- cmd = [
- "-v",
- "group-deploy-token",
- "delete",
- "--group-id",
- group_deploy_token.group_id,
- "--id",
- group_deploy_token.id,
- ]
- ret = gitlab_cli(cmd)
-
- assert ret.success
- # TODO assert not in list
-
-
-def test_delete_project(gitlab_cli, project):
- cmd = ["project", "delete", "--id", project.id]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_delete_group(gitlab_cli, group):
- cmd = ["group", "delete", "--id", group.id]
- ret = gitlab_cli(cmd)
-
- assert ret.success
diff --git a/tests/functional/cli/test_cli_variables.py b/tests/functional/cli/test_cli_variables.py
deleted file mode 100644
index 9b1b16d..0000000
--- a/tests/functional/cli/test_cli_variables.py
+++ /dev/null
@@ -1,19 +0,0 @@
-def test_list_instance_variables(gitlab_cli, gl):
- cmd = ["variable", "list"]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_list_group_variables(gitlab_cli, group):
- cmd = ["group-variable", "list", "--group-id", group.id]
- ret = gitlab_cli(cmd)
-
- assert ret.success
-
-
-def test_list_project_variables(gitlab_cli, project):
- cmd = ["project-variable", "list", "--project-id", project.id]
- ret = gitlab_cli(cmd)
-
- assert ret.success
diff --git a/tests/functional/conftest.py b/tests/functional/conftest.py
deleted file mode 100644
index 23aa583..0000000
--- a/tests/functional/conftest.py
+++ /dev/null
@@ -1,489 +0,0 @@
-import tempfile
-import time
-import uuid
-from pathlib import Path
-from subprocess import check_output
-
-import pytest
-
-import gitlab
-
-
-def reset_gitlab(gl):
- # previously tools/reset_gitlab.py
- for project in gl.projects.list():
- for deploy_token in project.deploytokens.list():
- deploy_token.delete()
- project.delete()
- for group in gl.groups.list():
- for deploy_token in group.deploytokens.list():
- deploy_token.delete()
- group.delete()
- for variable in gl.variables.list():
- variable.delete()
- for user in gl.users.list():
- if user.username != "root":
- user.delete(hard_delete=True)
-
-
-def set_token(container, rootdir):
- set_token_rb = rootdir / "fixtures" / "set_token.rb"
-
- with open(set_token_rb, "r") as f:
- set_token_command = f.read().strip()
-
- rails_command = [
- "docker",
- "exec",
- container,
- "gitlab-rails",
- "runner",
- set_token_command,
- ]
- output = check_output(rails_command).decode().strip()
-
- return output
-
-
-def pytest_report_collectionfinish(config, startdir, items):
- return [
- "",
- "Starting GitLab container.",
- "Waiting for GitLab to reconfigure.",
- "This may take a few minutes.",
- ]
-
-
-def pytest_addoption(parser):
- parser.addoption(
- "--keep-containers",
- action="store_true",
- help="Keep containers running after testing",
- )
-
-
-@pytest.fixture(scope="session")
-def temp_dir():
- return Path(tempfile.gettempdir())
-
-
-@pytest.fixture(scope="session")
-def test_dir(pytestconfig):
- return pytestconfig.rootdir / "tests" / "functional"
-
-
-@pytest.fixture(scope="session")
-def docker_compose_file(test_dir):
- return test_dir / "fixtures" / "docker-compose.yml"
-
-
-@pytest.fixture(scope="session")
-def docker_compose_project_name():
- """Set a consistent project name to enable optional reuse of containers."""
- return "pytest-python-gitlab"
-
-
-@pytest.fixture(scope="session")
-def docker_cleanup(request):
- """Conditionally keep containers around by overriding the cleanup command."""
- if request.config.getoption("--keep-containers"):
- # Print version and exit.
- return "-v"
- return "down -v"
-
-
-@pytest.fixture(scope="session")
-def check_is_alive():
- """
- Return a healthcheck function fixture for the GitLab container spinup.
- """
-
- def _check(container):
- logs = ["docker", "logs", container]
- return "gitlab Reconfigured!" in check_output(logs).decode()
-
- return _check
-
-
-@pytest.fixture
-def wait_for_sidekiq(gl):
- """
- Return a helper function to wait until there are no busy sidekiq processes.
-
- Use this with asserts for slow tasks (group/project/user creation/deletion).
- """
-
- def _wait(timeout=30, step=0.5):
- for _ in range(timeout):
- time.sleep(step)
- busy = False
- processes = gl.sidekiq.process_metrics()["processes"]
- for process in processes:
- if process["busy"]:
- busy = True
- if not busy:
- return True
- return False
-
- return _wait
-
-
-@pytest.fixture(scope="session")
-def gitlab_config(check_is_alive, docker_ip, docker_services, temp_dir, test_dir):
- config_file = temp_dir / "python-gitlab.cfg"
- port = docker_services.port_for("gitlab", 80)
-
- docker_services.wait_until_responsive(
- timeout=200, pause=5, check=lambda: check_is_alive("gitlab-test")
- )
-
- token = set_token("gitlab-test", rootdir=test_dir)
-
- config = f"""[global]
-default = local
-timeout = 60
-
-[local]
-url = http://{docker_ip}:{port}
-private_token = {token}
-api_version = 4"""
-
- with open(config_file, "w") as f:
- f.write(config)
-
- return config_file
-
-
-@pytest.fixture(scope="session")
-def gl(gitlab_config):
- """Helper instance to make fixtures and asserts directly via the API."""
-
- instance = gitlab.Gitlab.from_config("local", [gitlab_config])
- reset_gitlab(instance)
-
- return instance
-
-
-@pytest.fixture(scope="session")
-def gitlab_runner(gl):
- container = "gitlab-runner-test"
- runner_name = "python-gitlab-runner"
- token = "registration-token"
- url = "http://gitlab"
-
- docker_exec = ["docker", "exec", container, "gitlab-runner"]
- register = [
- "register",
- "--run-untagged",
- "--non-interactive",
- "--registration-token",
- token,
- "--name",
- runner_name,
- "--url",
- url,
- "--clone-url",
- url,
- "--executor",
- "shell",
- ]
- unregister = ["unregister", "--name", runner_name]
-
- yield check_output(docker_exec + register).decode()
-
- check_output(docker_exec + unregister).decode()
-
-
-@pytest.fixture(scope="module")
-def group(gl):
- """Group fixture for group API resource tests."""
- _id = uuid.uuid4().hex
- data = {
- "name": f"test-group-{_id}",
- "path": f"group-{_id}",
- }
- group = gl.groups.create(data)
-
- yield group
-
- try:
- group.delete()
- except gitlab.exceptions.GitlabDeleteError as e:
- print(f"Group already deleted: {e}")
-
-
-@pytest.fixture(scope="module")
-def project(gl):
- """Project fixture for project API resource tests."""
- _id = uuid.uuid4().hex
- name = f"test-project-{_id}"
-
- project = gl.projects.create(name=name)
-
- yield project
-
- try:
- project.delete()
- except gitlab.exceptions.GitlabDeleteError as e:
- print(f"Project already deleted: {e}")
-
-
-@pytest.fixture(scope="function")
-def merge_request(project, wait_for_sidekiq):
- """Fixture used to create a merge_request.
-
- It will create a branch, add a commit to the branch, and then create a
- merge request against project.default_branch. The MR will be returned.
-
- When finished any created merge requests and branches will be deleted.
-
- NOTE: No attempt is made to restore project.default_branch to its previous
- state. So if the merge request is merged then its content will be in the
- project.default_branch branch.
- """
-
- to_delete = []
-
- def _merge_request(*, source_branch: str):
- # Wait for processes to be done before we start...
- # NOTE(jlvillal): Sometimes the CI would give a "500 Internal Server
- # Error". Hoping that waiting until all other processes are done will
- # help with that.
- result = wait_for_sidekiq(timeout=60)
- assert result is True, "sidekiq process should have terminated but did not"
-
- project.refresh() # Gets us the current default branch
- project.branches.create(
- {"branch": source_branch, "ref": project.default_branch}
- )
- # NOTE(jlvillal): Must create a commit in the new branch before we can
- # create an MR that will work.
- project.files.create(
- {
- "file_path": f"README.{source_branch}",
- "branch": source_branch,
- "content": "Initial content",
- "commit_message": "New commit in new branch",
- }
- )
- mr = project.mergerequests.create(
- {
- "source_branch": source_branch,
- "target_branch": project.default_branch,
- "title": "Should remove source branch",
- "remove_source_branch": True,
- }
- )
- result = wait_for_sidekiq(timeout=60)
- assert result is True, "sidekiq process should have terminated but did not"
-
- mr_iid = mr.iid
- for _ in range(60):
- mr = project.mergerequests.get(mr_iid)
- if mr.merge_status != "checking":
- break
- time.sleep(0.5)
- assert mr.merge_status != "checking"
-
- to_delete.append((mr.iid, source_branch))
- return mr
-
- yield _merge_request
-
- for mr_iid, source_branch in to_delete:
- project.mergerequests.delete(mr_iid)
- try:
- project.branches.delete(source_branch)
- except gitlab.exceptions.GitlabDeleteError:
- # Ignore if branch was already deleted
- pass
-
-
-@pytest.fixture(scope="module")
-def project_file(project):
- """File fixture for tests requiring a project with files and branches."""
- project_file = project.files.create(
- {
- "file_path": "README",
- "branch": "master",
- "content": "Initial content",
- "commit_message": "Initial commit",
- }
- )
-
- return project_file
-
-
-@pytest.fixture(scope="function")
-def release(project, project_file):
- _id = uuid.uuid4().hex
- name = f"test-release-{_id}"
-
- project.refresh() # Gets us the current default branch
- release = project.releases.create(
- {
- "name": name,
- "tag_name": _id,
- "description": "description",
- "ref": project.default_branch,
- }
- )
-
- return release
-
-
-@pytest.fixture(scope="module")
-def user(gl):
- """User fixture for user API resource tests."""
- _id = uuid.uuid4().hex
- email = f"user{_id}@email.com"
- username = f"user{_id}"
- name = f"User {_id}"
- password = "fakepassword"
-
- user = gl.users.create(email=email, username=username, name=name, password=password)
-
- yield user
-
- try:
- user.delete()
- except gitlab.exceptions.GitlabDeleteError as e:
- print(f"User already deleted: {e}")
-
-
-@pytest.fixture(scope="module")
-def issue(project):
- """Issue fixture for issue API resource tests."""
- _id = uuid.uuid4().hex
- data = {"title": f"Issue {_id}", "description": f"Issue {_id} description"}
-
- return project.issues.create(data)
-
-
-@pytest.fixture(scope="module")
-def milestone(project):
- _id = uuid.uuid4().hex
- data = {"title": f"milestone{_id}"}
-
- return project.milestones.create(data)
-
-
-@pytest.fixture(scope="module")
-def label(project):
- """Label fixture for project label API resource tests."""
- _id = uuid.uuid4().hex
- data = {
- "name": f"prjlabel{_id}",
- "description": f"prjlabel1 {_id} description",
- "color": "#112233",
- }
-
- return project.labels.create(data)
-
-
-@pytest.fixture(scope="module")
-def group_label(group):
- """Label fixture for group label API resource tests."""
- _id = uuid.uuid4().hex
- data = {
- "name": f"grplabel{_id}",
- "description": f"grplabel1 {_id} description",
- "color": "#112233",
- }
-
- return group.labels.create(data)
-
-
-@pytest.fixture(scope="module")
-def variable(project):
- """Variable fixture for project variable API resource tests."""
- _id = uuid.uuid4().hex
- data = {"key": f"var{_id}", "value": f"Variable {_id}"}
-
- return project.variables.create(data)
-
-
-@pytest.fixture(scope="module")
-def deploy_token(project):
- """Deploy token fixture for project deploy token API resource tests."""
- _id = uuid.uuid4().hex
- data = {
- "name": f"token-{_id}",
- "username": "root",
- "expires_at": "2021-09-09",
- "scopes": "read_registry",
- }
-
- return project.deploytokens.create(data)
-
-
-@pytest.fixture(scope="module")
-def group_deploy_token(group):
- """Deploy token fixture for group deploy token API resource tests."""
- _id = uuid.uuid4().hex
- data = {
- "name": f"group-token-{_id}",
- "username": "root",
- "expires_at": "2021-09-09",
- "scopes": "read_registry",
- }
-
- return group.deploytokens.create(data)
-
-
-@pytest.fixture(scope="session")
-def GPG_KEY():
- return """-----BEGIN PGP PUBLIC KEY BLOCK-----
-
-mQENBFn5mzYBCADH6SDVPAp1zh/hxmTi0QplkOfExBACpuY6OhzNdIg+8/528b3g
-Y5YFR6T/HLv/PmeHskUj21end1C0PNG2T9dTx+2Vlh9ISsSG1kyF9T5fvMR3bE0x
-Dl6S489CXZrjPTS9SHk1kF+7dwjUxLJyxF9hPiSihFefDFu3NeOtG/u8vbC1mewQ
-ZyAYue+mqtqcCIFFoBz7wHKMWjIVSJSyTkXExu4OzpVvy3l2EikbvavI3qNz84b+
-Mgkv/kiBlNoCy3CVuPk99RYKZ3lX1vVtqQ0OgNGQvb4DjcpyjmbKyibuZwhDjIOh
-au6d1OyEbayTntd+dQ4j9EMSnEvm/0MJ4eXPABEBAAG0G0dpdGxhYlRlc3QxIDxm
-YWtlQGZha2UudGxkPokBNwQTAQgAIQUCWfmbNgIbAwULCQgHAgYVCAkKCwIEFgID
-AQIeAQIXgAAKCRBgxELHf8f3hF3yB/wNJlWPKY65UsB4Lo0hs1OxdxCDqXogSi0u
-6crDEIiyOte62pNZKzWy8TJcGZvznRTZ7t8hXgKFLz3PRMcl+vAiRC6quIDUj+2V
-eYfwaItd1lUfzvdCaC7Venf4TQ74f5vvNg/zoGwE6eRoSbjlLv9nqsxeA0rUBUQL
-LYikWhVMP3TrlfgfduYvh6mfgh57BDLJ9kJVpyfxxx9YLKZbaas9sPa6LgBtR555
-JziUxHmbEv8XCsUU8uoFeP1pImbNBplqE3wzJwzOMSmmch7iZzrAwfN7N2j3Wj0H
-B5kQddJ9dmB4BbU0IXGhWczvdpxboI2wdY8a1JypxOdePoph/43iuQENBFn5mzYB
-CADnTPY0Zf3d9zLjBNgIb3yDl94uOcKCq0twNmyjMhHzGqw+UMe9BScy34GL94Al
-xFRQoaL+7P8hGsnsNku29A/VDZivcI+uxTx4WQ7OLcn7V0bnHV4d76iky2ufbUt/
-GofthjDs1SonePO2N09sS4V4uK0d5N4BfCzzXgvg8etCLxNmC9BGt7AaKUUzKBO4
-2QvNNaC2C/8XEnOgNWYvR36ylAXAmo0sGFXUsBCTiq1fugS9pwtaS2JmaVpZZ3YT
-pMZlS0+SjC5BZYFqSmKCsA58oBRzCxQz57nR4h5VEflgD+Hy0HdW0UHETwz83E6/
-U0LL6YyvhwFr6KPq5GxinSvfABEBAAGJAR8EGAEIAAkFAln5mzYCGwwACgkQYMRC
-x3/H94SJgwgAlKQb10/xcL/epdDkR7vbiei7huGLBpRDb/L5fM8B5W77Qi8Xmuqj
-cCu1j99ZCA5hs/vwVn8j8iLSBGMC5gxcuaar/wtmiaEvT9fO/h6q4opG7NcuiJ8H
-wRj8ccJmRssNqDD913PLz7T40Ts62blhrEAlJozGVG/q7T3RAZcskOUHKeHfc2RI
-YzGsC/I9d7k6uxAv1L9Nm5F2HaAQDzhkdd16nKkGaPGR35cT1JLInkfl5cdm7ldN
-nxs4TLO3kZjUTgWKdhpgRNF5hwaz51ZjpebaRf/ZqRuNyX4lIRolDxzOn/+O1o8L
-qG2ZdhHHmSK2LaQLFiSprUkikStNU9BqSQ==
-=5OGa
------END PGP PUBLIC KEY BLOCK-----"""
-
-
-@pytest.fixture(scope="session")
-def SSH_KEY():
- return (
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDZAjAX8vTiHD7Yi3/EzuVaDChtih"
- "79HyJZ6H9dEqxFfmGA1YnncE0xujQ64TCebhkYJKzmTJCImSVkOu9C4hZgsw6eE76n"
- "+Cg3VwEeDUFy+GXlEJWlHaEyc3HWioxgOALbUp3rOezNh+d8BDwwqvENGoePEBsz5l"
- "a6WP5lTi/HJIjAl6Hu+zHgdj1XVExeH+S52EwpZf/ylTJub0Bl5gHwf/siVE48mLMI"
- "sqrukXTZ6Zg+8EHAIvIQwJ1dKcXe8P5IoLT7VKrbkgAnolS0I8J+uH7KtErZJb5oZh"
- "S4OEwsNpaXMAr+6/wWSpircV2/e7sFLlhlKBC4Iq1MpqlZ7G3p foo@bar"
- )
-
-
-@pytest.fixture(scope="session")
-def DEPLOY_KEY():
- return (
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDFdRyjJQh+1niBpXqE2I8dzjG"
- "MXFHlRjX9yk/UfOn075IdaockdU58sw2Ai1XIWFpZpfJkW7z+P47ZNSqm1gzeXI"
- "rtKa9ZUp8A7SZe8vH4XVn7kh7bwWCUirqtn8El9XdqfkzOs/+FuViriUWoJVpA6"
- "WZsDNaqINFKIA5fj/q8XQw+BcS92L09QJg9oVUuH0VVwNYbU2M2IRmSpybgC/gu"
- "uWTrnCDMmLItksATifLvRZwgdI8dr+q6tbxbZknNcgEPrI2jT0hYN9ZcjNeWuyv"
- "rke9IepE7SPBT41C+YtUX4dfDZDmczM1cE0YL/krdUCfuZHMa4ZS2YyNd6slufc"
- "vn bar@foo"
- )
diff --git a/tests/functional/ee-test.py b/tests/functional/ee-test.py
deleted file mode 100755
index 3a99951..0000000
--- a/tests/functional/ee-test.py
+++ /dev/null
@@ -1,158 +0,0 @@
-#!/usr/bin/env python
-
-import gitlab
-
-P1 = "root/project1"
-P2 = "root/project2"
-MR_P1 = 1
-I_P1 = 1
-I_P2 = 1
-EPIC_ISSUES = [4, 5]
-G1 = "group1"
-LDAP_CN = "app1"
-LDAP_PROVIDER = "ldapmain"
-
-
-def start_log(message):
- print("Testing %s... " % message, end="")
-
-
-def end_log():
- print("OK")
-
-
-gl = gitlab.Gitlab.from_config("ee")
-project1 = gl.projects.get(P1)
-project2 = gl.projects.get(P2)
-issue_p1 = project1.issues.get(I_P1)
-issue_p2 = project2.issues.get(I_P2)
-group1 = gl.groups.get(G1)
-mr = project1.mergerequests.get(1)
-
-start_log("MR approvals")
-approval = project1.approvals.get()
-v = approval.reset_approvals_on_push
-approval.reset_approvals_on_push = not v
-approval.save()
-approval = project1.approvals.get()
-assert v != approval.reset_approvals_on_push
-project1.approvals.set_approvers(1, [1], [])
-approval = project1.approvals.get()
-assert approval.approvers[0]["user"]["id"] == 1
-
-approval = mr.approvals.get()
-approval.approvals_required = 2
-approval.save()
-approval = mr.approvals.get()
-assert approval.approvals_required == 2
-approval.approvals_required = 3
-approval.save()
-approval = mr.approvals.get()
-assert approval.approvals_required == 3
-mr.approvals.set_approvers(1, [1], [])
-approval = mr.approvals.get()
-assert approval.approvers[0]["user"]["id"] == 1
-
-ars = project1.approvalrules.list(all=True)
-assert len(ars) == 0
-project1.approvalrules.create(
- {"name": "approval-rule", "approvals_required": 1, "group_ids": [group1.id]}
-)
-ars = project1.approvalrules.list(all=True)
-assert len(ars) == 1
-assert ars[0].approvals_required == 2
-ars[0].save()
-ars = project1.approvalrules.list(all=True)
-assert len(ars) == 1
-assert ars[0].approvals_required == 2
-ars[0].delete()
-ars = project1.approvalrules.list(all=True)
-assert len(ars) == 0
-end_log()
-
-start_log("geo nodes")
-# very basic tests because we only have 1 node...
-nodes = gl.geonodes.list()
-status = gl.geonodes.status()
-end_log()
-
-start_log("issue links")
-# bit of cleanup just in case
-for link in issue_p1.links.list():
- issue_p1.links.delete(link.issue_link_id)
-
-src, dst = issue_p1.links.create({"target_project_id": P2, "target_issue_iid": I_P2})
-links = issue_p1.links.list()
-link_id = links[0].issue_link_id
-issue_p1.links.delete(link_id)
-end_log()
-
-start_log("LDAP links")
-# bit of cleanup just in case
-if hasattr(group1, "ldap_group_links"):
- for link in group1.ldap_group_links:
- group1.delete_ldap_group_link(link["cn"], link["provider"])
-assert gl.ldapgroups.list()
-group1.add_ldap_group_link(LDAP_CN, 30, LDAP_PROVIDER)
-group1.ldap_sync()
-group1.delete_ldap_group_link(LDAP_CN)
-end_log()
-
-start_log("boards")
-# bit of cleanup just in case
-for board in project1.boards.list():
- if board.name == "testboard":
- board.delete()
-board = project1.boards.create({"name": "testboard"})
-board = project1.boards.get(board.id)
-project1.boards.delete(board.id)
-
-for board in group1.boards.list():
- if board.name == "testboard":
- board.delete()
-board = group1.boards.create({"name": "testboard"})
-board = group1.boards.get(board.id)
-group1.boards.delete(board.id)
-end_log()
-
-start_log("push rules")
-pr = project1.pushrules.get()
-if pr:
- pr.delete()
-pr = project1.pushrules.create({"deny_delete_tag": True})
-pr.deny_delete_tag = False
-pr.save()
-pr = project1.pushrules.get()
-assert pr is not None
-assert pr.deny_delete_tag is False
-pr.delete()
-end_log()
-
-start_log("license")
-license = gl.get_license()
-assert "user_limit" in license
-try:
- gl.set_license("dummykey")
-except Exception as e:
- assert "The license key is invalid." in e.error_message
-end_log()
-
-start_log("epics")
-epic = group1.epics.create({"title": "Test epic"})
-epic.title = "Fixed title"
-epic.labels = ["label1", "label2"]
-epic.save()
-epic = group1.epics.get(epic.iid)
-assert epic.title == "Fixed title"
-assert len(group1.epics.list())
-
-# issues
-assert not epic.issues.list()
-for i in EPIC_ISSUES:
- epic.issues.create({"issue_id": i})
-assert len(EPIC_ISSUES) == len(epic.issues.list())
-for ei in epic.issues.list():
- ei.delete()
-
-epic.delete()
-end_log()
diff --git a/tests/functional/fixtures/.env b/tests/functional/fixtures/.env
deleted file mode 100644
index 374f7ac..0000000
--- a/tests/functional/fixtures/.env
+++ /dev/null
@@ -1,2 +0,0 @@
-GITLAB_IMAGE=gitlab/gitlab-ce
-GITLAB_TAG=14.3.2-ce.0
diff --git a/tests/functional/fixtures/avatar.png b/tests/functional/fixtures/avatar.png
deleted file mode 100644
index a3a767c..0000000
--- a/tests/functional/fixtures/avatar.png
+++ /dev/null
Binary files differ
diff --git a/tests/functional/fixtures/docker-compose.yml b/tests/functional/fixtures/docker-compose.yml
deleted file mode 100644
index 134f266..0000000
--- a/tests/functional/fixtures/docker-compose.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-version: '3'
-
-networks:
- gitlab-network:
- name: gitlab-network
-
-services:
- gitlab:
- image: '${GITLAB_IMAGE}:${GITLAB_TAG}'
- container_name: 'gitlab-test'
- hostname: 'gitlab.test'
- privileged: true # Just in case https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/1350
- environment:
- GITLAB_ROOT_PASSWORD: 5iveL!fe
- GITLAB_SHARED_RUNNERS_REGISTRATION_TOKEN: registration-token
- GITLAB_OMNIBUS_CONFIG: |
- external_url 'http://gitlab.test'
- registry['enable'] = false
- nginx['redirect_http_to_https'] = false
- nginx['listen_port'] = 80
- nginx['listen_https'] = false
- pages_external_url 'http://pages.gitlab.lxd'
- gitlab_pages['enable'] = true
- gitlab_pages['inplace_chroot'] = true
- prometheus['enable'] = false
- alertmanager['enable'] = false
- node_exporter['enable'] = false
- redis_exporter['enable'] = false
- postgres_exporter['enable'] = false
- pgbouncer_exporter['enable'] = false
- gitlab_exporter['enable'] = false
- grafana['enable'] = false
- letsencrypt['enable'] = false
- ports:
- - '8080:80'
- - '2222:22'
- networks:
- - gitlab-network
-
- gitlab-runner:
- image: gitlab/gitlab-runner:latest
- container_name: 'gitlab-runner-test'
- depends_on:
- - gitlab
- networks:
- - gitlab-network
diff --git a/tests/functional/fixtures/set_token.rb b/tests/functional/fixtures/set_token.rb
deleted file mode 100644
index 503588b..0000000
--- a/tests/functional/fixtures/set_token.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#programmatically-creating-a-personal-access-token
-
-user = User.find_by_username('root')
-
-token = user.personal_access_tokens.first_or_create(scopes: [:api, :sudo], name: 'default');
-token.set_token('python-gitlab-token');
-token.save!
-
-puts token.token
diff --git a/tests/smoke/__init__.py b/tests/smoke/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tests/smoke/__init__.py
+++ /dev/null
diff --git a/tests/smoke/test_dists.py b/tests/smoke/test_dists.py
deleted file mode 100644
index 6f38ff7..0000000
--- a/tests/smoke/test_dists.py
+++ /dev/null
@@ -1,33 +0,0 @@
-import tarfile
-import zipfile
-from pathlib import Path
-from sys import version_info
-
-import pytest
-from setuptools import sandbox
-
-from gitlab import __title__, __version__
-
-DIST_DIR = Path("dist")
-TEST_DIR = "tests"
-SDIST_FILE = f"{__title__}-{__version__}.tar.gz"
-WHEEL_FILE = (
- f"{__title__.replace('-', '_')}-{__version__}-py{version_info.major}-none-any.whl"
-)
-
-
-@pytest.fixture(scope="function")
-def build():
- sandbox.run_setup("setup.py", ["clean", "--all"])
- return sandbox.run_setup("setup.py", ["sdist", "bdist_wheel"])
-
-
-def test_sdist_includes_tests(build):
- sdist = tarfile.open(DIST_DIR / SDIST_FILE, "r:gz")
- test_dir = sdist.getmember(f"{__title__}-{__version__}/{TEST_DIR}")
- assert test_dir.isdir()
-
-
-def test_wheel_excludes_tests(build):
- wheel = zipfile.ZipFile(DIST_DIR / WHEEL_FILE)
- assert [not file.startswith(TEST_DIR) for file in wheel.namelist()]
diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tests/unit/__init__.py
+++ /dev/null
diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py
deleted file mode 100644
index f58c77a..0000000
--- a/tests/unit/conftest.py
+++ /dev/null
@@ -1,84 +0,0 @@
-import pytest
-
-import gitlab
-
-
-@pytest.fixture
-def gl():
- return gitlab.Gitlab(
- "http://localhost",
- private_token="private_token",
- ssl_verify=True,
- api_version="4",
- )
-
-
-@pytest.fixture
-def gl_retry():
- return gitlab.Gitlab(
- "http://localhost",
- private_token="private_token",
- ssl_verify=True,
- api_version="4",
- retry_transient_errors=True,
- )
-
-
-# Todo: parametrize, but check what tests it's really useful for
-@pytest.fixture
-def gl_trailing():
- return gitlab.Gitlab(
- "http://localhost/", private_token="private_token", api_version="4"
- )
-
-
-@pytest.fixture
-def default_config(tmpdir):
- valid_config = """[global]
- default = one
- ssl_verify = true
- timeout = 2
-
- [one]
- url = http://one.url
- private_token = ABCDEF
- """
-
- config_path = tmpdir.join("python-gitlab.cfg")
- config_path.write(valid_config)
- return str(config_path)
-
-
-@pytest.fixture
-def tag_name():
- return "v1.0.0"
-
-
-@pytest.fixture
-def group(gl):
- return gl.groups.get(1, lazy=True)
-
-
-@pytest.fixture
-def project(gl):
- return gl.projects.get(1, lazy=True)
-
-
-@pytest.fixture
-def project_issue(project):
- return project.issues.get(1, lazy=True)
-
-
-@pytest.fixture
-def project_merge_request(project):
- return project.mergerequests.get(1, lazy=True)
-
-
-@pytest.fixture
-def release(project, tag_name):
- return project.releases.get(tag_name, lazy=True)
-
-
-@pytest.fixture
-def user(gl):
- return gl.users.get(1, lazy=True)
diff --git a/tests/unit/data/todo.json b/tests/unit/data/todo.json
deleted file mode 100644
index 93b2151..0000000
--- a/tests/unit/data/todo.json
+++ /dev/null
@@ -1,75 +0,0 @@
-[
- {
- "id": 102,
- "project": {
- "id": 2,
- "name": "Gitlab Ce",
- "name_with_namespace": "Gitlab Org / Gitlab Ce",
- "path": "gitlab-ce",
- "path_with_namespace": "gitlab-org/gitlab-ce"
- },
- "author": {
- "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"
- },
- "action_name": "marked",
- "target_type": "MergeRequest",
- "target": {
- "id": 34,
- "iid": 7,
- "project_id": 2,
- "title": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.",
- "description": "Et ea et omnis illum cupiditate. Dolor aspernatur tenetur ducimus facilis est nihil. Quo esse cupiditate molestiae illo corrupti qui quidem dolor.",
- "state": "opened",
- "created_at": "2016-06-17T07:49:24.419Z",
- "updated_at": "2016-06-17T07:52:43.484Z",
- "target_branch": "tutorials_git_tricks",
- "source_branch": "DNSBL_docs",
- "upvotes": 0,
- "downvotes": 0,
- "author": {
- "name": "Maxie Medhurst",
- "username": "craig_rutherford",
- "id": 12,
- "state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/craig_rutherford"
- },
- "assignee": {
- "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"
- },
- "source_project_id": 2,
- "target_project_id": 2,
- "labels": [],
- "work_in_progress": false,
- "milestone": {
- "id": 32,
- "iid": 2,
- "project_id": 2,
- "title": "v1.0",
- "description": "Assumenda placeat ea voluptatem voluptate qui.",
- "state": "active",
- "created_at": "2016-06-17T07:47:34.163Z",
- "updated_at": "2016-06-17T07:47:34.163Z",
- "due_date": null
- },
- "merge_when_pipeline_succeeds": false,
- "merge_status": "cannot_be_merged",
- "subscribed": true,
- "user_notes_count": 7
- },
- "target_url": "https://gitlab.example.com/gitlab-org/gitlab-ce/merge_requests/7",
- "body": "Dolores in voluptatem tenetur praesentium omnis repellendus voluptatem quaerat.",
- "state": "pending",
- "created_at": "2016-06-17T07:52:35.225Z"
- }
-]
diff --git a/tests/unit/mixins/__init__.py b/tests/unit/mixins/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tests/unit/mixins/__init__.py
+++ /dev/null
diff --git a/tests/unit/mixins/test_meta_mixins.py b/tests/unit/mixins/test_meta_mixins.py
deleted file mode 100644
index 4c8845b..0000000
--- a/tests/unit/mixins/test_meta_mixins.py
+++ /dev/null
@@ -1,58 +0,0 @@
-from gitlab.mixins import (
- CreateMixin,
- CRUDMixin,
- DeleteMixin,
- GetMixin,
- ListMixin,
- NoUpdateMixin,
- RetrieveMixin,
- UpdateMixin,
-)
-
-
-def test_retrieve_mixin():
- class M(RetrieveMixin):
- pass
-
- obj = M()
- assert hasattr(obj, "list")
- assert hasattr(obj, "get")
- assert not hasattr(obj, "create")
- assert not hasattr(obj, "update")
- assert not hasattr(obj, "delete")
- assert isinstance(obj, ListMixin)
- assert isinstance(obj, GetMixin)
-
-
-def test_crud_mixin():
- class M(CRUDMixin):
- pass
-
- obj = M()
- assert hasattr(obj, "get")
- assert hasattr(obj, "list")
- assert hasattr(obj, "create")
- assert hasattr(obj, "update")
- assert hasattr(obj, "delete")
- assert isinstance(obj, ListMixin)
- assert isinstance(obj, GetMixin)
- assert isinstance(obj, CreateMixin)
- assert isinstance(obj, UpdateMixin)
- assert isinstance(obj, DeleteMixin)
-
-
-def test_no_update_mixin():
- class M(NoUpdateMixin):
- pass
-
- obj = M()
- assert hasattr(obj, "get")
- assert hasattr(obj, "list")
- assert hasattr(obj, "create")
- assert not hasattr(obj, "update")
- assert hasattr(obj, "delete")
- assert isinstance(obj, ListMixin)
- assert isinstance(obj, GetMixin)
- assert isinstance(obj, CreateMixin)
- assert not isinstance(obj, UpdateMixin)
- assert isinstance(obj, DeleteMixin)
diff --git a/tests/unit/mixins/test_mixin_methods.py b/tests/unit/mixins/test_mixin_methods.py
deleted file mode 100644
index 626230e..0000000
--- a/tests/unit/mixins/test_mixin_methods.py
+++ /dev/null
@@ -1,300 +0,0 @@
-import pytest
-from httmock import HTTMock, response, urlmatch # noqa
-
-from gitlab import base
-from gitlab.mixins import (
- CreateMixin,
- DeleteMixin,
- GetMixin,
- GetWithoutIdMixin,
- ListMixin,
- RefreshMixin,
- SaveMixin,
- SetMixin,
- UpdateMixin,
-)
-
-
-class FakeObject(base.RESTObject):
- pass
-
-
-class FakeManager(base.RESTManager):
- _path = "/tests"
- _obj_cls = FakeObject
-
-
-def test_get_mixin(gl):
- class M(GetMixin, FakeManager):
- pass
-
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/tests/42", method="get")
- def resp_cont(url, request):
- headers = {"Content-Type": "application/json"}
- content = '{"id": 42, "foo": "bar"}'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- mgr = M(gl)
- obj = mgr.get(42)
- assert isinstance(obj, FakeObject)
- assert obj.foo == "bar"
- assert obj.id == 42
-
-
-def test_refresh_mixin(gl):
- class TestClass(RefreshMixin, FakeObject):
- pass
-
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/tests/42", method="get")
- def resp_cont(url, request):
- headers = {"Content-Type": "application/json"}
- content = '{"id": 42, "foo": "bar"}'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- mgr = FakeManager(gl)
- obj = TestClass(mgr, {"id": 42})
- res = obj.refresh()
- assert res is None
- assert obj.foo == "bar"
- assert obj.id == 42
-
-
-def test_get_without_id_mixin(gl):
- class M(GetWithoutIdMixin, FakeManager):
- pass
-
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/tests", method="get")
- def resp_cont(url, request):
- headers = {"Content-Type": "application/json"}
- content = '{"foo": "bar"}'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- mgr = M(gl)
- obj = mgr.get()
- assert isinstance(obj, FakeObject)
- assert obj.foo == "bar"
- assert not hasattr(obj, "id")
-
-
-def test_list_mixin(gl):
- class M(ListMixin, FakeManager):
- pass
-
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/tests", method="get")
- def resp_cont(url, request):
- headers = {"Content-Type": "application/json"}
- content = '[{"id": 42, "foo": "bar"},{"id": 43, "foo": "baz"}]'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- # test RESTObjectList
- mgr = M(gl)
- obj_list = mgr.list(as_list=False)
- assert isinstance(obj_list, base.RESTObjectList)
- for obj in obj_list:
- assert isinstance(obj, FakeObject)
- assert obj.id in (42, 43)
-
- # test list()
- obj_list = mgr.list(all=True)
- assert isinstance(obj_list, list)
- assert obj_list[0].id == 42
- assert obj_list[1].id == 43
- assert isinstance(obj_list[0], FakeObject)
- assert len(obj_list) == 2
-
-
-def test_list_other_url(gl):
- class M(ListMixin, FakeManager):
- pass
-
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/others", method="get")
- def resp_cont(url, request):
- headers = {"Content-Type": "application/json"}
- content = '[{"id": 42, "foo": "bar"}]'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- mgr = M(gl)
- obj_list = mgr.list(path="/others", as_list=False)
- assert isinstance(obj_list, base.RESTObjectList)
- obj = obj_list.next()
- assert obj.id == 42
- assert obj.foo == "bar"
- with pytest.raises(StopIteration):
- obj_list.next()
-
-
-def test_create_mixin_missing_attrs(gl):
- class M(CreateMixin, FakeManager):
- _create_attrs = base.RequiredOptional(
- required=("foo",), optional=("bar", "baz")
- )
-
- mgr = M(gl)
- data = {"foo": "bar", "baz": "blah"}
- mgr._check_missing_create_attrs(data)
-
- data = {"baz": "blah"}
- with pytest.raises(AttributeError) as error:
- mgr._check_missing_create_attrs(data)
- assert "foo" in str(error.value)
-
-
-def test_create_mixin(gl):
- class M(CreateMixin, FakeManager):
- _create_attrs = base.RequiredOptional(
- required=("foo",), optional=("bar", "baz")
- )
- _update_attrs = base.RequiredOptional(required=("foo",), optional=("bam",))
-
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/tests", method="post")
- def resp_cont(url, request):
- headers = {"Content-Type": "application/json"}
- content = '{"id": 42, "foo": "bar"}'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- mgr = M(gl)
- obj = mgr.create({"foo": "bar"})
- assert isinstance(obj, FakeObject)
- assert obj.id == 42
- assert obj.foo == "bar"
-
-
-def test_create_mixin_custom_path(gl):
- class M(CreateMixin, FakeManager):
- _create_attrs = base.RequiredOptional(
- required=("foo",), optional=("bar", "baz")
- )
- _update_attrs = base.RequiredOptional(required=("foo",), optional=("bam",))
-
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/others", method="post")
- def resp_cont(url, request):
- headers = {"Content-Type": "application/json"}
- content = '{"id": 42, "foo": "bar"}'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- mgr = M(gl)
- obj = mgr.create({"foo": "bar"}, path="/others")
- assert isinstance(obj, FakeObject)
- assert obj.id == 42
- assert obj.foo == "bar"
-
-
-def test_update_mixin_missing_attrs(gl):
- class M(UpdateMixin, FakeManager):
- _update_attrs = base.RequiredOptional(
- required=("foo",), optional=("bar", "baz")
- )
-
- mgr = M(gl)
- data = {"foo": "bar", "baz": "blah"}
- mgr._check_missing_update_attrs(data)
-
- data = {"baz": "blah"}
- with pytest.raises(AttributeError) as error:
- mgr._check_missing_update_attrs(data)
- assert "foo" in str(error.value)
-
-
-def test_update_mixin(gl):
- class M(UpdateMixin, FakeManager):
- _create_attrs = base.RequiredOptional(
- required=("foo",), optional=("bar", "baz")
- )
- _update_attrs = base.RequiredOptional(required=("foo",), optional=("bam",))
-
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/tests/42", method="put")
- def resp_cont(url, request):
- headers = {"Content-Type": "application/json"}
- content = '{"id": 42, "foo": "baz"}'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- mgr = M(gl)
- server_data = mgr.update(42, {"foo": "baz"})
- assert isinstance(server_data, dict)
- assert server_data["id"] == 42
- assert server_data["foo"] == "baz"
-
-
-def test_update_mixin_no_id(gl):
- class M(UpdateMixin, FakeManager):
- _create_attrs = base.RequiredOptional(
- required=("foo",), optional=("bar", "baz")
- )
- _update_attrs = base.RequiredOptional(required=("foo",), optional=("bam",))
-
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/tests", method="put")
- def resp_cont(url, request):
- headers = {"Content-Type": "application/json"}
- content = '{"foo": "baz"}'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- mgr = M(gl)
- server_data = mgr.update(new_data={"foo": "baz"})
- assert isinstance(server_data, dict)
- assert server_data["foo"] == "baz"
-
-
-def test_delete_mixin(gl):
- class M(DeleteMixin, FakeManager):
- pass
-
- @urlmatch(
- scheme="http", netloc="localhost", path="/api/v4/tests/42", method="delete"
- )
- def resp_cont(url, request):
- headers = {"Content-Type": "application/json"}
- content = ""
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- mgr = M(gl)
- mgr.delete(42)
-
-
-def test_save_mixin(gl):
- class M(UpdateMixin, FakeManager):
- pass
-
- class TestClass(SaveMixin, base.RESTObject):
- pass
-
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/tests/42", method="put")
- def resp_cont(url, request):
- headers = {"Content-Type": "application/json"}
- content = '{"id": 42, "foo": "baz"}'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- mgr = M(gl)
- obj = TestClass(mgr, {"id": 42, "foo": "bar"})
- obj.foo = "baz"
- obj.save()
- assert obj._attrs["foo"] == "baz"
- assert obj._updated_attrs == {}
-
-
-def test_set_mixin(gl):
- class M(SetMixin, FakeManager):
- pass
-
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/tests/foo", method="put")
- def resp_cont(url, request):
- headers = {"Content-Type": "application/json"}
- content = '{"key": "foo", "value": "bar"}'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- mgr = M(gl)
- obj = mgr.set("foo", "bar")
- assert isinstance(obj, FakeObject)
- assert obj.key == "foo"
- assert obj.value == "bar"
diff --git a/tests/unit/mixins/test_object_mixins_attributes.py b/tests/unit/mixins/test_object_mixins_attributes.py
deleted file mode 100644
index d54fa3a..0000000
--- a/tests/unit/mixins/test_object_mixins_attributes.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 Mika Mäenpää <mika.j.maenpaa@tut.fi>,
-# Tampere University of Technology
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-from gitlab.mixins import (
- AccessRequestMixin,
- SetMixin,
- SubscribableMixin,
- TimeTrackingMixin,
- TodoMixin,
- UserAgentDetailMixin,
-)
-
-
-def test_access_request_mixin():
- class TestClass(AccessRequestMixin):
- pass
-
- obj = TestClass()
- assert hasattr(obj, "approve")
-
-
-def test_subscribable_mixin():
- class TestClass(SubscribableMixin):
- pass
-
- obj = TestClass()
- assert hasattr(obj, "subscribe")
- assert hasattr(obj, "unsubscribe")
-
-
-def test_todo_mixin():
- class TestClass(TodoMixin):
- pass
-
- obj = TestClass()
- assert hasattr(obj, "todo")
-
-
-def test_time_tracking_mixin():
- class TestClass(TimeTrackingMixin):
- pass
-
- obj = TestClass()
- assert hasattr(obj, "time_stats")
- assert hasattr(obj, "time_estimate")
- assert hasattr(obj, "reset_time_estimate")
- assert hasattr(obj, "add_spent_time")
- assert hasattr(obj, "reset_spent_time")
-
-
-def test_set_mixin():
- class TestClass(SetMixin):
- pass
-
- obj = TestClass()
- assert hasattr(obj, "set")
-
-
-def test_user_agent_detail_mixin():
- class TestClass(UserAgentDetailMixin):
- pass
-
- obj = TestClass()
- assert hasattr(obj, "user_agent_detail")
diff --git a/tests/unit/objects/__init__.py b/tests/unit/objects/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tests/unit/objects/__init__.py
+++ /dev/null
diff --git a/tests/unit/objects/conftest.py b/tests/unit/objects/conftest.py
deleted file mode 100644
index d8a40d9..0000000
--- a/tests/unit/objects/conftest.py
+++ /dev/null
@@ -1,70 +0,0 @@
-"""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 no_content():
- return {"message": "204 No Content"}
-
-
-@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/tests/unit/objects/test_appearance.py b/tests/unit/objects/test_appearance.py
deleted file mode 100644
index 0de6524..0000000
--- a/tests/unit/objects/test_appearance.py
+++ /dev/null
@@ -1,65 +0,0 @@
-"""
-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):
- gl.appearance.update(title=new_title, description=new_description)
diff --git a/tests/unit/objects/test_applications.py b/tests/unit/objects/test_applications.py
deleted file mode 100644
index 61de019..0000000
--- a/tests/unit/objects/test_applications.py
+++ /dev/null
@@ -1,44 +0,0 @@
-"""
-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/tests/unit/objects/test_audit_events.py b/tests/unit/objects/test_audit_events.py
deleted file mode 100644
index aba778b..0000000
--- a/tests/unit/objects/test_audit_events.py
+++ /dev/null
@@ -1,109 +0,0 @@
-"""
-GitLab API:
-https://docs.gitlab.com/ee/api/audit_events.html#project-audit-events
-"""
-
-import re
-
-import pytest
-import responses
-
-from gitlab.v4.objects.audit_events import (
- AuditEvent,
- GroupAuditEvent,
- ProjectAuditEvent,
-)
-
-id = 5
-
-audit_events_content = {
- "id": 5,
- "author_id": 1,
- "entity_id": 7,
- "entity_type": "Project",
- "details": {
- "change": "prevent merge request approval from reviewers",
- "from": "",
- "to": "true",
- "author_name": "Administrator",
- "target_id": 7,
- "target_type": "Project",
- "target_details": "twitter/typeahead-js",
- "ip_address": "127.0.0.1",
- "entity_path": "twitter/typeahead-js",
- },
- "created_at": "2020-05-26T22:55:04.230Z",
-}
-
-audit_events_url = re.compile(
- r"http://localhost/api/v4/((groups|projects)/1/)?audit_events"
-)
-
-audit_events_url_id = re.compile(
- rf"http://localhost/api/v4/((groups|projects)/1/)?audit_events/{id}"
-)
-
-
-@pytest.fixture
-def resp_list_audit_events():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=audit_events_url,
- json=[audit_events_content],
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_get_audit_event():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=audit_events_url_id,
- json=audit_events_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-def test_list_instance_audit_events(gl, resp_list_audit_events):
- audit_events = gl.audit_events.list()
- assert isinstance(audit_events, list)
- assert isinstance(audit_events[0], AuditEvent)
- assert audit_events[0].id == id
-
-
-def test_get_instance_audit_events(gl, resp_get_audit_event):
- audit_event = gl.audit_events.get(id)
- assert isinstance(audit_event, AuditEvent)
- assert audit_event.id == id
-
-
-def test_list_group_audit_events(group, resp_list_audit_events):
- audit_events = group.audit_events.list()
- assert isinstance(audit_events, list)
- assert isinstance(audit_events[0], GroupAuditEvent)
- assert audit_events[0].id == id
-
-
-def test_get_group_audit_events(group, resp_get_audit_event):
- audit_event = group.audit_events.get(id)
- assert isinstance(audit_event, GroupAuditEvent)
- assert audit_event.id == id
-
-
-def test_list_project_audit_events(project, resp_list_audit_events):
- audit_events = project.audit_events.list()
- assert isinstance(audit_events, list)
- assert isinstance(audit_events[0], ProjectAuditEvent)
- assert audit_events[0].id == id
-
-
-def test_get_project_audit_events(project, resp_get_audit_event):
- audit_event = project.audit_events.get(id)
- assert isinstance(audit_event, ProjectAuditEvent)
- assert audit_event.id == id
diff --git a/tests/unit/objects/test_badges.py b/tests/unit/objects/test_badges.py
deleted file mode 100644
index e226684..0000000
--- a/tests/unit/objects/test_badges.py
+++ /dev/null
@@ -1,210 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ee/api/project_badges.html
-GitLab API: https://docs.gitlab.com/ee/api/group_badges.html
-"""
-import re
-
-import pytest
-import responses
-
-from gitlab.v4.objects import GroupBadge, ProjectBadge
-
-link_url = (
- "http://example.com/ci_status.svg?project=example-org/example-project&ref=master"
-)
-image_url = "https://example.io/my/badge"
-
-rendered_link_url = (
- "http://example.com/ci_status.svg?project=example-org/example-project&ref=master"
-)
-rendered_image_url = "https://example.io/my/badge"
-
-new_badge = {
- "link_url": link_url,
- "image_url": image_url,
-}
-
-badge_content = {
- "name": "Coverage",
- "id": 1,
- "link_url": link_url,
- "image_url": image_url,
- "rendered_link_url": rendered_image_url,
- "rendered_image_url": rendered_image_url,
-}
-
-preview_badge_content = {
- "link_url": link_url,
- "image_url": image_url,
- "rendered_link_url": rendered_link_url,
- "rendered_image_url": rendered_image_url,
-}
-
-
-@pytest.fixture()
-def resp_get_badge():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=re.compile(r"http://localhost/api/v4/(projects|groups)/1/badges/1"),
- json=badge_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture()
-def resp_list_badges():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=re.compile(r"http://localhost/api/v4/(projects|groups)/1/badges"),
- json=[badge_content],
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture()
-def resp_create_badge():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.POST,
- url=re.compile(r"http://localhost/api/v4/(projects|groups)/1/badges"),
- json=badge_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture()
-def resp_update_badge():
- updated_content = dict(badge_content)
- updated_content["link_url"] = "http://link_url"
-
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.PUT,
- url=re.compile(r"http://localhost/api/v4/(projects|groups)/1/badges/1"),
- json=updated_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture()
-def resp_delete_badge(no_content):
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.DELETE,
- url=re.compile(r"http://localhost/api/v4/(projects|groups)/1/badges/1"),
- json=no_content,
- content_type="application/json",
- status=204,
- )
- yield rsps
-
-
-@pytest.fixture()
-def resp_preview_badge():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=re.compile(
- r"http://localhost/api/v4/(projects|groups)/1/badges/render"
- ),
- json=preview_badge_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-def test_list_project_badges(project, resp_list_badges):
- badges = project.badges.list()
- assert isinstance(badges, list)
- assert isinstance(badges[0], ProjectBadge)
-
-
-def test_list_group_badges(group, resp_list_badges):
- badges = group.badges.list()
- assert isinstance(badges, list)
- assert isinstance(badges[0], GroupBadge)
-
-
-def test_get_project_badge(project, resp_get_badge):
- badge = project.badges.get(1)
- assert isinstance(badge, ProjectBadge)
- assert badge.name == "Coverage"
- assert badge.id == 1
-
-
-def test_get_group_badge(group, resp_get_badge):
- badge = group.badges.get(1)
- assert isinstance(badge, GroupBadge)
- assert badge.name == "Coverage"
- assert badge.id == 1
-
-
-def test_delete_project_badge(project, resp_delete_badge):
- badge = project.badges.get(1, lazy=True)
- badge.delete()
-
-
-def test_delete_group_badge(group, resp_delete_badge):
- badge = group.badges.get(1, lazy=True)
- badge.delete()
-
-
-def test_create_project_badge(project, resp_create_badge):
- badge = project.badges.create(new_badge)
- assert isinstance(badge, ProjectBadge)
- assert badge.image_url == image_url
-
-
-def test_create_group_badge(group, resp_create_badge):
- badge = group.badges.create(new_badge)
- assert isinstance(badge, GroupBadge)
- assert badge.image_url == image_url
-
-
-def test_preview_project_badge(project, resp_preview_badge):
- output = project.badges.render(
- link_url=link_url,
- image_url=image_url,
- )
- assert isinstance(output, dict)
- assert "rendered_link_url" in output
- assert "rendered_image_url" in output
- assert output["link_url"] == output["rendered_link_url"]
- assert output["image_url"] == output["rendered_image_url"]
-
-
-def test_preview_group_badge(group, resp_preview_badge):
- output = group.badges.render(
- link_url=link_url,
- image_url=image_url,
- )
- assert isinstance(output, dict)
- assert "rendered_link_url" in output
- assert "rendered_image_url" in output
- assert output["link_url"] == output["rendered_link_url"]
- assert output["image_url"] == output["rendered_image_url"]
-
-
-def test_update_project_badge(project, resp_update_badge):
- badge = project.badges.get(1, lazy=True)
- badge.link_url = "http://link_url"
- badge.save()
- assert badge.link_url == "http://link_url"
-
-
-def test_update_group_badge(group, resp_update_badge):
- badge = group.badges.get(1, lazy=True)
- badge.link_url = "http://link_url"
- badge.save()
- assert badge.link_url == "http://link_url"
diff --git a/tests/unit/objects/test_bridges.py b/tests/unit/objects/test_bridges.py
deleted file mode 100644
index 4d39186..0000000
--- a/tests/unit/objects/test_bridges.py
+++ /dev/null
@@ -1,109 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ee/api/jobs.html#list-pipeline-bridges
-"""
-import pytest
-import responses
-
-from gitlab.v4.objects import ProjectPipelineBridge
-
-
-@pytest.fixture
-def resp_list_bridges():
- export_bridges_content = {
- "commit": {
- "author_email": "admin@example.com",
- "author_name": "Administrator",
- "created_at": "2015-12-24T16:51:14.000+01:00",
- "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
- "message": "Test the CI integration.",
- "short_id": "0ff3ae19",
- "title": "Test the CI integration.",
- },
- "allow_failure": False,
- "created_at": "2015-12-24T15:51:21.802Z",
- "started_at": "2015-12-24T17:54:27.722Z",
- "finished_at": "2015-12-24T17:58:27.895Z",
- "duration": 240,
- "id": 7,
- "name": "teaspoon",
- "pipeline": {
- "id": 6,
- "ref": "master",
- "sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
- "status": "pending",
- "created_at": "2015-12-24T15:50:16.123Z",
- "updated_at": "2015-12-24T18:00:44.432Z",
- "web_url": "https://example.com/foo/bar/pipelines/6",
- },
- "ref": "master",
- "stage": "test",
- "status": "pending",
- "tag": False,
- "web_url": "https://example.com/foo/bar/-/jobs/7",
- "user": {
- "id": 1,
- "name": "Administrator",
- "username": "root",
- "state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://gitlab.dev/root",
- "created_at": "2015-12-21T13:14:24.077Z",
- "public_email": "",
- "skype": "",
- "linkedin": "",
- "twitter": "",
- "website_url": "",
- "organization": "",
- },
- "downstream_pipeline": {
- "id": 5,
- "sha": "f62a4b2fb89754372a346f24659212eb8da13601",
- "ref": "master",
- "status": "pending",
- "created_at": "2015-12-24T17:54:27.722Z",
- "updated_at": "2015-12-24T17:58:27.896Z",
- "web_url": "https://example.com/diaspora/diaspora-client/pipelines/5",
- },
- }
-
- export_pipelines_content = [
- {
- "id": 6,
- "status": "pending",
- "ref": "new-pipeline",
- "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
- "web_url": "https://example.com/foo/bar/pipelines/47",
- "created_at": "2016-08-11T11:28:34.085Z",
- "updated_at": "2016-08-11T11:32:35.169Z",
- },
- ]
-
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/pipelines/6/bridges",
- json=[export_bridges_content],
- content_type="application/json",
- status=200,
- )
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/pipelines",
- json=export_pipelines_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-def test_list_projects_pipelines_bridges(project, resp_list_bridges):
- pipeline = project.pipelines.list()[0]
- bridges = pipeline.bridges.list()
-
- assert isinstance(bridges, list)
- assert isinstance(bridges[0], ProjectPipelineBridge)
- assert bridges[0].downstream_pipeline["id"] == 5
- assert (
- bridges[0].downstream_pipeline["sha"]
- == "f62a4b2fb89754372a346f24659212eb8da13601"
- )
diff --git a/tests/unit/objects/test_commits.py b/tests/unit/objects/test_commits.py
deleted file mode 100644
index 6b98117..0000000
--- a/tests/unit/objects/test_commits.py
+++ /dev/null
@@ -1,115 +0,0 @@
-"""
-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/tests/unit/objects/test_deploy_tokens.py b/tests/unit/objects/test_deploy_tokens.py
deleted file mode 100644
index 66a79fa..0000000
--- a/tests/unit/objects/test_deploy_tokens.py
+++ /dev/null
@@ -1,45 +0,0 @@
-"""
-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/tests/unit/objects/test_deployments.py b/tests/unit/objects/test_deployments.py
deleted file mode 100644
index 3cde8fe..0000000
--- a/tests/unit/objects/test_deployments.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""
-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/tests/unit/objects/test_environments.py b/tests/unit/objects/test_environments.py
deleted file mode 100644
index b49a1db..0000000
--- a/tests/unit/objects/test_environments.py
+++ /dev/null
@@ -1,30 +0,0 @@
-"""
-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/tests/unit/objects/test_groups.py b/tests/unit/objects/test_groups.py
deleted file mode 100644
index 37023d8..0000000
--- a/tests/unit/objects/test_groups.py
+++ /dev/null
@@ -1,155 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ce/api/groups.html
-"""
-
-import re
-
-import pytest
-import responses
-
-import gitlab
-from gitlab.v4.objects import GroupDescendantGroup, GroupSubgroup
-
-subgroup_descgroup_content = [
- {
- "id": 2,
- "name": "Bar Group",
- "path": "foo/bar",
- "description": "A subgroup of Foo Group",
- "visibility": "public",
- "share_with_group_lock": False,
- "require_two_factor_authentication": False,
- "two_factor_grace_period": 48,
- "project_creation_level": "developer",
- "auto_devops_enabled": None,
- "subgroup_creation_level": "owner",
- "emails_disabled": None,
- "mentions_disabled": None,
- "lfs_enabled": True,
- "default_branch_protection": 2,
- "avatar_url": "http://gitlab.example.com/uploads/group/avatar/1/bar.jpg",
- "web_url": "http://gitlab.example.com/groups/foo/bar",
- "request_access_enabled": False,
- "full_name": "Bar Group",
- "full_path": "foo/bar",
- "file_template_project_id": 1,
- "parent_id": 123,
- "created_at": "2020-01-15T12:36:29.590Z",
- },
-]
-
-
-@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_list_subgroups_descendant_groups():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=re.compile(
- r"http://localhost/api/v4/groups/1/(subgroups|descendant_groups)"
- ),
- json=subgroup_descgroup_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
-
-
-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
-
-
-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
-
-
-def test_create_group_export(group, resp_export):
- export = group.exports.create()
- assert export.message == "202 Accepted"
-
-
-def test_list_group_subgroups(group, resp_list_subgroups_descendant_groups):
- subgroups = group.subgroups.list()
- assert isinstance(subgroups[0], GroupSubgroup)
- assert subgroups[0].path == subgroup_descgroup_content[0]["path"]
-
-
-def test_list_group_descendant_groups(group, resp_list_subgroups_descendant_groups):
- descendant_groups = group.descendant_groups.list()
- assert isinstance(descendant_groups[0], GroupDescendantGroup)
- assert descendant_groups[0].path == subgroup_descgroup_content[0]["path"]
-
-
-@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"
-
-
-@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/tests/unit/objects/test_hooks.py b/tests/unit/objects/test_hooks.py
deleted file mode 100644
index 0f9dbe2..0000000
--- a/tests/unit/objects/test_hooks.py
+++ /dev/null
@@ -1,209 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ce/api/system_hooks.html
-GitLab API: https://docs.gitlab.com/ce/api/groups.html#hooks
-GitLab API: https://docs.gitlab.com/ee/api/projects.html#hooks
-"""
-
-import re
-
-import pytest
-import responses
-
-from gitlab.v4.objects import GroupHook, Hook, ProjectHook
-
-hooks_content = [
- {
- "id": 1,
- "url": "testurl",
- "push_events": True,
- "tag_push_events": True,
- },
- {
- "id": 2,
- "url": "testurl_second",
- "push_events": False,
- "tag_push_events": False,
- },
-]
-
-hook_content = hooks_content[0]
-
-
-@pytest.fixture
-def resp_hooks_list():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=re.compile(r"http://localhost/api/v4/((groups|projects)/1/|)hooks"),
- json=hooks_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_hook_get():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=re.compile(r"http://localhost/api/v4/((groups|projects)/1/|)hooks/1"),
- json=hook_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_hook_create():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.POST,
- url=re.compile(r"http://localhost/api/v4/((groups|projects)/1/|)hooks"),
- json=hook_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_hook_update():
- with responses.RequestsMock() as rsps:
- pattern = re.compile(r"http://localhost/api/v4/((groups|projects)/1/|)hooks/1")
- rsps.add(
- method=responses.GET,
- url=pattern,
- json=hook_content,
- content_type="application/json",
- status=200,
- )
- rsps.add(
- method=responses.PUT,
- url=pattern,
- json=hook_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_hook_delete():
- with responses.RequestsMock() as rsps:
- pattern = re.compile(r"http://localhost/api/v4/((groups|projects)/1/|)hooks/1")
- rsps.add(
- method=responses.GET,
- url=pattern,
- json=hook_content,
- content_type="application/json",
- status=200,
- )
- rsps.add(
- method=responses.DELETE,
- url=pattern,
- status=204,
- )
- yield rsps
-
-
-def test_list_system_hooks(gl, resp_hooks_list):
- hooks = gl.hooks.list()
- assert hooks[0].id == 1
- assert hooks[0].url == "testurl"
- assert hooks[1].id == 2
- assert hooks[1].url == "testurl_second"
-
-
-def test_get_system_hook(gl, resp_hook_get):
- data = gl.hooks.get(1)
- assert isinstance(data, Hook)
- assert data.url == "testurl"
- assert data.id == 1
-
-
-def test_create_system_hook(gl, resp_hook_create):
- hook = gl.hooks.create(hook_content)
- assert hook.url == "testurl"
- assert hook.push_events is True
- assert hook.tag_push_events is True
-
-
-# there is no update method for system hooks
-
-
-def test_delete_system_hook(gl, resp_hook_delete):
- hook = gl.hooks.get(1)
- hook.delete()
- gl.hooks.delete(1)
-
-
-def test_list_group_hooks(group, resp_hooks_list):
- hooks = group.hooks.list()
- assert hooks[0].id == 1
- assert hooks[0].url == "testurl"
- assert hooks[1].id == 2
- assert hooks[1].url == "testurl_second"
-
-
-def test_get_group_hook(group, resp_hook_get):
- data = group.hooks.get(1)
- assert isinstance(data, GroupHook)
- assert data.url == "testurl"
- assert data.id == 1
-
-
-def test_create_group_hook(group, resp_hook_create):
- hook = group.hooks.create(hook_content)
- assert hook.url == "testurl"
- assert hook.push_events is True
- assert hook.tag_push_events is True
-
-
-def test_update_group_hook(group, resp_hook_update):
- hook = group.hooks.get(1)
- assert hook.id == 1
- hook.url = "testurl_more"
- hook.save()
-
-
-def test_delete_group_hook(group, resp_hook_delete):
- hook = group.hooks.get(1)
- hook.delete()
- group.hooks.delete(1)
-
-
-def test_list_project_hooks(project, resp_hooks_list):
- hooks = project.hooks.list()
- assert hooks[0].id == 1
- assert hooks[0].url == "testurl"
- assert hooks[1].id == 2
- assert hooks[1].url == "testurl_second"
-
-
-def test_get_project_hook(project, resp_hook_get):
- data = project.hooks.get(1)
- assert isinstance(data, ProjectHook)
- assert data.url == "testurl"
- assert data.id == 1
-
-
-def test_create_project_hook(project, resp_hook_create):
- hook = project.hooks.create(hook_content)
- assert hook.url == "testurl"
- assert hook.push_events is True
- assert hook.tag_push_events is True
-
-
-def test_update_project_hook(project, resp_hook_update):
- hook = project.hooks.get(1)
- assert hook.id == 1
- hook.url = "testurl_more"
- hook.save()
-
-
-def test_delete_project_hook(project, resp_hook_delete):
- hook = project.hooks.get(1)
- hook.delete()
- project.hooks.delete(1)
diff --git a/tests/unit/objects/test_issues.py b/tests/unit/objects/test_issues.py
deleted file mode 100644
index a4e1454..0000000
--- a/tests/unit/objects/test_issues.py
+++ /dev/null
@@ -1,88 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ce/api/issues.html
-"""
-import re
-
-import pytest
-import responses
-
-from gitlab.v4.objects import (
- GroupIssuesStatistics,
- IssuesStatistics,
- ProjectIssuesStatistics,
-)
-
-
-@pytest.fixture
-def resp_list_issues():
- 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_get_issue():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/issues/1",
- json={"name": "name", "id": 1},
- 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=re.compile(
- r"http://localhost/api/v4/((groups|projects)/1/)?issues_statistics"
- ),
- json=content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-def test_list_issues(gl, resp_list_issues):
- data = gl.issues.list()
- assert data[1].id == 2
- assert data[1].name == "other_name"
-
-
-def test_get_issue(gl, resp_get_issue):
- issue = gl.issues.get(1)
- assert issue.id == 1
- assert issue.name == "name"
-
-
-def test_get_issues_statistics(gl, resp_issue_statistics):
- statistics = gl.issues_statistics.get()
- assert isinstance(statistics, IssuesStatistics)
- assert statistics.statistics["counts"]["all"] == 20
-
-
-def test_get_group_issues_statistics(group, resp_issue_statistics):
- statistics = group.issues_statistics.get()
- assert isinstance(statistics, GroupIssuesStatistics)
- assert statistics.statistics["counts"]["all"] == 20
-
-
-def test_get_project_issues_statistics(project, resp_issue_statistics):
- statistics = project.issues_statistics.get()
- assert isinstance(statistics, ProjectIssuesStatistics)
- assert statistics.statistics["counts"]["all"] == 20
diff --git a/tests/unit/objects/test_job_artifacts.py b/tests/unit/objects/test_job_artifacts.py
deleted file mode 100644
index 7c5f1df..0000000
--- a/tests/unit/objects/test_job_artifacts.py
+++ /dev/null
@@ -1,30 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ee/api/job_artifacts.html
-"""
-
-import pytest
-import responses
-
-ref_name = "master"
-job = "build"
-
-
-@pytest.fixture
-def resp_artifacts_by_ref_name(binary_content):
- url = f"http://localhost/api/v4/projects/1/jobs/artifacts/{ref_name}/download?job={job}"
-
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=url,
- body=binary_content,
- content_type="application/octet-stream",
- status=200,
- )
- yield rsps
-
-
-def test_download_artifacts_by_ref_name(gl, binary_content, resp_artifacts_by_ref_name):
- project = gl.projects.get(1, lazy=True)
- artifacts = project.artifacts(ref_name=ref_name, job=job)
- assert artifacts == binary_content
diff --git a/tests/unit/objects/test_jobs.py b/tests/unit/objects/test_jobs.py
deleted file mode 100644
index 104d59d..0000000
--- a/tests/unit/objects/test_jobs.py
+++ /dev/null
@@ -1,96 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ee/api/jobs.html
-"""
-import pytest
-import responses
-
-from gitlab.v4.objects import ProjectJob
-
-job_content = {
- "commit": {
- "author_email": "admin@example.com",
- "author_name": "Administrator",
- },
- "coverage": None,
- "allow_failure": False,
- "created_at": "2015-12-24T15:51:21.880Z",
- "started_at": "2015-12-24T17:54:30.733Z",
- "finished_at": "2015-12-24T17:54:31.198Z",
- "duration": 0.465,
- "queued_duration": 0.010,
- "artifacts_expire_at": "2016-01-23T17:54:31.198Z",
- "tag_list": ["docker runner", "macos-10.15"],
- "id": 1,
- "name": "rubocop",
- "pipeline": {
- "id": 1,
- "project_id": 1,
- },
- "ref": "master",
- "artifacts": [],
- "runner": None,
- "stage": "test",
- "status": "failed",
- "tag": False,
- "web_url": "https://example.com/foo/bar/-/jobs/1",
- "user": {"id": 1},
-}
-
-
-@pytest.fixture
-def resp_get_job():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/jobs/1",
- json=job_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_cancel_job():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.POST,
- url="http://localhost/api/v4/projects/1/jobs/1/cancel",
- json=job_content,
- content_type="application/json",
- status=201,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_retry_job():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.POST,
- url="http://localhost/api/v4/projects/1/jobs/1/retry",
- json=job_content,
- content_type="application/json",
- status=201,
- )
- yield rsps
-
-
-def test_get_project_job(project, resp_get_job):
- job = project.jobs.get(1)
- assert isinstance(job, ProjectJob)
- assert job.ref == "master"
-
-
-def test_cancel_project_job(project, resp_cancel_job):
- job = project.jobs.get(1, lazy=True)
-
- output = job.cancel()
- assert output["ref"] == "master"
-
-
-def test_retry_project_job(project, resp_retry_job):
- job = project.jobs.get(1, lazy=True)
-
- output = job.retry()
- assert output["ref"] == "master"
diff --git a/tests/unit/objects/test_keys.py b/tests/unit/objects/test_keys.py
deleted file mode 100644
index 187a309..0000000
--- a/tests/unit/objects/test_keys.py
+++ /dev/null
@@ -1,54 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ce/api/keys.html
-"""
-import pytest
-import responses
-
-from gitlab.v4.objects import Key
-
-key_content = {"id": 1, "title": "title", "key": "ssh-keytype AAAAC3Nza/key comment"}
-
-
-@pytest.fixture
-def resp_get_key_by_id():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/keys/1",
- json=key_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_get_key_by_fingerprint():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/keys?fingerprint=foo",
- json=key_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-def test_get_key_by_id(gl, resp_get_key_by_id):
- key = gl.keys.get(1)
- assert isinstance(key, Key)
- assert key.id == 1
- assert key.title == "title"
-
-
-def test_get_key_by_fingerprint(gl, resp_get_key_by_fingerprint):
- key = gl.keys.get(fingerprint="foo")
- assert isinstance(key, Key)
- assert key.id == 1
- assert key.title == "title"
-
-
-def test_get_key_missing_attrs(gl):
- with pytest.raises(AttributeError):
- gl.keys.get()
diff --git a/tests/unit/objects/test_members.py b/tests/unit/objects/test_members.py
deleted file mode 100644
index 6a39369..0000000
--- a/tests/unit/objects/test_members.py
+++ /dev/null
@@ -1,58 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ee/api/members.html
-"""
-import pytest
-import responses
-
-from gitlab.v4.objects import GroupBillableMember
-
-billable_members_content = [
- {
- "id": 1,
- "username": "raymond_smith",
- "name": "Raymond Smith",
- "state": "active",
- "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
- "web_url": "http://192.168.1.8:3000/root",
- "last_activity_on": "2021-01-27",
- "membership_type": "group_member",
- "removable": True,
- }
-]
-
-
-@pytest.fixture
-def resp_list_billable_group_members():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/groups/1/billable_members",
- json=billable_members_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_delete_billable_group_member(no_content):
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.DELETE,
- url="http://localhost/api/v4/groups/1/billable_members/1",
- json=no_content,
- content_type="application/json",
- status=204,
- )
- yield rsps
-
-
-def test_list_group_billable_members(group, resp_list_billable_group_members):
- billable_members = group.billable_members.list()
- assert isinstance(billable_members, list)
- assert isinstance(billable_members[0], GroupBillableMember)
- assert billable_members[0].removable is True
-
-
-def test_delete_group_billable_member(group, resp_delete_billable_group_member):
- group.billable_members.delete(1)
diff --git a/tests/unit/objects/test_merge_request_pipelines.py b/tests/unit/objects/test_merge_request_pipelines.py
deleted file mode 100644
index 04b04a8..0000000
--- a/tests/unit/objects/test_merge_request_pipelines.py
+++ /dev/null
@@ -1,53 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ee/api/merge_requests.html#list-mr-pipelines
-"""
-import pytest
-import responses
-
-from gitlab.v4.objects import ProjectMergeRequestPipeline
-
-pipeline_content = {
- "id": 1,
- "sha": "959e04d7c7a30600c894bd3c0cd0e1ce7f42c11d",
- "ref": "master",
- "status": "success",
-}
-
-
-@pytest.fixture()
-def resp_list_merge_request_pipelines():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/merge_requests/1/pipelines",
- json=[pipeline_content],
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture()
-def resp_create_merge_request_pipeline():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.POST,
- url="http://localhost/api/v4/projects/1/merge_requests/1/pipelines",
- json=pipeline_content,
- content_type="application/json",
- status=201,
- )
- yield rsps
-
-
-def test_list_merge_requests_pipelines(project, resp_list_merge_request_pipelines):
- pipelines = project.mergerequests.get(1, lazy=True).pipelines.list()
- assert len(pipelines) == 1
- assert isinstance(pipelines[0], ProjectMergeRequestPipeline)
- assert pipelines[0].sha == pipeline_content["sha"]
-
-
-def test_create_merge_requests_pipelines(project, resp_create_merge_request_pipeline):
- pipeline = project.mergerequests.get(1, lazy=True).pipelines.create()
- assert isinstance(pipeline, ProjectMergeRequestPipeline)
- assert pipeline.sha == pipeline_content["sha"]
diff --git a/tests/unit/objects/test_merge_requests.py b/tests/unit/objects/test_merge_requests.py
deleted file mode 100644
index ee11f8a..0000000
--- a/tests/unit/objects/test_merge_requests.py
+++ /dev/null
@@ -1,56 +0,0 @@
-"""
-GitLab API:
-https://docs.gitlab.com/ce/api/merge_requests.html
-https://docs.gitlab.com/ee/api/deployments.html#list-of-merge-requests-associated-with-a-deployment
-"""
-import re
-
-import pytest
-import responses
-
-from gitlab.v4.objects import ProjectDeploymentMergeRequest, ProjectMergeRequest
-
-mr_content = {
- "id": 1,
- "iid": 1,
- "project_id": 3,
- "title": "test1",
- "description": "fixed login page css paddings",
- "state": "merged",
- "merged_by": {
- "id": 87854,
- "name": "Douwe Maan",
- "username": "DouweM",
- "state": "active",
- "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
- "web_url": "https://gitlab.com/DouweM",
- },
-}
-
-
-@pytest.fixture
-def resp_list_merge_requests():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=re.compile(
- r"http://localhost/api/v4/projects/1/(deployments/1/)?merge_requests"
- ),
- json=[mr_content],
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-def test_list_project_merge_requests(project, resp_list_merge_requests):
- mrs = project.mergerequests.list()
- assert isinstance(mrs[0], ProjectMergeRequest)
- assert mrs[0].iid == mr_content["iid"]
-
-
-def test_list_deployment_merge_requests(project, resp_list_merge_requests):
- deployment = project.deployments.get(1, lazy=True)
- mrs = deployment.mergerequests.list()
- assert isinstance(mrs[0], ProjectDeploymentMergeRequest)
- assert mrs[0].iid == mr_content["iid"]
diff --git a/tests/unit/objects/test_mro.py b/tests/unit/objects/test_mro.py
deleted file mode 100644
index 8f67b77..0000000
--- a/tests/unit/objects/test_mro.py
+++ /dev/null
@@ -1,122 +0,0 @@
-"""
-Ensure objects defined in gitlab.v4.objects have REST* as last item in class
-definition
-
-Original notes by John L. Villalovos
-
-An example of an incorrect definition:
- class ProjectPipeline(RESTObject, RefreshMixin, ObjectDeleteMixin):
- ^^^^^^^^^^ This should be at the end.
-
-Correct way would be:
- class ProjectPipeline(RefreshMixin, ObjectDeleteMixin, RESTObject):
- Correctly at the end ^^^^^^^^^^
-
-
-Why this is an issue:
-
- When we do type-checking for gitlab/mixins.py we make RESTObject or
- RESTManager the base class for the mixins
-
- Here is how our classes look when type-checking:
-
- class RESTObject(object):
- def __init__(self, manager: "RESTManager", attrs: Dict[str, Any]) -> None:
- ...
-
- class Mixin(RESTObject):
- ...
-
- # Wrong ordering here
- class Wrongv4Object(RESTObject, RefreshMixin):
- ...
-
- If we actually ran this in Python we would get the following error:
- class Wrongv4Object(RESTObject, Mixin):
- TypeError: Cannot create a consistent method resolution
- order (MRO) for bases RESTObject, Mixin
-
- When we are type-checking it fails to understand the class Wrongv4Object
- and thus we can't type check it correctly.
-
-Almost all classes in gitlab/v4/objects/*py were already correct before this
-check was added.
-"""
-import inspect
-
-import pytest
-
-import gitlab.v4.objects
-
-
-def test_show_issue():
- """Test case to demonstrate the TypeError that occurs"""
-
- class RESTObject(object):
- def __init__(self, manager: str, attrs: int) -> None:
- ...
-
- class Mixin(RESTObject):
- ...
-
- with pytest.raises(TypeError) as exc_info:
- # Wrong ordering here
- class Wrongv4Object(RESTObject, Mixin):
- ...
-
- # The error message in the exception should be:
- # TypeError: Cannot create a consistent method resolution
- # order (MRO) for bases RESTObject, Mixin
-
- # Make sure the exception string contains "MRO"
- assert "MRO" in exc_info.exconly()
-
- # Correctly ordered class, no exception
- class Correctv4Object(Mixin, RESTObject):
- ...
-
-
-def test_mros():
- """Ensure objects defined in gitlab.v4.objects have REST* as last item in
- class definition.
-
- We do this as we need to ensure the MRO (Method Resolution Order) is
- correct.
- """
-
- failed_messages = []
- for module_name, module_value in inspect.getmembers(gitlab.v4.objects):
- if not inspect.ismodule(module_value):
- # We only care about the modules
- continue
- # Iterate through all the classes in our module
- for class_name, class_value in inspect.getmembers(module_value):
- if not inspect.isclass(class_value):
- continue
-
- # Ignore imported classes from gitlab.base
- if class_value.__module__ == "gitlab.base":
- continue
-
- mro = class_value.mro()
-
- # We only check classes which have a 'gitlab.base' class in their MRO
- has_base = False
- for count, obj in enumerate(mro, start=1):
- if obj.__module__ == "gitlab.base":
- has_base = True
- base_classname = obj.__name__
- if has_base:
- filename = inspect.getfile(class_value)
- # NOTE(jlvillal): The very last item 'mro[-1]' is always going
- # to be 'object'. That is why we are checking 'mro[-2]'.
- if mro[-2].__module__ != "gitlab.base":
- failed_messages.append(
- (
- f"class definition for {class_name!r} in file {filename!r} "
- f"must have {base_classname!r} as the last class in the "
- f"class definition"
- )
- )
- failed_msg = "\n".join(failed_messages)
- assert not failed_messages, failed_msg
diff --git a/tests/unit/objects/test_packages.py b/tests/unit/objects/test_packages.py
deleted file mode 100644
index 687054f..0000000
--- a/tests/unit/objects/test_packages.py
+++ /dev/null
@@ -1,252 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ce/api/packages.html
-"""
-import re
-from urllib.parse import quote_plus
-
-import pytest
-import responses
-
-from gitlab.v4.objects import (
- GenericPackage,
- GroupPackage,
- ProjectPackage,
- ProjectPackageFile,
-)
-
-package_content = {
- "id": 1,
- "name": "com/mycompany/my-app",
- "version": "1.0-SNAPSHOT",
- "package_type": "maven",
- "_links": {
- "web_path": "/namespace1/project1/-/packages/1",
- "delete_api_path": "/namespace1/project1/-/packages/1",
- },
- "created_at": "2019-11-27T03:37:38.711Z",
- "pipeline": {
- "id": 123,
- "status": "pending",
- "ref": "new-pipeline",
- "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
- "web_url": "https://example.com/foo/bar/pipelines/47",
- "created_at": "2016-08-11T11:28:34.085Z",
- "updated_at": "2016-08-11T11:32:35.169Z",
- "user": {
- "name": "Administrator",
- "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- },
- },
- "versions": [
- {
- "id": 2,
- "version": "2.0-SNAPSHOT",
- "created_at": "2020-04-28T04:42:11.573Z",
- "pipeline": {
- "id": 234,
- "status": "pending",
- "ref": "new-pipeline",
- "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
- "web_url": "https://example.com/foo/bar/pipelines/58",
- "created_at": "2016-08-11T11:28:34.085Z",
- "updated_at": "2016-08-11T11:32:35.169Z",
- "user": {
- "name": "Administrator",
- "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- },
- },
- }
- ],
-}
-
-package_file_content = [
- {
- "id": 25,
- "package_id": 1,
- "created_at": "2018-11-07T15:25:52.199Z",
- "file_name": "my-app-1.5-20181107.152550-1.jar",
- "size": 2421,
- "file_md5": "58e6a45a629910c6ff99145a688971ac",
- "file_sha1": "ebd193463d3915d7e22219f52740056dfd26cbfe",
- "pipelines": [
- {
- "id": 123,
- "status": "pending",
- "ref": "new-pipeline",
- "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
- "web_url": "https://example.com/foo/bar/pipelines/47",
- "created_at": "2016-08-11T11:28:34.085Z",
- "updated_at": "2016-08-11T11:32:35.169Z",
- "user": {
- "name": "Administrator",
- "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- },
- }
- ],
- },
- {
- "id": 26,
- "package_id": 1,
- "created_at": "2018-11-07T15:25:56.776Z",
- "file_name": "my-app-1.5-20181107.152550-1.pom",
- "size": 1122,
- "file_md5": "d90f11d851e17c5513586b4a7e98f1b2",
- "file_sha1": "9608d068fe88aff85781811a42f32d97feb440b5",
- },
- {
- "id": 27,
- "package_id": 1,
- "created_at": "2018-11-07T15:26:00.556Z",
- "file_name": "maven-metadata.xml",
- "size": 767,
- "file_md5": "6dfd0cce1203145a927fef5e3a1c650c",
- "file_sha1": "d25932de56052d320a8ac156f745ece73f6a8cd2",
- },
-]
-
-package_name = "hello-world"
-package_version = "v1.0.0"
-file_name = "hello.tar.gz"
-file_content = "package content"
-package_url = "http://localhost/api/v4/projects/1/packages/generic/{}/{}/{}".format(
- # https://datatracker.ietf.org/doc/html/rfc3986.html#section-2.3 :(
- quote_plus(package_name).replace(".", "%2E"),
- quote_plus(package_version).replace(".", "%2E"),
- quote_plus(file_name).replace(".", "%2E"),
-)
-
-
-@pytest.fixture
-def resp_list_packages():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=re.compile(r"http://localhost/api/v4/(groups|projects)/1/packages"),
- json=[package_content],
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_get_package():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/packages/1",
- json=package_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_delete_package(no_content):
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.DELETE,
- url="http://localhost/api/v4/projects/1/packages/1",
- json=no_content,
- content_type="application/json",
- status=204,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_list_package_files():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=re.compile(
- r"http://localhost/api/v4/projects/1/packages/1/package_files"
- ),
- json=package_file_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_upload_generic_package(created_content):
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.PUT,
- url=package_url,
- json=created_content,
- content_type="application/json",
- status=201,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_download_generic_package(created_content):
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=package_url,
- body=file_content,
- content_type="application/octet-stream",
- status=200,
- )
- yield rsps
-
-
-def test_list_project_packages(project, resp_list_packages):
- packages = project.packages.list()
- assert isinstance(packages, list)
- assert isinstance(packages[0], ProjectPackage)
- assert packages[0].version == "1.0-SNAPSHOT"
-
-
-def test_list_group_packages(group, resp_list_packages):
- packages = group.packages.list()
- assert isinstance(packages, list)
- assert isinstance(packages[0], GroupPackage)
- assert packages[0].version == "1.0-SNAPSHOT"
-
-
-def test_get_project_package(project, resp_get_package):
- package = project.packages.get(1)
- assert isinstance(package, ProjectPackage)
- assert package.version == "1.0-SNAPSHOT"
-
-
-def test_delete_project_package(project, resp_delete_package):
- package = project.packages.get(1, lazy=True)
- package.delete()
-
-
-def test_list_project_package_files(project, resp_list_package_files):
- package = project.packages.get(1, lazy=True)
- package_files = package.package_files.list()
- assert isinstance(package_files, list)
- assert isinstance(package_files[0], ProjectPackageFile)
- assert package_files[0].id == 25
-
-
-def test_upload_generic_package(tmp_path, project, resp_upload_generic_package):
- path = tmp_path / file_name
- path.write_text(file_content)
- package = project.generic_packages.upload(
- package_name=package_name,
- package_version=package_version,
- file_name=file_name,
- path=path,
- )
-
- assert isinstance(package, GenericPackage)
-
-
-def test_download_generic_package(project, resp_download_generic_package):
- package = project.generic_packages.download(
- package_name=package_name,
- package_version=package_version,
- file_name=file_name,
- )
-
- assert isinstance(package, bytes)
diff --git a/tests/unit/objects/test_personal_access_tokens.py b/tests/unit/objects/test_personal_access_tokens.py
deleted file mode 100644
index 065b5c8..0000000
--- a/tests/unit/objects/test_personal_access_tokens.py
+++ /dev/null
@@ -1,94 +0,0 @@
-"""
-GitLab API:
-https://docs.gitlab.com/ee/api/personal_access_tokens.html
-https://docs.gitlab.com/ee/api/users.html#create-a-personal-access-token
-"""
-
-import pytest
-import responses
-
-user_id = 1
-token_id = 1
-token_name = "Test Token"
-
-token_url = "http://localhost/api/v4/personal_access_tokens"
-single_token_url = f"{token_url}/{token_id}"
-user_token_url = f"http://localhost/api/v4/users/{user_id}/personal_access_tokens"
-
-content = {
- "id": token_id,
- "name": token_name,
- "revoked": False,
- "created_at": "2020-07-23T14:31:47.729Z",
- "scopes": ["api"],
- "active": True,
- "user_id": user_id,
- "expires_at": None,
-}
-
-
-@pytest.fixture
-def resp_create_user_personal_access_token():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.POST,
- url=user_token_url,
- json=content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_personal_access_token(no_content):
- with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps:
- rsps.add(
- method=responses.GET,
- url=token_url,
- json=[content],
- content_type="application/json",
- status=200,
- )
- rsps.add(
- method=responses.DELETE,
- url=single_token_url,
- json=no_content,
- content_type="application/json",
- status=204,
- )
- yield rsps
-
-
-def test_create_personal_access_token(gl, resp_create_user_personal_access_token):
- user = gl.users.get(1, lazy=True)
- access_token = user.personal_access_tokens.create(
- {"name": token_name, "scopes": "api"}
- )
- assert access_token.revoked is False
- assert access_token.name == token_name
-
-
-def test_list_personal_access_tokens(gl, resp_personal_access_token):
- access_tokens = gl.personal_access_tokens.list()
- assert len(access_tokens) == 1
- assert access_tokens[0].revoked is False
- assert access_tokens[0].name == token_name
-
-
-def test_list_personal_access_tokens_filter(gl, resp_personal_access_token):
- access_tokens = gl.personal_access_tokens.list(user_id=user_id)
- assert len(access_tokens) == 1
- assert access_tokens[0].revoked is False
- assert access_tokens[0].user_id == user_id
-
-
-def test_revoke_personal_access_token(gl, resp_personal_access_token):
- access_token = gl.personal_access_tokens.list(user_id=user_id)[0]
- access_token.delete()
- assert resp_personal_access_token.assert_call_count(single_token_url, 1)
-
-
-def test_revoke_personal_access_token_by_id(gl, resp_personal_access_token):
- gl.personal_access_tokens.delete(token_id)
- assert resp_personal_access_token.assert_call_count(single_token_url, 1)
diff --git a/tests/unit/objects/test_pipeline_schedules.py b/tests/unit/objects/test_pipeline_schedules.py
deleted file mode 100644
index c5dcc76..0000000
--- a/tests/unit/objects/test_pipeline_schedules.py
+++ /dev/null
@@ -1,62 +0,0 @@
-"""
-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/tests/unit/objects/test_pipelines.py b/tests/unit/objects/test_pipelines.py
deleted file mode 100644
index c0b87f2..0000000
--- a/tests/unit/objects/test_pipelines.py
+++ /dev/null
@@ -1,146 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ee/api/pipelines.html
-"""
-import pytest
-import responses
-
-from gitlab.v4.objects import ProjectPipeline, ProjectPipelineTestReport
-
-pipeline_content = {
- "id": 46,
- "project_id": 1,
- "status": "pending",
- "ref": "master",
- "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
- "before_sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
- "tag": False,
- "yaml_errors": None,
- "user": {
- "name": "Administrator",
- "username": "root",
- "id": 1,
- "state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://localhost:3000/root",
- },
- "created_at": "2016-08-11T11:28:34.085Z",
- "updated_at": "2016-08-11T11:32:35.169Z",
- "started_at": None,
- "finished_at": "2016-08-11T11:32:35.145Z",
- "committed_at": None,
- "duration": None,
- "queued_duration": 0.010,
- "coverage": None,
- "web_url": "https://example.com/foo/bar/pipelines/46",
-}
-
-
-test_report_content = {
- "total_time": 5,
- "total_count": 1,
- "success_count": 1,
- "failed_count": 0,
- "skipped_count": 0,
- "error_count": 0,
- "test_suites": [
- {
- "name": "Secure",
- "total_time": 5,
- "total_count": 1,
- "success_count": 1,
- "failed_count": 0,
- "skipped_count": 0,
- "error_count": 0,
- "test_cases": [
- {
- "status": "success",
- "name": "Security Reports can create an auto-remediation MR",
- "classname": "vulnerability_management_spec",
- "execution_time": 5,
- "system_output": None,
- "stack_trace": None,
- }
- ],
- }
- ],
-}
-
-
-@pytest.fixture
-def resp_get_pipeline():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/pipelines/1",
- json=pipeline_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_cancel_pipeline():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.POST,
- url="http://localhost/api/v4/projects/1/pipelines/1/cancel",
- json=pipeline_content,
- content_type="application/json",
- status=201,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_retry_pipeline():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.POST,
- url="http://localhost/api/v4/projects/1/pipelines/1/retry",
- json=pipeline_content,
- content_type="application/json",
- status=201,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_get_pipeline_test_report():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/pipelines/1/test_report",
- json=test_report_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-def test_get_project_pipeline(project, resp_get_pipeline):
- pipeline = project.pipelines.get(1)
- assert isinstance(pipeline, ProjectPipeline)
- assert pipeline.ref == "master"
-
-
-def test_cancel_project_pipeline(project, resp_cancel_pipeline):
- pipeline = project.pipelines.get(1, lazy=True)
-
- output = pipeline.cancel()
- assert output["ref"] == "master"
-
-
-def test_retry_project_pipeline(project, resp_retry_pipeline):
- pipeline = project.pipelines.get(1, lazy=True)
-
- output = pipeline.retry()
- assert output["ref"] == "master"
-
-
-def test_get_project_pipeline_test_report(project, resp_get_pipeline_test_report):
- pipeline = project.pipelines.get(1, lazy=True)
- test_report = pipeline.test_report.get()
- assert isinstance(test_report, ProjectPipelineTestReport)
- assert test_report.total_time == 5
- assert test_report.test_suites[0]["name"] == "Secure"
diff --git a/tests/unit/objects/test_project_access_tokens.py b/tests/unit/objects/test_project_access_tokens.py
deleted file mode 100644
index 4d4788d..0000000
--- a/tests/unit/objects/test_project_access_tokens.py
+++ /dev/null
@@ -1,113 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ee/api/resource_access_tokens.html
-"""
-
-import pytest
-import responses
-
-
-@pytest.fixture
-def resp_list_project_access_token():
- content = [
- {
- "user_id": 141,
- "scopes": ["api"],
- "name": "token",
- "expires_at": "2021-01-31",
- "id": 42,
- "active": True,
- "created_at": "2021-01-20T22:11:48.151Z",
- "revoked": False,
- }
- ]
-
- with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/access_tokens",
- json=content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_create_project_access_token():
- content = {
- "user_id": 141,
- "scopes": ["api"],
- "name": "token",
- "expires_at": "2021-01-31",
- "id": 42,
- "active": True,
- "created_at": "2021-01-20T22:11:48.151Z",
- "revoked": False,
- }
-
- with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps:
- rsps.add(
- method=responses.POST,
- url="http://localhost/api/v4/projects/1/access_tokens",
- json=content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_revoke_project_access_token():
- content = [
- {
- "user_id": 141,
- "scopes": ["api"],
- "name": "token",
- "expires_at": "2021-01-31",
- "id": 42,
- "active": True,
- "created_at": "2021-01-20T22:11:48.151Z",
- "revoked": False,
- }
- ]
-
- with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps:
- rsps.add(
- method=responses.DELETE,
- url="http://localhost/api/v4/projects/1/access_tokens/42",
- json=content,
- content_type="application/json",
- status=204,
- )
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/access_tokens",
- json=content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-def test_list_project_access_tokens(gl, resp_list_project_access_token):
- access_tokens = gl.projects.get(1, lazy=True).access_tokens.list()
- assert len(access_tokens) == 1
- assert access_tokens[0].revoked is False
- assert access_tokens[0].name == "token"
-
-
-def test_create_project_access_token(gl, resp_create_project_access_token):
- access_tokens = gl.projects.get(1, lazy=True).access_tokens.create(
- {"name": "test", "scopes": ["api"]}
- )
- assert access_tokens.revoked is False
- assert access_tokens.user_id == 141
- assert access_tokens.expires_at == "2021-01-31"
-
-
-def test_revoke_project_access_token(
- gl, resp_list_project_access_token, resp_revoke_project_access_token
-):
- gl.projects.get(1, lazy=True).access_tokens.delete(42)
- access_token = gl.projects.get(1, lazy=True).access_tokens.list()[0]
- access_token.delete()
diff --git a/tests/unit/objects/test_project_import_export.py b/tests/unit/objects/test_project_import_export.py
deleted file mode 100644
index 78e51b1..0000000
--- a/tests/unit/objects/test_project_import_export.py
+++ /dev/null
@@ -1,112 +0,0 @@
-"""
-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/tests/unit/objects/test_project_merge_request_approvals.py b/tests/unit/objects/test_project_merge_request_approvals.py
deleted file mode 100644
index 16d58bd..0000000
--- a/tests/unit/objects/test_project_merge_request_approvals.py
+++ /dev/null
@@ -1,317 +0,0 @@
-"""
-Gitlab API: https://docs.gitlab.com/ee/api/merge_request_approvals.html
-"""
-
-import copy
-
-import pytest
-import responses
-
-import gitlab
-
-approval_rule_id = 1
-approval_rule_name = "security"
-approvals_required = 3
-user_ids = [5, 50]
-group_ids = [5]
-
-new_approval_rule_name = "new approval rule"
-new_approval_rule_user_ids = user_ids
-new_approval_rule_approvals_required = 2
-
-updated_approval_rule_user_ids = [5]
-updated_approval_rule_approvals_required = 1
-
-
-@pytest.fixture
-def resp_snippet():
- merge_request_content = [
- {
- "id": 1,
- "iid": 1,
- "project_id": 1,
- "title": "test1",
- "description": "fixed login page css paddings",
- "state": "merged",
- "merged_by": {
- "id": 87854,
- "name": "Douwe Maan",
- "username": "DouweM",
- "state": "active",
- "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
- "web_url": "https://gitlab.com/DouweM",
- },
- "merged_at": "2018-09-07T11:16:17.520Z",
- "closed_by": None,
- "closed_at": None,
- "created_at": "2017-04-29T08:46:00Z",
- "updated_at": "2017-04-29T08:46:00Z",
- "target_branch": "master",
- "source_branch": "test1",
- "upvotes": 0,
- "downvotes": 0,
- "author": {
- "id": 1,
- "name": "Administrator",
- "username": "admin",
- "state": "active",
- "avatar_url": None,
- "web_url": "https://gitlab.example.com/admin",
- },
- "assignee": {
- "id": 1,
- "name": "Administrator",
- "username": "admin",
- "state": "active",
- "avatar_url": None,
- "web_url": "https://gitlab.example.com/admin",
- },
- "assignees": [
- {
- "name": "Miss Monserrate Beier",
- "username": "axel.block",
- "id": 12,
- "state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/axel.block",
- }
- ],
- "source_project_id": 2,
- "target_project_id": 3,
- "labels": ["Community contribution", "Manage"],
- "work_in_progress": None,
- "milestone": {
- "id": 5,
- "iid": 1,
- "project_id": 3,
- "title": "v2.0",
- "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.",
- "state": "closed",
- "created_at": "2015-02-02T19:49:26.013Z",
- "updated_at": "2015-02-02T19:49:26.013Z",
- "due_date": "2018-09-22",
- "start_date": "2018-08-08",
- "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1",
- },
- "merge_when_pipeline_succeeds": None,
- "merge_status": "can_be_merged",
- "sha": "8888888888888888888888888888888888888888",
- "merge_commit_sha": None,
- "squash_commit_sha": None,
- "user_notes_count": 1,
- "discussion_locked": None,
- "should_remove_source_branch": True,
- "force_remove_source_branch": False,
- "allow_collaboration": False,
- "allow_maintainer_to_push": False,
- "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
- "references": {
- "short": "!1",
- "relative": "my-group/my-project!1",
- "full": "my-group/my-project!1",
- },
- "time_stats": {
- "time_estimate": 0,
- "total_time_spent": 0,
- "human_time_estimate": None,
- "human_total_time_spent": None,
- },
- "squash": False,
- "task_completion_status": {"count": 0, "completed_count": 0},
- }
- ]
- mr_ars_content = [
- {
- "id": approval_rule_id,
- "name": approval_rule_name,
- "rule_type": "regular",
- "eligible_approvers": [
- {
- "id": user_ids[0],
- "name": "John Doe",
- "username": "jdoe",
- "state": "active",
- "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon",
- "web_url": "http://localhost/jdoe",
- },
- {
- "id": user_ids[1],
- "name": "Group Member 1",
- "username": "group_member_1",
- "state": "active",
- "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon",
- "web_url": "http://localhost/group_member_1",
- },
- ],
- "approvals_required": approvals_required,
- "source_rule": None,
- "users": [
- {
- "id": 5,
- "name": "John Doe",
- "username": "jdoe",
- "state": "active",
- "avatar_url": "https://www.gravatar.com/avatar/0?s=80&d=identicon",
- "web_url": "http://localhost/jdoe",
- }
- ],
- "groups": [
- {
- "id": 5,
- "name": "group1",
- "path": "group1",
- "description": "",
- "visibility": "public",
- "lfs_enabled": False,
- "avatar_url": None,
- "web_url": "http://localhost/groups/group1",
- "request_access_enabled": False,
- "full_name": "group1",
- "full_path": "group1",
- "parent_id": None,
- "ldap_cn": None,
- "ldap_access": None,
- }
- ],
- "contains_hidden_groups": False,
- "overridden": False,
- }
- ]
-
- with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/merge_requests",
- json=merge_request_content,
- content_type="application/json",
- status=200,
- )
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/merge_requests/1",
- json=merge_request_content[0],
- content_type="application/json",
- status=200,
- )
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/merge_requests/1/approval_rules",
- json=mr_ars_content,
- content_type="application/json",
- status=200,
- )
-
- new_mr_ars_content = dict(mr_ars_content[0])
- new_mr_ars_content["name"] = new_approval_rule_name
- new_mr_ars_content["approvals_required"] = new_approval_rule_approvals_required
-
- rsps.add(
- method=responses.POST,
- url="http://localhost/api/v4/projects/1/merge_requests/1/approval_rules",
- json=new_mr_ars_content,
- content_type="application/json",
- status=200,
- )
-
- updated_mr_ars_content = copy.deepcopy(mr_ars_content[0])
- updated_mr_ars_content["eligible_approvers"] = [
- mr_ars_content[0]["eligible_approvers"][0]
- ]
-
- updated_mr_ars_content[
- "approvals_required"
- ] = updated_approval_rule_approvals_required
-
- rsps.add(
- method=responses.PUT,
- url="http://localhost/api/v4/projects/1/merge_requests/1/approval_rules/1",
- json=updated_mr_ars_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-def test_project_approval_manager_update_uses_post(project, resp_snippet):
- """Ensure the
- gitlab.v4.objects.merge_request_approvals.ProjectApprovalManager object has
- _update_uses_post set to True"""
- approvals = project.approvals
- assert isinstance(
- approvals, gitlab.v4.objects.merge_request_approvals.ProjectApprovalManager
- )
- assert approvals._update_uses_post is True
-
-
-def test_list_merge_request_approval_rules(project, resp_snippet):
- approval_rules = project.mergerequests.get(1).approval_rules.list()
- assert len(approval_rules) == 1
- assert approval_rules[0].name == approval_rule_name
- assert approval_rules[0].id == approval_rule_id
-
-
-def test_update_merge_request_approvals_set_approvers(project, resp_snippet):
- approvals = project.mergerequests.get(1).approvals
- assert isinstance(
- approvals,
- gitlab.v4.objects.merge_request_approvals.ProjectMergeRequestApprovalManager,
- )
- assert approvals._update_uses_post is True
- response = approvals.set_approvers(
- updated_approval_rule_approvals_required,
- approver_ids=updated_approval_rule_user_ids,
- approver_group_ids=group_ids,
- approval_rule_name=approval_rule_name,
- )
-
- assert response.approvals_required == updated_approval_rule_approvals_required
- assert len(response.eligible_approvers) == len(updated_approval_rule_user_ids)
- assert response.eligible_approvers[0]["id"] == updated_approval_rule_user_ids[0]
- assert response.name == approval_rule_name
-
-
-def test_create_merge_request_approvals_set_approvers(project, resp_snippet):
- approvals = project.mergerequests.get(1).approvals
- assert isinstance(
- approvals,
- gitlab.v4.objects.merge_request_approvals.ProjectMergeRequestApprovalManager,
- )
- assert approvals._update_uses_post is True
- response = approvals.set_approvers(
- new_approval_rule_approvals_required,
- approver_ids=new_approval_rule_user_ids,
- approver_group_ids=group_ids,
- approval_rule_name=new_approval_rule_name,
- )
- assert response.approvals_required == new_approval_rule_approvals_required
- assert len(response.eligible_approvers) == len(new_approval_rule_user_ids)
- assert response.eligible_approvers[0]["id"] == new_approval_rule_user_ids[0]
- assert response.name == new_approval_rule_name
-
-
-def test_create_merge_request_approval_rule(project, resp_snippet):
- approval_rules = project.mergerequests.get(1).approval_rules
- data = {
- "name": new_approval_rule_name,
- "approvals_required": new_approval_rule_approvals_required,
- "rule_type": "regular",
- "user_ids": new_approval_rule_user_ids,
- "group_ids": group_ids,
- }
- response = approval_rules.create(data)
- assert response.approvals_required == new_approval_rule_approvals_required
- assert len(response.eligible_approvers) == len(new_approval_rule_user_ids)
- assert response.eligible_approvers[0]["id"] == new_approval_rule_user_ids[0]
- assert response.name == new_approval_rule_name
-
-
-def test_update_merge_request_approval_rule(project, resp_snippet):
- approval_rules = project.mergerequests.get(1).approval_rules
- ar_1 = approval_rules.list()[0]
- ar_1.user_ids = updated_approval_rule_user_ids
- ar_1.approvals_required = updated_approval_rule_approvals_required
- ar_1.save()
-
- assert ar_1.approvals_required == updated_approval_rule_approvals_required
- assert len(ar_1.eligible_approvers) == len(updated_approval_rule_user_ids)
- assert ar_1.eligible_approvers[0]["id"] == updated_approval_rule_user_ids[0]
diff --git a/tests/unit/objects/test_project_statistics.py b/tests/unit/objects/test_project_statistics.py
deleted file mode 100644
index 50d9a6d..0000000
--- a/tests/unit/objects/test_project_statistics.py
+++ /dev/null
@@ -1,28 +0,0 @@
-"""
-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/tests/unit/objects/test_projects.py b/tests/unit/objects/test_projects.py
deleted file mode 100644
index 039d5ec..0000000
--- a/tests/unit/objects/test_projects.py
+++ /dev/null
@@ -1,237 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ce/api/projects.html
-"""
-
-import pytest
-import responses
-
-from gitlab.v4.objects import Project
-
-project_content = {"name": "name", "id": 1}
-import_content = {
- "id": 1,
- "name": "project",
- "import_status": "scheduled",
-}
-
-
-@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,
- )
- 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,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_import_bitbucket_server():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.POST,
- url="http://localhost/api/v4/import/bitbucket_server",
- json=import_content,
- content_type="application/json",
- status=201,
- )
- 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"
-
-
-def test_import_bitbucket_server(gl, resp_import_bitbucket_server):
- res = gl.projects.import_bitbucket_server(
- bitbucket_server_project="project",
- bitbucket_server_repo="repo",
- bitbucket_server_url="url",
- bitbucket_server_username="username",
- personal_access_token="token",
- new_name="new_name",
- target_namespace="namespace",
- )
- assert res["id"] == 1
- assert res["name"] == "project"
- assert res["import_status"] == "scheduled"
-
-
-@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_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
-
-
-@pytest.mark.skip(reason="missing test")
-def test_import_github(gl):
- pass
diff --git a/tests/unit/objects/test_releases.py b/tests/unit/objects/test_releases.py
deleted file mode 100644
index 58ab5d0..0000000
--- a/tests/unit/objects/test_releases.py
+++ /dev/null
@@ -1,170 +0,0 @@
-"""
-GitLab API:
-https://docs.gitlab.com/ee/api/releases/index.html
-https://docs.gitlab.com/ee/api/releases/links.html
-"""
-import re
-
-import pytest
-import responses
-
-from gitlab.v4.objects import ProjectReleaseLink
-
-tag_name = "v1.0.0"
-encoded_tag_name = "v1%2E0%2E0"
-release_name = "demo-release"
-release_description = "my-rel-desc"
-released_at = "2019-03-15T08:00:00Z"
-link_name = "hello-world"
-link_url = "https://gitlab.example.com/group/hello/-/jobs/688/artifacts/raw/bin/hello-darwin-amd64"
-direct_url = f"https://gitlab.example.com/group/hello/-/releases/{encoded_tag_name}/downloads/hello-world"
-new_link_type = "package"
-link_content = {
- "id": 2,
- "name": link_name,
- "url": link_url,
- "direct_asset_url": direct_url,
- "external": False,
- "link_type": "other",
-}
-
-release_content = {
- "id": 3,
- "tag_name": tag_name,
- "name": release_name,
- "description": release_description,
- "milestones": [],
- "released_at": released_at,
-}
-
-release_url = re.compile(
- rf"http://localhost/api/v4/projects/1/releases/{encoded_tag_name}"
-)
-links_url = re.compile(
- rf"http://localhost/api/v4/projects/1/releases/{encoded_tag_name}/assets/links"
-)
-link_id_url = re.compile(
- rf"http://localhost/api/v4/projects/1/releases/{encoded_tag_name}/assets/links/1"
-)
-
-
-@pytest.fixture
-def resp_list_links():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=links_url,
- json=[link_content],
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_get_link():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=link_id_url,
- json=link_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_create_link():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.POST,
- url=links_url,
- json=link_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_update_link():
- updated_content = dict(link_content)
- updated_content["link_type"] = new_link_type
-
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.PUT,
- url=link_id_url,
- json=updated_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_delete_link(no_content):
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.DELETE,
- url=link_id_url,
- json=link_content,
- content_type="application/json",
- status=204,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_update_release():
- updated_content = dict(release_content)
-
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.PUT,
- url=release_url,
- json=updated_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-def test_list_release_links(release, resp_list_links):
- links = release.links.list()
- assert isinstance(links, list)
- assert isinstance(links[0], ProjectReleaseLink)
- assert links[0].url == link_url
-
-
-def test_get_release_link(release, resp_get_link):
- link = release.links.get(1)
- assert isinstance(link, ProjectReleaseLink)
- assert link.url == link_url
-
-
-def test_create_release_link(release, resp_create_link):
- link = release.links.create({"url": link_url, "name": link_name})
- assert isinstance(link, ProjectReleaseLink)
- assert link.url == link_url
-
-
-def test_update_release_link(release, resp_update_link):
- link = release.links.get(1, lazy=True)
- link.link_type = new_link_type
- link.save()
- assert link.link_type == new_link_type
-
-
-def test_delete_release_link(release, resp_delete_link):
- link = release.links.get(1, lazy=True)
- link.delete()
-
-
-def test_update_release(release, resp_update_release):
- release.name = release_name
- release.description = release_description
- release.save()
- assert release.name == release_name
- assert release.description == release_description
diff --git a/tests/unit/objects/test_remote_mirrors.py b/tests/unit/objects/test_remote_mirrors.py
deleted file mode 100644
index 1ac35a2..0000000
--- a/tests/unit/objects/test_remote_mirrors.py
+++ /dev/null
@@ -1,72 +0,0 @@
-"""
-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/tests/unit/objects/test_repositories.py b/tests/unit/objects/test_repositories.py
deleted file mode 100644
index 7c4d77d..0000000
--- a/tests/unit/objects/test_repositories.py
+++ /dev/null
@@ -1,49 +0,0 @@
-"""
-GitLab API:
-https://docs.gitlab.com/ee/api/repositories.html
-https://docs.gitlab.com/ee/api/repository_files.html
-"""
-from urllib.parse import quote
-
-import pytest
-import responses
-
-from gitlab.v4.objects import ProjectFile
-
-file_path = "app/models/key.rb"
-ref = "main"
-
-
-@pytest.fixture
-def resp_get_repository_file():
- file_response = {
- "file_name": "key.rb",
- "file_path": file_path,
- "size": 1476,
- "encoding": "base64",
- "content": "IyA9PSBTY2hlbWEgSW5mb3...",
- "content_sha256": "4c294617b60715c1d218e61164a3abd4808a4284cbc30e6728a01ad9aada4481",
- "ref": ref,
- "blob_id": "79f7bbd25901e8334750839545a9bd021f0e4c83",
- "commit_id": "d5a3ff139356ce33e37e73add446f16869741b50",
- "last_commit_id": "570e7b2abdd848b95f2f578043fc23bd6f6fd24d",
- }
-
- # requests also encodes `.`
- encoded_path = quote(file_path, safe="").replace(".", "%2E")
-
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=f"http://localhost/api/v4/projects/1/repository/files/{encoded_path}",
- json=file_response,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-def test_get_repository_file(project, resp_get_repository_file):
- file = project.files.get(file_path, ref=ref)
- assert isinstance(file, ProjectFile)
- assert file.file_path == file_path
diff --git a/tests/unit/objects/test_resource_label_events.py b/tests/unit/objects/test_resource_label_events.py
deleted file mode 100644
index deea8a0..0000000
--- a/tests/unit/objects/test_resource_label_events.py
+++ /dev/null
@@ -1,105 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ee/api/resource_label_events.html
-"""
-
-import pytest
-import responses
-
-from gitlab.v4.objects import (
- GroupEpicResourceLabelEvent,
- ProjectIssueResourceLabelEvent,
- ProjectMergeRequestResourceLabelEvent,
-)
-
-
-@pytest.fixture()
-def resp_group_epic_request_label_events():
- epic_content = {"id": 1}
- events_content = {"id": 1, "resource_type": "Epic"}
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/groups/1/epics",
- json=[epic_content],
- content_type="application/json",
- status=200,
- )
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/groups/1/epics/1/resource_label_events",
- json=[events_content],
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture()
-def resp_merge_request_label_events():
- mr_content = {"iid": 1}
- events_content = {"id": 1, "resource_type": "MergeRequest"}
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/merge_requests",
- json=[mr_content],
- content_type="application/json",
- status=200,
- )
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/merge_requests/1/resource_label_events",
- json=[events_content],
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture()
-def resp_project_issue_label_events():
- issue_content = {"iid": 1}
- events_content = {"id": 1, "resource_type": "Issue"}
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/issues",
- json=[issue_content],
- content_type="application/json",
- status=200,
- )
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/issues/1/resource_label_events",
- json=[events_content],
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-def test_project_issue_label_events(project, resp_project_issue_label_events):
- issue = project.issues.list()[0]
- label_events = issue.resourcelabelevents.list()
- assert isinstance(label_events, list)
- label_event = label_events[0]
- assert isinstance(label_event, ProjectIssueResourceLabelEvent)
- assert label_event.resource_type == "Issue"
-
-
-def test_merge_request_label_events(project, resp_merge_request_label_events):
- mr = project.mergerequests.list()[0]
- label_events = mr.resourcelabelevents.list()
- assert isinstance(label_events, list)
- label_event = label_events[0]
- assert isinstance(label_event, ProjectMergeRequestResourceLabelEvent)
- assert label_event.resource_type == "MergeRequest"
-
-
-def test_group_epic_request_label_events(group, resp_group_epic_request_label_events):
- epic = group.epics.list()[0]
- label_events = epic.resourcelabelevents.list()
- assert isinstance(label_events, list)
- label_event = label_events[0]
- assert isinstance(label_event, GroupEpicResourceLabelEvent)
- assert label_event.resource_type == "Epic"
diff --git a/tests/unit/objects/test_resource_milestone_events.py b/tests/unit/objects/test_resource_milestone_events.py
deleted file mode 100644
index 99faeaa..0000000
--- a/tests/unit/objects/test_resource_milestone_events.py
+++ /dev/null
@@ -1,73 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ee/api/resource_milestone_events.html
-"""
-
-import pytest
-import responses
-
-from gitlab.v4.objects import (
- ProjectIssueResourceMilestoneEvent,
- ProjectMergeRequestResourceMilestoneEvent,
-)
-
-
-@pytest.fixture()
-def resp_merge_request_milestone_events():
- mr_content = {"iid": 1}
- events_content = {"id": 1, "resource_type": "MergeRequest"}
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/merge_requests",
- json=[mr_content],
- content_type="application/json",
- status=200,
- )
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/merge_requests/1/resource_milestone_events",
- json=[events_content],
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture()
-def resp_project_issue_milestone_events():
- issue_content = {"iid": 1}
- events_content = {"id": 1, "resource_type": "Issue"}
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/issues",
- json=[issue_content],
- content_type="application/json",
- status=200,
- )
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/issues/1/resource_milestone_events",
- json=[events_content],
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-def test_project_issue_milestone_events(project, resp_project_issue_milestone_events):
- issue = project.issues.list()[0]
- milestone_events = issue.resourcemilestoneevents.list()
- assert isinstance(milestone_events, list)
- milestone_event = milestone_events[0]
- assert isinstance(milestone_event, ProjectIssueResourceMilestoneEvent)
- assert milestone_event.resource_type == "Issue"
-
-
-def test_merge_request_milestone_events(project, resp_merge_request_milestone_events):
- mr = project.mergerequests.list()[0]
- milestone_events = mr.resourcemilestoneevents.list()
- assert isinstance(milestone_events, list)
- milestone_event = milestone_events[0]
- assert isinstance(milestone_event, ProjectMergeRequestResourceMilestoneEvent)
- assert milestone_event.resource_type == "MergeRequest"
diff --git a/tests/unit/objects/test_resource_state_events.py b/tests/unit/objects/test_resource_state_events.py
deleted file mode 100644
index bf18193..0000000
--- a/tests/unit/objects/test_resource_state_events.py
+++ /dev/null
@@ -1,104 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ee/api/resource_state_events.html
-"""
-
-import pytest
-import responses
-
-from gitlab.v4.objects import (
- ProjectIssueResourceStateEvent,
- ProjectMergeRequestResourceStateEvent,
-)
-
-issue_event_content = {"id": 1, "resource_type": "Issue"}
-mr_event_content = {"id": 1, "resource_type": "MergeRequest"}
-
-
-@pytest.fixture()
-def resp_list_project_issue_state_events():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/issues/1/resource_state_events",
- json=[issue_event_content],
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture()
-def resp_get_project_issue_state_event():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/issues/1/resource_state_events/1",
- json=issue_event_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture()
-def resp_list_merge_request_state_events():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/merge_requests/1/resource_state_events",
- json=[mr_event_content],
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture()
-def resp_get_merge_request_state_event():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/projects/1/merge_requests/1/resource_state_events/1",
- json=mr_event_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-def test_list_project_issue_state_events(
- project_issue, resp_list_project_issue_state_events
-):
- state_events = project_issue.resourcestateevents.list()
- assert isinstance(state_events, list)
-
- state_event = state_events[0]
- assert isinstance(state_event, ProjectIssueResourceStateEvent)
- assert state_event.resource_type == "Issue"
-
-
-def test_get_project_issue_state_event(
- project_issue, resp_get_project_issue_state_event
-):
- state_event = project_issue.resourcestateevents.get(1)
- assert isinstance(state_event, ProjectIssueResourceStateEvent)
- assert state_event.resource_type == "Issue"
-
-
-def test_list_merge_request_state_events(
- project_merge_request, resp_list_merge_request_state_events
-):
- state_events = project_merge_request.resourcestateevents.list()
- assert isinstance(state_events, list)
-
- state_event = state_events[0]
- assert isinstance(state_event, ProjectMergeRequestResourceStateEvent)
- assert state_event.resource_type == "MergeRequest"
-
-
-def test_get_merge_request_state_event(
- project_merge_request, resp_get_merge_request_state_event
-):
- state_event = project_merge_request.resourcestateevents.get(1)
- assert isinstance(state_event, ProjectMergeRequestResourceStateEvent)
- assert state_event.resource_type == "MergeRequest"
diff --git a/tests/unit/objects/test_runners.py b/tests/unit/objects/test_runners.py
deleted file mode 100644
index 686eec2..0000000
--- a/tests/unit/objects/test_runners.py
+++ /dev/null
@@ -1,282 +0,0 @@
-import re
-
-import pytest
-import responses
-
-import gitlab
-
-runner_detail = {
- "active": True,
- "architecture": "amd64",
- "description": "test-1-20150125",
- "id": 6,
- "ip_address": "127.0.0.1",
- "is_shared": False,
- "contacted_at": "2016-01-25T16:39:48.066Z",
- "name": "test-runner",
- "online": True,
- "status": "online",
- "platform": "linux",
- "projects": [
- {
- "id": 1,
- "name": "GitLab Community Edition",
- "name_with_namespace": "GitLab.org / GitLab Community Edition",
- "path": "gitlab-foss",
- "path_with_namespace": "gitlab-org/gitlab-foss",
- }
- ],
- "revision": "5nj35",
- "tag_list": ["ruby", "mysql"],
- "version": "v13.0.0",
- "access_level": "ref_protected",
- "maximum_timeout": 3600,
-}
-
-runner_shortinfo = {
- "active": True,
- "description": "test-1-20150125",
- "id": 6,
- "is_shared": False,
- "ip_address": "127.0.0.1",
- "name": "test-name",
- "online": True,
- "status": "online",
-}
-
-runner_jobs = [
- {
- "id": 6,
- "ip_address": "127.0.0.1",
- "status": "running",
- "stage": "test",
- "name": "test",
- "ref": "master",
- "tag": False,
- "coverage": "99%",
- "created_at": "2017-11-16T08:50:29.000Z",
- "started_at": "2017-11-16T08:51:29.000Z",
- "finished_at": "2017-11-16T08:53:29.000Z",
- "duration": 120,
- "user": {
- "id": 1,
- "name": "John Doe2",
- "username": "user2",
- "state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon",
- "web_url": "http://localhost/user2",
- "created_at": "2017-11-16T18:38:46.000Z",
- "bio": None,
- "location": None,
- "public_email": "",
- "skype": "",
- "linkedin": "",
- "twitter": "",
- "website_url": "",
- "organization": None,
- },
- }
-]
-
-
-@pytest.fixture
-def resp_get_runners_jobs():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/runners/6/jobs",
- json=runner_jobs,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_get_runners_list():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=re.compile(r".*?(/runners(/all)?|/(groups|projects)/1/runners)"),
- json=[runner_shortinfo],
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_runner_detail():
- with responses.RequestsMock() as rsps:
- pattern = re.compile(r".*?/runners/6")
- rsps.add(
- method=responses.GET,
- url=pattern,
- json=runner_detail,
- content_type="application/json",
- status=200,
- )
- rsps.add(
- method=responses.PUT,
- url=pattern,
- json=runner_detail,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_runner_register():
- with responses.RequestsMock() as rsps:
- pattern = re.compile(r".*?/runners")
- rsps.add(
- method=responses.POST,
- url=pattern,
- json={"id": "6", "token": "6337ff461c94fd3fa32ba3b1ff4125"},
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_runner_enable():
- with responses.RequestsMock() as rsps:
- pattern = re.compile(r".*?(projects|groups)/1/runners")
- rsps.add(
- method=responses.POST,
- url=pattern,
- json=runner_shortinfo,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_runner_delete():
- with responses.RequestsMock() as rsps:
- pattern = re.compile(r".*?/runners/6")
- rsps.add(
- method=responses.GET,
- url=pattern,
- json=runner_detail,
- content_type="application/json",
- status=200,
- )
- rsps.add(
- method=responses.DELETE,
- url=pattern,
- status=204,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_runner_disable():
- with responses.RequestsMock() as rsps:
- pattern = re.compile(r".*?/(groups|projects)/1/runners/6")
- rsps.add(
- method=responses.DELETE,
- url=pattern,
- status=204,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_runner_verify():
- with responses.RequestsMock() as rsps:
- pattern = re.compile(r".*?/runners/verify")
- rsps.add(
- method=responses.POST,
- url=pattern,
- status=200,
- )
- yield rsps
-
-
-def test_owned_runners_list(gl: gitlab.Gitlab, resp_get_runners_list):
- runners = gl.runners.list()
- assert runners[0].active is True
- assert runners[0].id == 6
- assert runners[0].name == "test-name"
- assert len(runners) == 1
-
-
-def test_project_runners_list(gl: gitlab.Gitlab, resp_get_runners_list):
- runners = gl.projects.get(1, lazy=True).runners.list()
- assert runners[0].active is True
- assert runners[0].id == 6
- assert runners[0].name == "test-name"
- assert len(runners) == 1
-
-
-def test_group_runners_list(gl: gitlab.Gitlab, resp_get_runners_list):
- runners = gl.groups.get(1, lazy=True).runners.list()
- assert runners[0].active is True
- assert runners[0].id == 6
- assert runners[0].name == "test-name"
- assert len(runners) == 1
-
-
-def test_all_runners_list(gl: gitlab.Gitlab, resp_get_runners_list):
- runners = gl.runners.all()
- assert runners[0].active is True
- assert runners[0].id == 6
- assert runners[0].name == "test-name"
- assert len(runners) == 1
-
-
-def test_create_runner(gl: gitlab.Gitlab, resp_runner_register):
- runner = gl.runners.create({"token": "token"})
- assert runner.id == "6"
- assert runner.token == "6337ff461c94fd3fa32ba3b1ff4125"
-
-
-def test_get_update_runner(gl: gitlab.Gitlab, resp_runner_detail):
- runner = gl.runners.get(6)
- assert runner.active is True
- runner.tag_list.append("new")
- runner.save()
-
-
-def test_remove_runner(gl: gitlab.Gitlab, resp_runner_delete):
- runner = gl.runners.get(6)
- runner.delete()
- gl.runners.delete(6)
-
-
-def test_disable_project_runner(gl: gitlab.Gitlab, resp_runner_disable):
- gl.projects.get(1, lazy=True).runners.delete(6)
-
-
-def test_disable_group_runner(gl: gitlab.Gitlab, resp_runner_disable):
- gl.groups.get(1, lazy=True).runners.delete(6)
-
-
-def test_enable_project_runner(gl: gitlab.Gitlab, resp_runner_enable):
- runner = gl.projects.get(1, lazy=True).runners.create({"runner_id": 6})
- assert runner.active is True
- assert runner.id == 6
- assert runner.name == "test-name"
-
-
-def test_enable_group_runner(gl: gitlab.Gitlab, resp_runner_enable):
- runner = gl.groups.get(1, lazy=True).runners.create({"runner_id": 6})
- assert runner.active is True
- assert runner.id == 6
- assert runner.name == "test-name"
-
-
-def test_verify_runner(gl: gitlab.Gitlab, resp_runner_verify):
- gl.runners.verify("token")
-
-
-def test_runner_jobs(gl: gitlab.Gitlab, resp_get_runners_jobs):
- jobs = gl.runners.get(6, lazy=True).jobs.list()
- assert jobs[0].duration == 120
- assert jobs[0].name == "test"
- assert jobs[0].user.get("name") == "John Doe2"
- assert len(jobs) == 1
diff --git a/tests/unit/objects/test_services.py b/tests/unit/objects/test_services.py
deleted file mode 100644
index 5b2bcb8..0000000
--- a/tests/unit/objects/test_services.py
+++ /dev/null
@@ -1,93 +0,0 @@
-"""
-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/tests/unit/objects/test_snippets.py b/tests/unit/objects/test_snippets.py
deleted file mode 100644
index 2540fc3..0000000
--- a/tests/unit/objects/test_snippets.py
+++ /dev/null
@@ -1,89 +0,0 @@
-"""
-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/tests/unit/objects/test_submodules.py b/tests/unit/objects/test_submodules.py
deleted file mode 100644
index 69c1cd7..0000000
--- a/tests/unit/objects/test_submodules.py
+++ /dev/null
@@ -1,46 +0,0 @@
-"""
-GitLab API: https://docs.gitlab.com/ce/api/repository_submodules.html
-"""
-import pytest
-import responses
-
-
-@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/tests/unit/objects/test_todos.py b/tests/unit/objects/test_todos.py
deleted file mode 100644
index 058fe33..0000000
--- a/tests/unit/objects/test_todos.py
+++ /dev/null
@@ -1,62 +0,0 @@
-"""
-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/tests/unit/objects/test_users.py b/tests/unit/objects/test_users.py
deleted file mode 100644
index e46a315..0000000
--- a/tests/unit/objects/test_users.py
+++ /dev/null
@@ -1,217 +0,0 @@
-"""
-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
-
-
-@pytest.fixture
-def resp_delete_user_identity(no_content):
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.DELETE,
- url="http://localhost/api/v4/users/1/identities/test_provider",
- json=no_content,
- content_type="application/json",
- status=204,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_follow_unfollow():
- user = {
- "id": 1,
- "username": "john_smith",
- "name": "John Smith",
- "state": "active",
- "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg",
- "web_url": "http://localhost:3000/john_smith",
- }
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.POST,
- url="http://localhost/api/v4/users/1/follow",
- json=user,
- content_type="application/json",
- status=201,
- )
- rsps.add(
- method=responses.POST,
- url="http://localhost/api/v4/users/1/unfollow",
- json=user,
- content_type="application/json",
- status=201,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_followers_following():
- content = [
- {
- "id": 2,
- "name": "Lennie Donnelly",
- "username": "evette.kilback",
- "state": "active",
- "avatar_url": "https://www.gravatar.com/avatar/7955171a55ac4997ed81e5976287890a?s=80&d=identicon",
- "web_url": "http://127.0.0.1:3000/evette.kilback",
- },
- {
- "id": 4,
- "name": "Serena Bradtke",
- "username": "cammy",
- "state": "active",
- "avatar_url": "https://www.gravatar.com/avatar/a2daad869a7b60d3090b7b9bef4baf57?s=80&d=identicon",
- "web_url": "http://127.0.0.1:3000/cammy",
- },
- ]
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/users/1/followers",
- json=content,
- content_type="application/json",
- status=200,
- )
- rsps.add(
- method=responses.GET,
- url="http://localhost/api/v4/users/1/following",
- 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()
-
-
-def test_delete_user_identity(user, resp_delete_user_identity):
- user.identityproviders.delete("test_provider")
-
-
-def test_user_follow_unfollow(user, resp_follow_unfollow):
- user.follow()
- user.unfollow()
-
-
-def test_list_followers(user, resp_followers_following):
- followers = user.followers_users.list()
- followings = user.following_users.list()
- assert isinstance(followers[0], User)
- assert followers[0].id == 2
- assert isinstance(followings[0], User)
- assert followings[1].id == 4
diff --git a/tests/unit/objects/test_variables.py b/tests/unit/objects/test_variables.py
deleted file mode 100644
index fae37a8..0000000
--- a/tests/unit/objects/test_variables.py
+++ /dev/null
@@ -1,192 +0,0 @@
-"""
-GitLab API:
-https://docs.gitlab.com/ee/api/instance_level_ci_variables.html
-https://docs.gitlab.com/ee/api/project_level_variables.html
-https://docs.gitlab.com/ee/api/group_level_variables.html
-"""
-
-import re
-
-import pytest
-import responses
-
-from gitlab.v4.objects import GroupVariable, ProjectVariable, Variable
-
-key = "TEST_VARIABLE_1"
-value = "TEST_1"
-new_value = "TEST_2"
-
-variable_content = {
- "key": key,
- "variable_type": "env_var",
- "value": value,
- "protected": False,
- "masked": True,
-}
-variables_url = re.compile(
- r"http://localhost/api/v4/(((groups|projects)/1)|(admin/ci))/variables"
-)
-variables_key_url = re.compile(
- rf"http://localhost/api/v4/(((groups|projects)/1)|(admin/ci))/variables/{key}"
-)
-
-
-@pytest.fixture
-def resp_list_variables():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=variables_url,
- json=[variable_content],
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_get_variable():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.GET,
- url=variables_key_url,
- json=variable_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_create_variable():
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.POST,
- url=variables_url,
- json=variable_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_update_variable():
- updated_content = dict(variable_content)
- updated_content["value"] = new_value
-
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.PUT,
- url=variables_key_url,
- json=updated_content,
- content_type="application/json",
- status=200,
- )
- yield rsps
-
-
-@pytest.fixture
-def resp_delete_variable(no_content):
- with responses.RequestsMock() as rsps:
- rsps.add(
- method=responses.DELETE,
- url=variables_key_url,
- json=no_content,
- content_type="application/json",
- status=204,
- )
- yield rsps
-
-
-def test_list_instance_variables(gl, resp_list_variables):
- variables = gl.variables.list()
- assert isinstance(variables, list)
- assert isinstance(variables[0], Variable)
- assert variables[0].value == value
-
-
-def test_get_instance_variable(gl, resp_get_variable):
- variable = gl.variables.get(key)
- assert isinstance(variable, Variable)
- assert variable.value == value
-
-
-def test_create_instance_variable(gl, resp_create_variable):
- variable = gl.variables.create({"key": key, "value": value})
- assert isinstance(variable, Variable)
- assert variable.value == value
-
-
-def test_update_instance_variable(gl, resp_update_variable):
- variable = gl.variables.get(key, lazy=True)
- variable.value = new_value
- variable.save()
- assert variable.value == new_value
-
-
-def test_delete_instance_variable(gl, resp_delete_variable):
- variable = gl.variables.get(key, lazy=True)
- variable.delete()
-
-
-def test_list_project_variables(project, resp_list_variables):
- variables = project.variables.list()
- assert isinstance(variables, list)
- assert isinstance(variables[0], ProjectVariable)
- assert variables[0].value == value
-
-
-def test_get_project_variable(project, resp_get_variable):
- variable = project.variables.get(key)
- assert isinstance(variable, ProjectVariable)
- assert variable.value == value
-
-
-def test_create_project_variable(project, resp_create_variable):
- variable = project.variables.create({"key": key, "value": value})
- assert isinstance(variable, ProjectVariable)
- assert variable.value == value
-
-
-def test_update_project_variable(project, resp_update_variable):
- variable = project.variables.get(key, lazy=True)
- variable.value = new_value
- variable.save()
- assert variable.value == new_value
-
-
-def test_delete_project_variable(project, resp_delete_variable):
- variable = project.variables.get(key, lazy=True)
- variable.delete()
-
-
-def test_list_group_variables(group, resp_list_variables):
- variables = group.variables.list()
- assert isinstance(variables, list)
- assert isinstance(variables[0], GroupVariable)
- assert variables[0].value == value
-
-
-def test_get_group_variable(group, resp_get_variable):
- variable = group.variables.get(key)
- assert isinstance(variable, GroupVariable)
- assert variable.value == value
-
-
-def test_create_group_variable(group, resp_create_variable):
- variable = group.variables.create({"key": key, "value": value})
- assert isinstance(variable, GroupVariable)
- assert variable.value == value
-
-
-def test_update_group_variable(group, resp_update_variable):
- variable = group.variables.get(key, lazy=True)
- variable.value = new_value
- variable.save()
- assert variable.value == new_value
-
-
-def test_delete_group_variable(group, resp_delete_variable):
- variable = group.variables.get(key, lazy=True)
- variable.delete()
diff --git a/tests/unit/test_base.py b/tests/unit/test_base.py
deleted file mode 100644
index cccdfad..0000000
--- a/tests/unit/test_base.py
+++ /dev/null
@@ -1,179 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2017 Gauvain Pocentek <gauvain@pocentek.net>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import pickle
-
-import pytest
-
-import gitlab
-from gitlab import base
-
-
-class FakeGitlab(object):
- pass
-
-
-class FakeObject(base.RESTObject):
- pass
-
-
-class FakeManager(base.RESTManager):
- _obj_cls = FakeObject
- _path = "/tests"
-
-
-@pytest.fixture
-def fake_gitlab():
- return FakeGitlab()
-
-
-@pytest.fixture
-def fake_manager(fake_gitlab):
- return FakeManager(fake_gitlab)
-
-
-class TestRESTManager:
- def test_computed_path_simple(self):
- class MGR(base.RESTManager):
- _path = "/tests"
- _obj_cls = object
-
- mgr = MGR(FakeGitlab())
- assert mgr._computed_path == "/tests"
-
- def test_computed_path_with_parent(self):
- class MGR(base.RESTManager):
- _path = "/tests/%(test_id)s/cases"
- _obj_cls = object
- _from_parent_attrs = {"test_id": "id"}
-
- class Parent(object):
- id = 42
-
- mgr = MGR(FakeGitlab(), parent=Parent())
- assert mgr._computed_path == "/tests/42/cases"
-
- def test_path_property(self):
- class MGR(base.RESTManager):
- _path = "/tests"
- _obj_cls = object
-
- mgr = MGR(FakeGitlab())
- assert mgr.path == "/tests"
-
-
-class TestRESTObject:
- def test_instantiate(self, fake_gitlab, fake_manager):
- obj = FakeObject(fake_manager, {"foo": "bar"})
-
- assert {"foo": "bar"} == obj._attrs
- assert {} == obj._updated_attrs
- assert obj._create_managers() is None
- assert fake_manager == obj.manager
- assert fake_gitlab == obj.manager.gitlab
-
- def test_instantiate_non_dict(self, fake_gitlab, fake_manager):
- with pytest.raises(gitlab.exceptions.GitlabParsingError):
- FakeObject(fake_manager, ["a", "list", "fails"])
-
- def test_picklability(self, fake_manager):
- obj = FakeObject(fake_manager, {"foo": "bar"})
- original_obj_module = obj._module
- pickled = pickle.dumps(obj)
- unpickled = pickle.loads(pickled)
- assert isinstance(unpickled, FakeObject)
- assert hasattr(unpickled, "_module")
- assert unpickled._module == original_obj_module
- pickle.dumps(unpickled)
-
- def test_attrs(self, fake_manager):
- obj = FakeObject(fake_manager, {"foo": "bar"})
-
- assert "bar" == obj.foo
- with pytest.raises(AttributeError):
- getattr(obj, "bar")
-
- obj.bar = "baz"
- assert "baz" == obj.bar
- assert {"foo": "bar"} == obj._attrs
- assert {"bar": "baz"} == obj._updated_attrs
-
- def test_get_id(self, fake_manager):
- obj = FakeObject(fake_manager, {"foo": "bar"})
- obj.id = 42
- assert 42 == obj.get_id()
-
- obj.id = None
- assert obj.get_id() is None
-
- def test_custom_id_attr(self, fake_manager):
- class OtherFakeObject(FakeObject):
- _id_attr = "foo"
-
- obj = OtherFakeObject(fake_manager, {"foo": "bar"})
- assert "bar" == obj.get_id()
-
- def test_update_attrs(self, fake_manager):
- obj = FakeObject(fake_manager, {"foo": "bar"})
- obj.bar = "baz"
- obj._update_attrs({"foo": "foo", "bar": "bar"})
- assert {"foo": "foo", "bar": "bar"} == obj._attrs
- assert {} == obj._updated_attrs
-
- def test_update_attrs_deleted(self, fake_manager):
- obj = FakeObject(fake_manager, {"foo": "foo", "bar": "bar"})
- obj.bar = "baz"
- obj._update_attrs({"foo": "foo"})
- assert {"foo": "foo"} == obj._attrs
- assert {} == obj._updated_attrs
-
- def test_dir_unique(self, fake_manager):
- obj = FakeObject(fake_manager, {"manager": "foo"})
- assert len(dir(obj)) == len(set(dir(obj)))
-
- def test_create_managers(self, fake_gitlab, fake_manager):
- class ObjectWithManager(FakeObject):
- fakes: "FakeManager"
-
- obj = ObjectWithManager(fake_manager, {"foo": "bar"})
- obj.id = 42
- assert isinstance(obj.fakes, FakeManager)
- assert obj.fakes.gitlab == fake_gitlab
- assert obj.fakes._parent == obj
-
- def test_equality(self, fake_manager):
- obj1 = FakeObject(fake_manager, {"id": "foo"})
- obj2 = FakeObject(fake_manager, {"id": "foo", "other_attr": "bar"})
- assert obj1 == obj2
-
- def test_equality_custom_id(self, fake_manager):
- class OtherFakeObject(FakeObject):
- _id_attr = "foo"
-
- obj1 = OtherFakeObject(fake_manager, {"foo": "bar"})
- obj2 = OtherFakeObject(fake_manager, {"foo": "bar", "other_attr": "baz"})
- assert obj1 == obj2
-
- def test_inequality(self, fake_manager):
- obj1 = FakeObject(fake_manager, {"id": "foo"})
- obj2 = FakeObject(fake_manager, {"id": "bar"})
- assert obj1 != obj2
-
- def test_inequality_no_id(self, fake_manager):
- obj1 = FakeObject(fake_manager, {"attr1": "foo"})
- obj2 = FakeObject(fake_manager, {"attr1": "bar"})
- assert obj1 != obj2
diff --git a/tests/unit/test_cli.py b/tests/unit/test_cli.py
deleted file mode 100644
index a9ca958..0000000
--- a/tests/unit/test_cli.py
+++ /dev/null
@@ -1,157 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2016-2017 Gauvain Pocentek <gauvain@pocentek.net>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import argparse
-import io
-import os
-import tempfile
-from contextlib import redirect_stderr # noqa: H302
-
-import pytest
-
-from gitlab import cli
-
-
-@pytest.mark.parametrize(
- "what,expected_class",
- [
- ("class", "Class"),
- ("test-class", "TestClass"),
- ("test-longer-class", "TestLongerClass"),
- ("current-user-gpg-key", "CurrentUserGPGKey"),
- ("user-gpg-key", "UserGPGKey"),
- ("ldap-group", "LDAPGroup"),
- ],
-)
-def test_what_to_cls(what, expected_class):
- def _namespace():
- pass
-
- ExpectedClass = type(expected_class, (), {})
- _namespace.__dict__[expected_class] = ExpectedClass
-
- assert cli.what_to_cls(what, _namespace) == ExpectedClass
-
-
-@pytest.mark.parametrize(
- "class_name,expected_what",
- [
- ("Class", "class"),
- ("TestClass", "test-class"),
- ("TestUPPERCASEClass", "test-uppercase-class"),
- ("UPPERCASETestClass", "uppercase-test-class"),
- ("CurrentUserGPGKey", "current-user-gpg-key"),
- ("UserGPGKey", "user-gpg-key"),
- ("LDAPGroup", "ldap-group"),
- ],
-)
-def test_cls_to_what(class_name, expected_what):
- TestClass = type(class_name, (), {})
-
- assert cli.cls_to_what(TestClass) == expected_what
-
-
-def test_die():
- fl = io.StringIO()
- with redirect_stderr(fl):
- with pytest.raises(SystemExit) as test:
- cli.die("foobar")
- assert fl.getvalue() == "foobar\n"
- assert test.value.code == 1
-
-
-def test_parse_value():
- ret = cli._parse_value("foobar")
- assert ret == "foobar"
-
- ret = cli._parse_value(True)
- assert ret is True
-
- ret = cli._parse_value(1)
- assert ret == 1
-
- ret = cli._parse_value(None)
- assert ret is None
-
- fd, temp_path = tempfile.mkstemp()
- os.write(fd, b"content")
- os.close(fd)
- ret = cli._parse_value("@%s" % temp_path)
- assert ret == "content"
- os.unlink(temp_path)
-
- fl = io.StringIO()
- with redirect_stderr(fl):
- with pytest.raises(SystemExit) as exc:
- cli._parse_value("@/thisfileprobablydoesntexist")
- assert (
- fl.getvalue() == "[Errno 2] No such file or directory:"
- " '/thisfileprobablydoesntexist'\n"
- )
- assert exc.value.code == 1
-
-
-def test_base_parser():
- parser = cli._get_base_parser()
- args = parser.parse_args(["-v", "-g", "gl_id", "-c", "foo.cfg", "-c", "bar.cfg"])
- assert args.verbose
- assert args.gitlab == "gl_id"
- assert args.config_file == ["foo.cfg", "bar.cfg"]
-
-
-def test_v4_parse_args():
- parser = cli._get_parser()
- args = parser.parse_args(["project", "list"])
- assert args.what == "project"
- assert args.whaction == "list"
-
-
-def test_v4_parser():
- parser = cli._get_parser()
- subparsers = next(
- action
- for action in parser._actions
- if isinstance(action, argparse._SubParsersAction)
- )
- assert subparsers is not None
- assert "project" in subparsers.choices
-
- user_subparsers = next(
- action
- for action in subparsers.choices["project"]._actions
- if isinstance(action, argparse._SubParsersAction)
- )
- assert user_subparsers is not None
- assert "list" in user_subparsers.choices
- assert "get" in user_subparsers.choices
- assert "delete" in user_subparsers.choices
- assert "update" in user_subparsers.choices
- assert "create" in user_subparsers.choices
- assert "archive" in user_subparsers.choices
- assert "unarchive" in user_subparsers.choices
-
- actions = user_subparsers.choices["create"]._option_string_actions
- assert not actions["--description"].required
-
- user_subparsers = next(
- action
- for action in subparsers.choices["group"]._actions
- if isinstance(action, argparse._SubParsersAction)
- )
- actions = user_subparsers.choices["create"]._option_string_actions
- assert actions["--name"].required
diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py
deleted file mode 100644
index a62106b..0000000
--- a/tests/unit/test_config.py
+++ /dev/null
@@ -1,317 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2016-2017 Gauvain Pocentek <gauvain@pocentek.net>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import io
-import os
-from textwrap import dedent
-
-import mock
-import pytest
-
-from gitlab import config, USER_AGENT
-
-custom_user_agent = "my-package/1.0.0"
-
-valid_config = u"""[global]
-default = one
-ssl_verify = true
-timeout = 2
-
-[one]
-url = http://one.url
-private_token = ABCDEF
-
-[two]
-url = https://two.url
-private_token = GHIJKL
-ssl_verify = false
-timeout = 10
-
-[three]
-url = https://three.url
-private_token = MNOPQR
-ssl_verify = /path/to/CA/bundle.crt
-per_page = 50
-
-[four]
-url = https://four.url
-oauth_token = STUV
-"""
-
-custom_user_agent_config = """[global]
-default = one
-user_agent = {}
-
-[one]
-url = http://one.url
-private_token = ABCDEF
-""".format(
- custom_user_agent
-)
-
-no_default_config = u"""[global]
-[there]
-url = http://there.url
-private_token = ABCDEF
-"""
-
-missing_attr_config = u"""[global]
-[one]
-url = http://one.url
-
-[two]
-private_token = ABCDEF
-
-[three]
-meh = hem
-
-[four]
-url = http://four.url
-private_token = ABCDEF
-per_page = 200
-"""
-
-
-def global_retry_transient_errors(value: bool) -> str:
- return u"""[global]
-default = one
-retry_transient_errors={}
-[one]
-url = http://one.url
-private_token = ABCDEF""".format(
- value
- )
-
-
-def global_and_gitlab_retry_transient_errors(
- global_value: bool, gitlab_value: bool
-) -> str:
- return u"""[global]
- default = one
- retry_transient_errors={global_value}
- [one]
- url = http://one.url
- private_token = ABCDEF
- retry_transient_errors={gitlab_value}""".format(
- global_value=global_value, gitlab_value=gitlab_value
- )
-
-
-@mock.patch.dict(os.environ, {"PYTHON_GITLAB_CFG": "/some/path"})
-def test_env_config_present():
- assert ["/some/path"] == config._env_config()
-
-
-@mock.patch.dict(os.environ, {}, clear=True)
-def test_env_config_missing():
- assert [] == config._env_config()
-
-
-@mock.patch("os.path.exists")
-def test_missing_config(path_exists):
- path_exists.return_value = False
- with pytest.raises(config.GitlabConfigMissingError):
- config.GitlabConfigParser("test")
-
-
-@mock.patch("os.path.exists")
-@mock.patch("builtins.open")
-def test_invalid_id(m_open, path_exists):
- fd = io.StringIO(no_default_config)
- fd.close = mock.Mock(return_value=None)
- m_open.return_value = fd
- path_exists.return_value = True
- config.GitlabConfigParser("there")
- with pytest.raises(config.GitlabIDError):
- config.GitlabConfigParser()
-
- fd = io.StringIO(valid_config)
- fd.close = mock.Mock(return_value=None)
- m_open.return_value = fd
- with pytest.raises(config.GitlabDataError):
- config.GitlabConfigParser(gitlab_id="not_there")
-
-
-@mock.patch("os.path.exists")
-@mock.patch("builtins.open")
-def test_invalid_data(m_open, path_exists):
- fd = io.StringIO(missing_attr_config)
- fd.close = mock.Mock(return_value=None, side_effect=lambda: fd.seek(0))
- m_open.return_value = fd
- path_exists.return_value = True
-
- config.GitlabConfigParser("one")
- config.GitlabConfigParser("one")
- with pytest.raises(config.GitlabDataError):
- config.GitlabConfigParser(gitlab_id="two")
- with pytest.raises(config.GitlabDataError):
- config.GitlabConfigParser(gitlab_id="three")
- with pytest.raises(config.GitlabDataError) as emgr:
- config.GitlabConfigParser("four")
- assert "Unsupported per_page number: 200" == emgr.value.args[0]
-
-
-@mock.patch("os.path.exists")
-@mock.patch("builtins.open")
-def test_valid_data(m_open, path_exists):
- fd = io.StringIO(valid_config)
- fd.close = mock.Mock(return_value=None)
- m_open.return_value = fd
- path_exists.return_value = True
-
- cp = config.GitlabConfigParser()
- assert "one" == cp.gitlab_id
- assert "http://one.url" == cp.url
- assert "ABCDEF" == cp.private_token
- assert cp.oauth_token is None
- assert 2 == cp.timeout
- assert cp.ssl_verify is True
- assert cp.per_page is None
-
- fd = io.StringIO(valid_config)
- fd.close = mock.Mock(return_value=None)
- m_open.return_value = fd
- cp = config.GitlabConfigParser(gitlab_id="two")
- assert "two" == cp.gitlab_id
- assert "https://two.url" == cp.url
- assert "GHIJKL" == cp.private_token
- assert cp.oauth_token is None
- assert 10 == cp.timeout
- assert cp.ssl_verify is False
-
- fd = io.StringIO(valid_config)
- fd.close = mock.Mock(return_value=None)
- m_open.return_value = fd
- cp = config.GitlabConfigParser(gitlab_id="three")
- assert "three" == cp.gitlab_id
- assert "https://three.url" == cp.url
- assert "MNOPQR" == cp.private_token
- assert cp.oauth_token is None
- assert 2 == cp.timeout
- assert "/path/to/CA/bundle.crt" == cp.ssl_verify
- assert 50 == cp.per_page
-
- fd = io.StringIO(valid_config)
- fd.close = mock.Mock(return_value=None)
- m_open.return_value = fd
- cp = config.GitlabConfigParser(gitlab_id="four")
- assert "four" == cp.gitlab_id
- assert "https://four.url" == cp.url
- assert cp.private_token is None
- assert "STUV" == cp.oauth_token
- assert 2 == cp.timeout
- assert cp.ssl_verify is True
-
-
-@mock.patch("os.path.exists")
-@mock.patch("builtins.open")
-def test_data_from_helper(m_open, path_exists, tmp_path):
- helper = tmp_path / "helper.sh"
- helper.write_text(
- dedent(
- """\
- #!/bin/sh
- echo "secret"
- """
- )
- )
- helper.chmod(0o755)
-
- fd = io.StringIO(
- dedent(
- """\
- [global]
- default = helper
-
- [helper]
- url = https://helper.url
- oauth_token = helper: %s
- """
- )
- % helper
- )
-
- fd.close = mock.Mock(return_value=None)
- m_open.return_value = fd
- cp = config.GitlabConfigParser(gitlab_id="helper")
- assert "helper" == cp.gitlab_id
- assert "https://helper.url" == cp.url
- assert cp.private_token is None
- assert "secret" == cp.oauth_token
-
-
-@mock.patch("os.path.exists")
-@mock.patch("builtins.open")
-@pytest.mark.parametrize(
- "config_string,expected_agent",
- [
- (valid_config, USER_AGENT),
- (custom_user_agent_config, custom_user_agent),
- ],
-)
-def test_config_user_agent(m_open, path_exists, config_string, expected_agent):
- fd = io.StringIO(config_string)
- fd.close = mock.Mock(return_value=None)
- m_open.return_value = fd
-
- cp = config.GitlabConfigParser()
- assert cp.user_agent == expected_agent
-
-
-@mock.patch("os.path.exists")
-@mock.patch("builtins.open")
-@pytest.mark.parametrize(
- "config_string,expected",
- [
- pytest.param(valid_config, False, id="default_value"),
- pytest.param(
- global_retry_transient_errors(True), True, id="global_config_true"
- ),
- pytest.param(
- global_retry_transient_errors(False), False, id="global_config_false"
- ),
- pytest.param(
- global_and_gitlab_retry_transient_errors(False, True),
- True,
- id="gitlab_overrides_global_true",
- ),
- pytest.param(
- global_and_gitlab_retry_transient_errors(True, False),
- False,
- id="gitlab_overrides_global_false",
- ),
- pytest.param(
- global_and_gitlab_retry_transient_errors(True, True),
- True,
- id="gitlab_equals_global_true",
- ),
- pytest.param(
- global_and_gitlab_retry_transient_errors(False, False),
- False,
- id="gitlab_equals_global_false",
- ),
- ],
-)
-def test_config_retry_transient_errors_when_global_config_is_set(
- m_open, path_exists, config_string, expected
-):
- fd = io.StringIO(config_string)
- fd.close = mock.Mock(return_value=None)
- m_open.return_value = fd
-
- cp = config.GitlabConfigParser()
- assert cp.retry_transient_errors == expected
diff --git a/tests/unit/test_exceptions.py b/tests/unit/test_exceptions.py
deleted file mode 100644
index 57b394b..0000000
--- a/tests/unit/test_exceptions.py
+++ /dev/null
@@ -1,18 +0,0 @@
-import pytest
-
-from gitlab import exceptions
-
-
-def test_error_raises_from_http_error():
- """Methods decorated with @on_http_error should raise from GitlabHttpError."""
-
- class TestError(Exception):
- pass
-
- @exceptions.on_http_error(TestError)
- def raise_error_from_http_error():
- raise exceptions.GitlabHttpError
-
- with pytest.raises(TestError) as context:
- raise_error_from_http_error()
- assert isinstance(context.value.__cause__, exceptions.GitlabHttpError)
diff --git a/tests/unit/test_gitlab.py b/tests/unit/test_gitlab.py
deleted file mode 100644
index 2bd7d4d..0000000
--- a/tests/unit/test_gitlab.py
+++ /dev/null
@@ -1,196 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 Mika Mäenpää <mika.j.maenpaa@tut.fi>,
-# Tampere University of Technology
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or`
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import pickle
-
-import pytest
-from httmock import HTTMock, response, urlmatch, with_httmock # noqa
-
-from gitlab import DEFAULT_URL, Gitlab, GitlabList, USER_AGENT
-from gitlab.v4.objects import CurrentUser
-
-localhost = "http://localhost"
-username = "username"
-user_id = 1
-token = "abc123"
-
-
-@urlmatch(scheme="http", netloc="localhost", path="/api/v4/user", method="get")
-def resp_get_user(url, request):
- headers = {"content-type": "application/json"}
- content = '{{"id": {0:d}, "username": "{1:s}"}}'.format(user_id, username).encode(
- "utf-8"
- )
- return response(200, content, headers, None, 5, request)
-
-
-@urlmatch(scheme="http", netloc="localhost", path="/api/v4/tests", method="get")
-def resp_page_1(url, request):
- headers = {
- "content-type": "application/json",
- "X-Page": 1,
- "X-Next-Page": 2,
- "X-Per-Page": 1,
- "X-Total-Pages": 2,
- "X-Total": 2,
- "Link": ("<http://localhost/api/v4/tests?per_page=1&page=2>;" ' rel="next"'),
- }
- content = '[{"a": "b"}]'
- return response(200, content, headers, None, 5, request)
-
-
-@urlmatch(
- scheme="http",
- netloc="localhost",
- path="/api/v4/tests",
- method="get",
- query=r".*page=2",
-)
-def resp_page_2(url, request):
- headers = {
- "content-type": "application/json",
- "X-Page": 2,
- "X-Next-Page": 2,
- "X-Per-Page": 1,
- "X-Total-Pages": 2,
- "X-Total": 2,
- }
- content = '[{"c": "d"}]'
- return response(200, content, headers, None, 5, request)
-
-
-def test_gitlab_build_list(gl):
- with HTTMock(resp_page_1):
- obj = gl.http_list("/tests", as_list=False)
- assert len(obj) == 2
- assert obj._next_url == "http://localhost/api/v4/tests?per_page=1&page=2"
- assert obj.current_page == 1
- assert obj.prev_page is None
- assert obj.next_page == 2
- assert obj.per_page == 1
- assert obj.total_pages == 2
- assert obj.total == 2
-
- with HTTMock(resp_page_2):
- test_list = list(obj)
- assert len(test_list) == 2
- assert test_list[0]["a"] == "b"
- assert test_list[1]["c"] == "d"
-
-
-@with_httmock(resp_page_1, resp_page_2)
-def test_gitlab_all_omitted_when_as_list(gl):
- result = gl.http_list("/tests", as_list=False, all=True)
- assert isinstance(result, GitlabList)
-
-
-def test_gitlab_strip_base_url(gl_trailing):
- assert gl_trailing.url == "http://localhost"
-
-
-def test_gitlab_strip_api_url(gl_trailing):
- assert gl_trailing.api_url == "http://localhost/api/v4"
-
-
-def test_gitlab_build_url(gl_trailing):
- r = gl_trailing._build_url("/projects")
- assert r == "http://localhost/api/v4/projects"
-
-
-def test_gitlab_pickability(gl):
- original_gl_objects = gl._objects
- pickled = pickle.dumps(gl)
- unpickled = pickle.loads(pickled)
- assert isinstance(unpickled, Gitlab)
- assert hasattr(unpickled, "_objects")
- assert unpickled._objects == original_gl_objects
-
-
-@with_httmock(resp_get_user)
-def test_gitlab_token_auth(gl, callback=None):
- gl.auth()
- assert gl.user.username == username
- assert gl.user.id == user_id
- assert isinstance(gl.user, CurrentUser)
-
-
-def test_gitlab_default_url():
- gl = Gitlab()
- assert gl.url == DEFAULT_URL
-
-
-@pytest.mark.parametrize(
- "args, kwargs, expected_url, expected_private_token, expected_oauth_token",
- [
- ([], {}, DEFAULT_URL, None, None),
- ([None, token], {}, DEFAULT_URL, token, None),
- ([localhost], {}, localhost, None, None),
- ([localhost, token], {}, localhost, token, None),
- ([localhost, None, token], {}, localhost, None, token),
- ([], {"private_token": token}, DEFAULT_URL, token, None),
- ([], {"oauth_token": token}, DEFAULT_URL, None, token),
- ([], {"url": localhost}, localhost, None, None),
- ([], {"url": localhost, "private_token": token}, localhost, token, None),
- ([], {"url": localhost, "oauth_token": token}, localhost, None, token),
- ],
- ids=[
- "no_args",
- "args_private_token",
- "args_url",
- "args_url_private_token",
- "args_url_oauth_token",
- "kwargs_private_token",
- "kwargs_oauth_token",
- "kwargs_url",
- "kwargs_url_private_token",
- "kwargs_url_oauth_token",
- ],
-)
-def test_gitlab_args_kwargs(
- args, kwargs, expected_url, expected_private_token, expected_oauth_token
-):
- gl = Gitlab(*args, **kwargs)
- assert gl.url == expected_url
- assert gl.private_token == expected_private_token
- assert gl.oauth_token == expected_oauth_token
-
-
-def test_gitlab_from_config(default_config):
- config_path = default_config
- Gitlab.from_config("one", [config_path])
-
-
-def test_gitlab_subclass_from_config(default_config):
- class MyGitlab(Gitlab):
- pass
-
- config_path = default_config
- gl = MyGitlab.from_config("one", [config_path])
- assert isinstance(gl, MyGitlab)
-
-
-@pytest.mark.parametrize(
- "kwargs,expected_agent",
- [
- ({}, USER_AGENT),
- ({"user_agent": "my-package/1.0.0"}, "my-package/1.0.0"),
- ],
-)
-def test_gitlab_user_agent(kwargs, expected_agent):
- gl = Gitlab("http://localhost", **kwargs)
- assert gl.headers["User-Agent"] == expected_agent
diff --git a/tests/unit/test_gitlab_auth.py b/tests/unit/test_gitlab_auth.py
deleted file mode 100644
index 314fbed..0000000
--- a/tests/unit/test_gitlab_auth.py
+++ /dev/null
@@ -1,85 +0,0 @@
-import pytest
-import requests
-
-from gitlab import Gitlab
-
-
-def test_invalid_auth_args():
- with pytest.raises(ValueError):
- Gitlab(
- "http://localhost",
- api_version="4",
- private_token="private_token",
- oauth_token="bearer",
- )
- with pytest.raises(ValueError):
- Gitlab(
- "http://localhost",
- api_version="4",
- oauth_token="bearer",
- http_username="foo",
- http_password="bar",
- )
- with pytest.raises(ValueError):
- Gitlab(
- "http://localhost",
- api_version="4",
- private_token="private_token",
- http_password="bar",
- )
- with pytest.raises(ValueError):
- Gitlab(
- "http://localhost",
- api_version="4",
- private_token="private_token",
- http_username="foo",
- )
-
-
-def test_private_token_auth():
- gl = Gitlab("http://localhost", private_token="private_token", api_version="4")
- assert gl.private_token == "private_token"
- assert gl.oauth_token is None
- assert gl.job_token is None
- assert gl._http_auth is None
- assert "Authorization" not in gl.headers
- assert gl.headers["PRIVATE-TOKEN"] == "private_token"
- assert "JOB-TOKEN" not in gl.headers
-
-
-def test_oauth_token_auth():
- gl = Gitlab("http://localhost", oauth_token="oauth_token", api_version="4")
- assert gl.private_token is None
- assert gl.oauth_token == "oauth_token"
- assert gl.job_token is None
- assert gl._http_auth is None
- assert gl.headers["Authorization"] == "Bearer oauth_token"
- assert "PRIVATE-TOKEN" not in gl.headers
- assert "JOB-TOKEN" not in gl.headers
-
-
-def test_job_token_auth():
- gl = Gitlab("http://localhost", job_token="CI_JOB_TOKEN", api_version="4")
- assert gl.private_token is None
- assert gl.oauth_token is None
- assert gl.job_token == "CI_JOB_TOKEN"
- assert gl._http_auth is None
- assert "Authorization" not in gl.headers
- assert "PRIVATE-TOKEN" not in gl.headers
- assert gl.headers["JOB-TOKEN"] == "CI_JOB_TOKEN"
-
-
-def test_http_auth():
- gl = Gitlab(
- "http://localhost",
- private_token="private_token",
- http_username="foo",
- http_password="bar",
- api_version="4",
- )
- assert gl.private_token == "private_token"
- assert gl.oauth_token is None
- assert gl.job_token is None
- assert isinstance(gl._http_auth, requests.auth.HTTPBasicAuth)
- assert gl.headers["PRIVATE-TOKEN"] == "private_token"
- assert "Authorization" not in gl.headers
diff --git a/tests/unit/test_gitlab_http_methods.py b/tests/unit/test_gitlab_http_methods.py
deleted file mode 100644
index ba57c31..0000000
--- a/tests/unit/test_gitlab_http_methods.py
+++ /dev/null
@@ -1,406 +0,0 @@
-import pytest
-import requests
-from httmock import HTTMock, response, urlmatch
-
-from gitlab import GitlabHttpError, GitlabList, GitlabParsingError, RedirectError
-
-
-def test_build_url(gl):
- r = gl._build_url("http://localhost/api/v4")
- assert r == "http://localhost/api/v4"
- r = gl._build_url("https://localhost/api/v4")
- assert r == "https://localhost/api/v4"
- r = gl._build_url("/projects")
- assert r == "http://localhost/api/v4/projects"
-
-
-def test_http_request(gl):
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/projects", method="get")
- def resp_cont(url, request):
- headers = {"content-type": "application/json"}
- content = '[{"name": "project1"}]'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- http_r = gl.http_request("get", "/projects")
- http_r.json()
- assert http_r.status_code == 200
-
-
-def test_http_request_404(gl):
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/not_there", method="get")
- def resp_cont(url, request):
- content = {"Here is why it failed"}
- return response(404, content, {}, None, 5, request)
-
- with HTTMock(resp_cont):
- with pytest.raises(GitlabHttpError):
- gl.http_request("get", "/not_there")
-
-
-@pytest.mark.parametrize("status_code", [500, 502, 503, 504])
-def test_http_request_with_only_failures(gl, status_code):
- call_count = 0
-
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/projects", method="get")
- def resp_cont(url, request):
- nonlocal call_count
- call_count += 1
- return response(status_code, {"Here is why it failed"}, {}, None, 5, request)
-
- with HTTMock(resp_cont):
- with pytest.raises(GitlabHttpError):
- gl.http_request("get", "/projects")
-
- assert call_count == 1
-
-
-def test_http_request_with_retry_on_method_for_transient_failures(gl):
- call_count = 0
- calls_before_success = 3
-
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/projects", method="get")
- def resp_cont(url, request):
- nonlocal call_count
- call_count += 1
- status_code = 200 if call_count == calls_before_success else 500
- return response(
- status_code,
- {"Failure is the stepping stone to success"},
- {},
- None,
- 5,
- request,
- )
-
- with HTTMock(resp_cont):
- http_r = gl.http_request("get", "/projects", retry_transient_errors=True)
-
- assert http_r.status_code == 200
- assert call_count == calls_before_success
-
-
-def test_http_request_with_retry_on_class_for_transient_failures(gl_retry):
- call_count = 0
- calls_before_success = 3
-
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/projects", method="get")
- def resp_cont(url, request):
- nonlocal call_count
- call_count += 1
- status_code = 200 if call_count == calls_before_success else 500
- return response(
- status_code,
- {"Failure is the stepping stone to success"},
- {},
- None,
- 5,
- request,
- )
-
- with HTTMock(resp_cont):
- http_r = gl_retry.http_request("get", "/projects")
-
- assert http_r.status_code == 200
- assert call_count == calls_before_success
-
-
-def test_http_request_with_retry_on_class_and_method_for_transient_failures(gl_retry):
- call_count = 0
- calls_before_success = 3
-
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/projects", method="get")
- def resp_cont(url, request):
- nonlocal call_count
- call_count += 1
- status_code = 200 if call_count == calls_before_success else 500
- return response(status_code, {"Here is why it failed"}, {}, None, 5, request)
-
- with HTTMock(resp_cont):
- with pytest.raises(GitlabHttpError):
- gl_retry.http_request("get", "/projects", retry_transient_errors=False)
-
- assert call_count == 1
-
-
-def create_redirect_response(
- *, request: requests.models.PreparedRequest, http_method: str, api_path: str
-) -> requests.models.Response:
- """Create a Requests response object that has a redirect in it"""
-
- assert api_path.startswith("/")
- http_method = http_method.upper()
-
- # Create a history which contains our original request which is redirected
- history = [
- response(
- status_code=302,
- content="",
- headers={"Location": f"http://example.com/api/v4{api_path}"},
- reason="Moved Temporarily",
- request=request,
- )
- ]
-
- # Create a "prepped" Request object to be the final redirect. The redirect
- # will be a "GET" method as Requests changes the method to "GET" when there
- # is a 301/302 redirect code.
- req = requests.Request(
- method="GET",
- url=f"http://example.com/api/v4{api_path}",
- )
- prepped = req.prepare()
-
- resp_obj = response(
- status_code=200,
- content="",
- headers={},
- reason="OK",
- elapsed=5,
- request=prepped,
- )
- resp_obj.history = history
- return resp_obj
-
-
-def test_http_request_302_get_does_not_raise(gl):
- """Test to show that a redirect of a GET will not cause an error"""
-
- method = "get"
- api_path = "/user/status"
-
- @urlmatch(
- scheme="http", netloc="localhost", path=f"/api/v4{api_path}", method=method
- )
- def resp_cont(
- url: str, request: requests.models.PreparedRequest
- ) -> requests.models.Response:
- resp_obj = create_redirect_response(
- request=request, http_method=method, api_path=api_path
- )
- return resp_obj
-
- with HTTMock(resp_cont):
- gl.http_request(verb=method, path=api_path)
-
-
-def test_http_request_302_put_raises_redirect_error(gl):
- """Test to show that a redirect of a PUT will cause an error"""
-
- method = "put"
- api_path = "/user/status"
-
- @urlmatch(
- scheme="http", netloc="localhost", path=f"/api/v4{api_path}", method=method
- )
- def resp_cont(
- url: str, request: requests.models.PreparedRequest
- ) -> requests.models.Response:
- resp_obj = create_redirect_response(
- request=request, http_method=method, api_path=api_path
- )
- return resp_obj
-
- with HTTMock(resp_cont):
- with pytest.raises(RedirectError) as exc:
- gl.http_request(verb=method, path=api_path)
- error_message = exc.value.error_message
- assert "Moved Temporarily" in error_message
- assert "http://localhost/api/v4/user/status" in error_message
- assert "http://example.com/api/v4/user/status" in error_message
-
-
-def test_get_request(gl):
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/projects", method="get")
- def resp_cont(url: str, request: requests.models.PreparedRequest):
- headers = {"content-type": "application/json"}
- content = '{"name": "project1"}'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- result = gl.http_get("/projects")
- assert isinstance(result, dict)
- assert result["name"] == "project1"
-
-
-def test_get_request_raw(gl):
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/projects", method="get")
- def resp_cont(url, request):
- headers = {"content-type": "application/octet-stream"}
- content = "content"
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- result = gl.http_get("/projects")
- assert result.content.decode("utf-8") == "content"
-
-
-def test_get_request_404(gl):
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/not_there", method="get")
- def resp_cont(url, request):
- content = {"Here is why it failed"}
- return response(404, content, {}, None, 5, request)
-
- with HTTMock(resp_cont):
- with pytest.raises(GitlabHttpError):
- gl.http_get("/not_there")
-
-
-def test_get_request_invalid_data(gl):
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/projects", method="get")
- def resp_cont(url, request):
- headers = {"content-type": "application/json"}
- content = '["name": "project1"]'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- with pytest.raises(GitlabParsingError):
- gl.http_get("/projects")
-
-
-def test_list_request(gl):
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/projects", method="get")
- def resp_cont(url, request):
- headers = {"content-type": "application/json", "X-Total": 1}
- content = '[{"name": "project1"}]'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- result = gl.http_list("/projects", as_list=True)
- assert isinstance(result, list)
- assert len(result) == 1
-
- with HTTMock(resp_cont):
- result = gl.http_list("/projects", as_list=False)
- assert isinstance(result, GitlabList)
- assert len(result) == 1
-
- with HTTMock(resp_cont):
- result = gl.http_list("/projects", all=True)
- assert isinstance(result, list)
- assert len(result) == 1
-
-
-def test_list_request_404(gl):
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/not_there", method="get")
- def resp_cont(url, request):
- content = {"Here is why it failed"}
- return response(404, content, {}, None, 5, request)
-
- with HTTMock(resp_cont):
- with pytest.raises(GitlabHttpError):
- gl.http_list("/not_there")
-
-
-def test_list_request_invalid_data(gl):
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/projects", method="get")
- def resp_cont(url, request):
- headers = {"content-type": "application/json"}
- content = '["name": "project1"]'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- with pytest.raises(GitlabParsingError):
- gl.http_list("/projects")
-
-
-def test_post_request(gl):
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/projects", method="post")
- def resp_cont(url, request):
- headers = {"content-type": "application/json"}
- content = '{"name": "project1"}'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- result = gl.http_post("/projects")
- assert isinstance(result, dict)
- assert result["name"] == "project1"
-
-
-def test_post_request_404(gl):
- @urlmatch(
- scheme="http", netloc="localhost", path="/api/v4/not_there", method="post"
- )
- def resp_cont(url, request):
- content = {"Here is why it failed"}
- return response(404, content, {}, None, 5, request)
-
- with HTTMock(resp_cont):
- with pytest.raises(GitlabHttpError):
- gl.http_post("/not_there")
-
-
-def test_post_request_invalid_data(gl):
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/projects", method="post")
- def resp_cont(url, request):
- headers = {"content-type": "application/json"}
- content = '["name": "project1"]'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- with pytest.raises(GitlabParsingError):
- gl.http_post("/projects")
-
-
-def test_put_request(gl):
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/projects", method="put")
- def resp_cont(url, request):
- headers = {"content-type": "application/json"}
- content = '{"name": "project1"}'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- result = gl.http_put("/projects")
- assert isinstance(result, dict)
- assert result["name"] == "project1"
-
-
-def test_put_request_404(gl):
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/not_there", method="put")
- def resp_cont(url, request):
- content = {"Here is why it failed"}
- return response(404, content, {}, None, 5, request)
-
- with HTTMock(resp_cont):
- with pytest.raises(GitlabHttpError):
- gl.http_put("/not_there")
-
-
-def test_put_request_invalid_data(gl):
- @urlmatch(scheme="http", netloc="localhost", path="/api/v4/projects", method="put")
- def resp_cont(url, request):
- headers = {"content-type": "application/json"}
- content = '["name": "project1"]'
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- with pytest.raises(GitlabParsingError):
- gl.http_put("/projects")
-
-
-def test_delete_request(gl):
- @urlmatch(
- scheme="http", netloc="localhost", path="/api/v4/projects", method="delete"
- )
- def resp_cont(url, request):
- headers = {"content-type": "application/json"}
- content = "true"
- return response(200, content, headers, None, 5, request)
-
- with HTTMock(resp_cont):
- result = gl.http_delete("/projects")
- assert isinstance(result, requests.Response)
- assert result.json() is True
-
-
-def test_delete_request_404(gl):
- @urlmatch(
- scheme="http", netloc="localhost", path="/api/v4/not_there", method="delete"
- )
- def resp_cont(url, request):
- content = {"Here is why it failed"}
- return response(404, content, {}, None, 5, request)
-
- with HTTMock(resp_cont):
- with pytest.raises(GitlabHttpError):
- gl.http_delete("/not_there")
diff --git a/tests/unit/test_types.py b/tests/unit/test_types.py
deleted file mode 100644
index a2e5ff5..0000000
--- a/tests/unit/test_types.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2018 Gauvain Pocentek <gauvain@pocentek.net>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-from gitlab import types
-
-
-def test_gitlab_attribute_get():
- o = types.GitlabAttribute("whatever")
- assert o.get() == "whatever"
-
- o.set_from_cli("whatever2")
- assert o.get() == "whatever2"
- assert o.get_for_api() == "whatever2"
-
- o = types.GitlabAttribute()
- assert o._value is None
-
-
-def test_list_attribute_input():
- o = types.ListAttribute()
- o.set_from_cli("foo,bar,baz")
- assert o.get() == ["foo", "bar", "baz"]
-
- o.set_from_cli("foo")
- assert o.get() == ["foo"]
-
-
-def test_list_attribute_empty_input():
- o = types.ListAttribute()
- o.set_from_cli("")
- assert o.get() == []
-
- o.set_from_cli(" ")
- assert o.get() == []
-
-
-def test_list_attribute_get_for_api_from_cli():
- o = types.ListAttribute()
- o.set_from_cli("foo,bar,baz")
- assert o.get_for_api() == "foo,bar,baz"
-
-
-def test_list_attribute_get_for_api_from_list():
- o = types.ListAttribute(["foo", "bar", "baz"])
- assert o.get_for_api() == "foo,bar,baz"
-
-
-def test_list_attribute_get_for_api_from_int_list():
- o = types.ListAttribute([1, 9, 7])
- assert o.get_for_api() == "1,9,7"
-
-
-def test_list_attribute_does_not_split_string():
- o = types.ListAttribute("foo")
- assert o.get_for_api() == "foo"
-
-
-def test_lowercase_string_attribute_get_for_api():
- o = types.LowercaseStringAttribute("FOO")
- assert o.get_for_api() == "foo"
diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py
deleted file mode 100644
index dbe0838..0000000
--- a/tests/unit/test_utils.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2019 Gauvain Pocentek <gauvain@pocentek.net>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-from gitlab import utils
-
-
-def test_clean_str_id():
- src = "nothing_special"
- dest = "nothing_special"
- assert dest == utils.clean_str_id(src)
-
- src = "foo#bar/baz/"
- dest = "foo%23bar%2Fbaz%2F"
- assert dest == utils.clean_str_id(src)
-
- src = "foo%bar/baz/"
- dest = "foo%25bar%2Fbaz%2F"
- assert dest == utils.clean_str_id(src)
-
-
-def test_sanitized_url():
- src = "http://localhost/foo/bar"
- dest = "http://localhost/foo/bar"
- assert dest == utils.sanitized_url(src)
-
- src = "http://localhost/foo.bar.baz"
- dest = "http://localhost/foo%2Ebar%2Ebaz"
- assert dest == utils.sanitized_url(src)