class GitLabOAuthTests(TestCase): fixtures = ['eric', 'test_data'] repo_response_data = { 'lfs_enabled': True, 'request_access_enabled': False, 'approvals_before_merge': 0, 'forks_count': 12, 'only_allow_merge_if_all_discussions_are_resolved': False, 'container_registry_enabled': True, 'web_url': 'https://gitlab.com/testorga/testrepo', 'owner': { 'username': '******', 'web_url': 'https://gitlab.com/testorga', 'name': 'Test Orga', 'state': 'active', 'avatar_url': 'https://secure.gravatar.com/avatar/test', 'id': 42, }, 'wiki_enabled': True, 'id': 42, 'merge_requests_enabled': True, 'archived': False, 'snippets_enabled': True, 'http_url_to_repo': 'https://gitlab.com/testorga/testrepo.git', 'namespace': { 'kind': 'user', 'name': 'Test Orga', 'parent_id': None, 'plan': 'early_adopter', 'path': 'testorga', 'id': 42, 'full_path': 'testorga', }, 'star_count': 1, '_links': { 'repo_branches': 'http://gitlab.com/api/v4/projects/42/repository/branches', 'merge_requests': 'http://gitlab.com/api/v4/projects/42/merge_requests', 'self': 'http://gitlab.com/api/v4/projects/42', 'labels': 'http://gitlab.com/api/v4/projects/42/labels', 'members': 'http://gitlab.com/api/v4/projects/42/members', 'events': 'http://gitlab.com/api/v4/projects/42/events', 'issues': 'http://gitlab.com/api/v4/projects/42/issues', }, 'resolve_outdated_diff_discussions': False, 'issues_enabled': True, 'path_with_namespace': 'testorga/testrepo', 'ci_config_path': None, 'shared_with_groups': [], 'description': 'Test Repo', 'default_branch': 'master', 'visibility': 'public', 'ssh_url_to_repo': '[email protected]:testorga/testrepo.git', 'public_jobs': True, 'path': 'testrepo', 'import_status': 'none', 'only_allow_merge_if_pipeline_succeeds': False, 'open_issues_count': 0, 'last_activity_at': '2017-11-28T14:21:17.570Z', 'name': 'testrepo', 'printing_merge_request_link_enabled': True, 'name_with_namespace': 'testorga / testrepo', 'created_at': '2017-11-27T19:19:30.906Z', 'shared_runners_enabled': True, 'creator_id': 389803, 'avatar_url': None, 'permissions': { 'group_access': None, 'project_access': { 'notification_level': 3, 'access_level': 40, }, }, 'tag_list': [], 'jobs_enabled': True, } group_response_data = { 'id': 1, 'name': 'Test Orga', 'path': 'testorga', 'description': 'An interesting group', 'visibility': 'public', 'lfs_enabled': True, 'avatar_url': 'https://secure.gravatar.com/avatar/test', 'web_url': 'https://gitlab.com/groups/testorga', 'request_access_enabled': False, 'full_name': 'Test Orga', 'full_path': 'testorga', 'parent_id': None, } def setUp(self): self.client.login(username='******', password='******') self.user = User.objects.get(pk=1) self.project = Project.objects.get(slug='pip') self.project.repo = 'https://gitlab.com/testorga/testrepo' self.project.save() self.org = RemoteOrganization.objects.create(slug='testorga', json='') self.privacy = self.project.version_privacy_level self.service = GitLabService(user=self.user, account=None) self.external_version = get(Version, project=self.project, type=EXTERNAL) self.external_build = get(Build, project=self.project, version=self.external_version) self.integration = get(GitLabWebhook, project=self.project, provider_data={'id': '999999999'}) self.provider_data = [{ 'id': 1084320, 'url': 'https://readthedocs.io/api/v2/webhook/test/99999999/', }] def get_private_repo_data(self): """Manipulate repo response data to get private repo data.""" data = self.repo_response_data.copy() data.update({ 'visibility': 'private', }) return data def test_make_project_pass(self): with mock.patch('readthedocs.oauth.services.gitlab.GitLabService.is_owned_by') as m: # yapf: disable m.return_value = True repo = self.service.create_repository( self.repo_response_data, organization=self.org, privacy=self.privacy, ) self.assertIsInstance(repo, RemoteRepository) self.assertEqual(repo.name, 'testrepo') self.assertEqual(repo.full_name, 'testorga / testrepo') self.assertEqual(repo.description, 'Test Repo') self.assertEqual( repo.avatar_url, 'https://secure.gravatar.com/avatar/test', ) self.assertIn(self.user, repo.users.all()) self.assertEqual(repo.organization, self.org) self.assertEqual( repo.clone_url, 'https://gitlab.com/testorga/testrepo.git', ) self.assertEqual(repo.ssh_url, '[email protected]:testorga/testrepo.git') self.assertEqual(repo.html_url, 'https://gitlab.com/testorga/testrepo') self.assertTrue(repo.admin) self.assertFalse(repo.private) def test_make_private_project_fail(self): repo = self.service.create_repository( self.get_private_repo_data(), organization=self.org, privacy=self.privacy, ) self.assertIsNone(repo) def test_make_private_project_success(self): repo = self.service.create_repository( self.get_private_repo_data(), organization=self.org, privacy=constants.PRIVATE, ) self.assertIsInstance(repo, RemoteRepository) self.assertTrue(repo.private, True) def test_make_organization(self): org = self.service.create_organization(self.group_response_data) self.assertIsInstance(org, RemoteOrganization) self.assertEqual(org.slug, 'testorga') self.assertEqual(org.name, 'Test Orga') self.assertEqual( org.avatar_url, 'https://secure.gravatar.com/avatar/test', ) self.assertEqual(org.url, 'https://gitlab.com/testorga') @override_settings(DEFAULT_PRIVACY_LEVEL='private') def test_make_private_project(self): """ Test ability to import ``public`` repositories under ``private`` level. """ data = self.repo_response_data.copy() data['visibility'] = 'public' with mock.patch('readthedocs.oauth.services.gitlab.GitLabService.is_owned_by') as m: # yapf: disable m.return_value = True repo = self.service.create_repository(data, organization=self.org) self.assertIsNotNone(repo) @mock.patch('readthedocs.oauth.services.gitlab.log') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService.get_session') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService._get_repo_id') def test_send_build_status_successful(self, repo_id, session, mock_logger): session().post.return_value.status_code = 201 repo_id().return_value = '9999' success = self.service.send_build_status(self.external_build, self.external_build.commit, BUILD_STATUS_SUCCESS) self.assertTrue(success) mock_logger.info.assert_called_with( "GitLab commit status created for project: %s, commit status: %s", self.project, BUILD_STATUS_SUCCESS) @mock.patch('readthedocs.oauth.services.gitlab.log') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService.get_session') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService._get_repo_id') def test_send_build_status_404_error(self, repo_id, session, mock_logger): session().post.return_value.status_code = 404 repo_id().return_value = '9999' success = self.service.send_build_status(self.external_build, self.external_build.commit, BUILD_STATUS_SUCCESS) self.assertFalse(success) mock_logger.info.assert_called_with( 'GitLab project does not exist or user does not have ' 'permissions: project=%s', self.project) @mock.patch('readthedocs.oauth.services.gitlab.log') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService.get_session') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService._get_repo_id') def test_send_build_status_value_error(self, repo_id, session, mock_logger): session().post.side_effect = ValueError repo_id().return_value = '9999' success = self.service.send_build_status(self.external_build, self.external_build.commit, BUILD_STATUS_SUCCESS) self.assertFalse(success) mock_logger.exception.assert_called_with( 'GitLab commit status creation failed for project: %s', self.project, ) @mock.patch('readthedocs.oauth.services.gitlab.log') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService.get_session') def test_setup_webhook_successful(self, session, mock_logger): session().post.return_value.status_code = 201 session().post.return_value.json.return_value = {} success, _ = self.service.setup_webhook(self.project, self.integration) self.integration.refresh_from_db() self.assertTrue(success) self.assertIsNotNone(self.integration.secret) mock_logger.info.assert_called_with( "GitLab webhook creation successful for project: %s", self.project, ) @mock.patch('readthedocs.oauth.services.gitlab.log') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService.get_session') def test_setup_webhook_404_error(self, session, mock_logger): session().post.return_value.status_code = 404 success, _ = self.service.setup_webhook(self.project, self.integration) self.integration.refresh_from_db() self.assertFalse(success) self.assertIsNone(self.integration.secret) mock_logger.info.assert_called_with( 'Gitlab project does not exist or user does not have ' 'permissions: project=%s', self.project, ) @mock.patch('readthedocs.oauth.services.gitlab.log') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService.get_session') def test_setup_webhook_value_error(self, session, mock_logger): session().post.side_effect = ValueError success = self.service.setup_webhook(self.project, self.integration) self.integration.refresh_from_db() self.assertIsNone(self.integration.secret) mock_logger.exception.assert_called_with( 'GitLab webhook creation failed for project: %s', self.project, ) @mock.patch('readthedocs.oauth.services.gitlab.log') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService.get_session') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService._get_repo_id') def test_update_webhook_successful(self, repo_id, session, mock_logger): repo_id.return_value = '9999' session().put.return_value.status_code = 200 session().put.return_value.json.return_value = {} success, _ = self.service.update_webhook(self.project, self.integration) self.integration.refresh_from_db() self.assertTrue(success) self.assertIsNotNone(self.integration.secret) mock_logger.info.assert_called_with( "GitLab webhook update successful for project: %s", self.project, ) @mock.patch('readthedocs.oauth.services.gitlab.GitLabService.get_session') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService.setup_webhook' ) @mock.patch('readthedocs.oauth.services.gitlab.GitLabService._get_repo_id') def test_update_webhook_404_error(self, repo_id, setup_webhook, session): repo_id.return_value = '9999' session().put.return_value.status_code = 404 self.service.update_webhook(self.project, self.integration) setup_webhook.assert_called_once_with(self.project, self.integration) @mock.patch('readthedocs.oauth.services.gitlab.GitLabService.get_session') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService.setup_webhook' ) @mock.patch('readthedocs.oauth.services.gitlab.GitLabService._get_repo_id') def test_update_webhook_no_provider_data(self, repo_id, setup_webhook, session): self.integration.provider_data = None self.integration.save() repo_id.return_value = '9999' session().put.side_effect = AttributeError self.service.update_webhook(self.project, self.integration) setup_webhook.assert_called_once_with(self.project, self.integration) @mock.patch('readthedocs.oauth.services.gitlab.log') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService.get_session') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService._get_repo_id') def test_update_webhook_value_error(self, repo_id, session, mock_logger): repo_id.return_value = '9999' session().put.side_effect = ValueError self.service.update_webhook(self.project, self.integration) self.integration.refresh_from_db() self.assertIsNone(self.integration.secret) mock_logger.exception.assert_called_with( 'GitLab webhook update failed for project: %s', self.project, ) @mock.patch('readthedocs.oauth.services.gitlab.log') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService.get_session') def test_get_provider_data_successful(self, session, mock_logger): self.integration.provider_data = {} self.integration.save() webhook_data = self.provider_data rtd_webhook_url = 'https://{domain}{path}'.format( domain=settings.PRODUCTION_DOMAIN, path=reverse( 'api_webhook', kwargs={ 'project_slug': self.project.slug, 'integration_pk': self.integration.pk, }, )) webhook_data[0]["url"] = rtd_webhook_url session().get.return_value.status_code = 200 session().get.return_value.json.return_value = webhook_data self.service.get_provider_data(self.project, self.integration) self.integration.refresh_from_db() self.assertEqual(self.integration.provider_data, webhook_data[0]) mock_logger.info.assert_called_with( 'GitLab integration updated with provider data for project: %s', self.project, ) @mock.patch('readthedocs.oauth.services.gitlab.log') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService.get_session') def test_get_provider_data_404_error(self, session, mock_logger): self.integration.provider_data = {} self.integration.save() session().get.return_value.status_code = 404 self.service.get_provider_data(self.project, self.integration) self.integration.refresh_from_db() self.assertEqual(self.integration.provider_data, {}) mock_logger.info.assert_called_with( 'GitLab project does not exist or user does not have ' 'permissions: project=%s', self.project, ) @mock.patch('readthedocs.oauth.services.gitlab.log') @mock.patch('readthedocs.oauth.services.gitlab.GitLabService.get_session') def test_get_provider_data_attribute_error(self, session, mock_logger): self.integration.provider_data = {} self.integration.save() session().get.side_effect = AttributeError self.service.get_provider_data(self.project, self.integration) self.integration.refresh_from_db() self.assertEqual(self.integration.provider_data, {}) mock_logger.exception.assert_called_with( 'GitLab webhook Listing failed for project: %s', self.project, )
class GitLabOAuthTests(TestCase): fixtures = ['eric', 'test_data'] repo_response_data = { 'lfs_enabled': True, 'request_access_enabled': False, 'approvals_before_merge': 0, 'forks_count': 12, 'only_allow_merge_if_all_discussions_are_resolved': False, 'container_registry_enabled': True, 'web_url': 'https://gitlab.com/testorga/testrepo', 'owner': { 'username': '******', 'web_url': 'https://gitlab.com/testorga', 'name': 'Test Orga', 'state': 'active', 'avatar_url': 'https://secure.gravatar.com/avatar/test', 'id': 42, }, 'wiki_enabled': True, 'id': 42, 'merge_requests_enabled': True, 'archived': False, 'snippets_enabled': True, 'http_url_to_repo': 'https://gitlab.com/testorga/testrepo.git', 'namespace': { 'kind': 'user', 'name': 'Test Orga', 'parent_id': None, 'plan': 'early_adopter', 'path': 'testorga', 'id': 42, 'full_path': 'testorga', }, 'star_count': 1, '_links': { 'repo_branches': 'http://gitlab.com/api/v4/projects/42/repository/branches', 'merge_requests': 'http://gitlab.com/api/v4/projects/42/merge_requests', 'self': 'http://gitlab.com/api/v4/projects/42', 'labels': 'http://gitlab.com/api/v4/projects/42/labels', 'members': 'http://gitlab.com/api/v4/projects/42/members', 'events': 'http://gitlab.com/api/v4/projects/42/events', 'issues': 'http://gitlab.com/api/v4/projects/42/issues', }, 'resolve_outdated_diff_discussions': False, 'issues_enabled': True, 'path_with_namespace': 'testorga/testrepo', 'ci_config_path': None, 'shared_with_groups': [], 'description': 'Test Repo', 'default_branch': 'master', 'visibility': 'public', 'ssh_url_to_repo': '[email protected]:testorga/testrepo.git', 'public_jobs': True, 'path': 'testrepo', 'import_status': 'none', 'only_allow_merge_if_pipeline_succeeds': False, 'open_issues_count': 0, 'last_activity_at': '2017-11-28T14:21:17.570Z', 'name': 'testrepo', 'printing_merge_request_link_enabled': True, 'name_with_namespace': 'testorga / testrepo', 'created_at': '2017-11-27T19:19:30.906Z', 'shared_runners_enabled': True, 'creator_id': 389803, 'avatar_url': None, 'permissions': { 'group_access': None, 'project_access': { 'notification_level': 3, 'access_level': 40, }, }, 'tag_list': [], 'jobs_enabled': True, } group_response_data = { 'id': 1, 'name': 'Test Orga', 'path': 'testorga', 'description': 'An interesting group', 'visibility': 'public', 'lfs_enabled': True, 'avatar_url': 'https://secure.gravatar.com/avatar/test', 'web_url': 'https://gitlab.com/groups/testorga', 'request_access_enabled': False, 'full_name': 'Test Orga', 'full_path': 'testorga', 'parent_id': None, } def setUp(self): self.client.login(username='******', password='******') self.user = User.objects.get(pk=1) self.project = Project.objects.get(slug='pip') self.org = RemoteOrganization.objects.create(slug='testorga', json='') self.privacy = self.project.version_privacy_level self.service = GitLabService(user=self.user, account=None) def get_private_repo_data(self): """Manipulate repo response data to get private repo data.""" data = self.repo_response_data.copy() data.update({ 'visibility': 'private', }) return data def test_make_project_pass(self): with mock.patch('readthedocs.oauth.services.gitlab.GitLabService.is_owned_by') as m: # yapf: disable m.return_value = True repo = self.service.create_repository( self.repo_response_data, organization=self.org, privacy=self.privacy) self.assertIsInstance(repo, RemoteRepository) self.assertEqual(repo.name, 'testrepo') self.assertEqual(repo.full_name, 'testorga / testrepo') self.assertEqual(repo.description, 'Test Repo') self.assertEqual( repo.avatar_url, 'https://secure.gravatar.com/avatar/test', ) self.assertIn(self.user, repo.users.all()) self.assertEqual(repo.organization, self.org) self.assertEqual( repo.clone_url, 'https://gitlab.com/testorga/testrepo.git', ) self.assertEqual(repo.ssh_url, '[email protected]:testorga/testrepo.git') self.assertEqual(repo.html_url, 'https://gitlab.com/testorga/testrepo') self.assertTrue(repo.admin) self.assertFalse(repo.private) def test_make_private_project_fail(self): repo = self.service.create_repository( self.get_private_repo_data(), organization=self.org, privacy=self.privacy) self.assertIsNone(repo) def test_make_private_project_success(self): repo = self.service.create_repository( self.get_private_repo_data(), organization=self.org, privacy=constants.PRIVATE) self.assertIsInstance(repo, RemoteRepository) self.assertTrue(repo.private, True) def test_make_organization(self): org = self.service.create_organization(self.group_response_data) self.assertIsInstance(org, RemoteOrganization) self.assertEqual(org.slug, 'testorga') self.assertEqual(org.name, 'Test Orga') self.assertEqual( org.avatar_url, 'https://secure.gravatar.com/avatar/test', ) self.assertEqual(org.url, 'https://gitlab.com/testorga')
class GitLabOAuthTests(TestCase): fixtures = ['eric', 'test_data'] repo_response_data = { 'lfs_enabled': True, 'request_access_enabled': False, 'approvals_before_merge': 0, 'forks_count': 12, 'only_allow_merge_if_all_discussions_are_resolved': False, 'container_registry_enabled': True, 'web_url': 'https://gitlab.com/testorga/testrepo', 'owner': { 'username': '******', 'web_url': 'https://gitlab.com/testorga', 'name': 'Test Orga', 'state': 'active', 'avatar_url': 'https://secure.gravatar.com/avatar/test', 'id': 42, }, 'wiki_enabled': True, 'id': 42, 'merge_requests_enabled': True, 'archived': False, 'snippets_enabled': True, 'http_url_to_repo': 'https://gitlab.com/testorga/testrepo.git', 'namespace': { 'kind': 'user', 'name': 'Test Orga', 'parent_id': None, 'plan': 'early_adopter', 'path': 'testorga', 'id': 42, 'full_path': 'testorga', }, 'star_count': 1, '_links': { 'repo_branches': 'http://gitlab.com/api/v4/projects/42/repository/branches', 'merge_requests': 'http://gitlab.com/api/v4/projects/42/merge_requests', 'self': 'http://gitlab.com/api/v4/projects/42', 'labels': 'http://gitlab.com/api/v4/projects/42/labels', 'members': 'http://gitlab.com/api/v4/projects/42/members', 'events': 'http://gitlab.com/api/v4/projects/42/events', 'issues': 'http://gitlab.com/api/v4/projects/42/issues', }, 'resolve_outdated_diff_discussions': False, 'issues_enabled': True, 'path_with_namespace': 'testorga/testrepo', 'ci_config_path': None, 'shared_with_groups': [], 'description': 'Test Repo', 'default_branch': 'master', 'visibility': 'public', 'ssh_url_to_repo': '[email protected]:testorga/testrepo.git', 'public_jobs': True, 'path': 'testrepo', 'import_status': 'none', 'only_allow_merge_if_pipeline_succeeds': False, 'open_issues_count': 0, 'last_activity_at': '2017-11-28T14:21:17.570Z', 'name': 'testrepo', 'printing_merge_request_link_enabled': True, 'name_with_namespace': 'testorga / testrepo', 'created_at': '2017-11-27T19:19:30.906Z', 'shared_runners_enabled': True, 'creator_id': 389803, 'avatar_url': None, 'permissions': { 'group_access': None, 'project_access': { 'notification_level': 3, 'access_level': 40, }, }, 'tag_list': [], 'jobs_enabled': True, } group_response_data = { 'id': 1, 'name': 'Test Orga', 'path': 'testorga', 'description': 'An interesting group', 'visibility': 'public', 'lfs_enabled': True, 'avatar_url': 'https://secure.gravatar.com/avatar/test', 'web_url': 'https://gitlab.com/groups/testorga', 'request_access_enabled': False, 'full_name': 'Test Orga', 'full_path': 'testorga', 'parent_id': None, } def setUp(self): self.client.login(username='******', password='******') self.user = User.objects.get(pk=1) self.project = Project.objects.get(slug='pip') self.org = RemoteOrganization.objects.create(slug='testorga', json='') self.privacy = self.project.version_privacy_level self.service = GitLabService(user=self.user, account=None) def get_private_repo_data(self): """Manipulate repo response data to get private repo data.""" data = self.repo_response_data.copy() data.update({ 'visibility': 'private', }) return data def test_make_project_pass(self): with mock.patch('readthedocs.oauth.services.gitlab.GitLabService.is_owned_by') as m: # yapf: disable m.return_value = True repo = self.service.create_repository( self.repo_response_data, organization=self.org, privacy=self.privacy, ) self.assertIsInstance(repo, RemoteRepository) self.assertEqual(repo.name, 'testrepo') self.assertEqual(repo.full_name, 'testorga / testrepo') self.assertEqual(repo.description, 'Test Repo') self.assertEqual( repo.avatar_url, 'https://secure.gravatar.com/avatar/test', ) self.assertIn(self.user, repo.users.all()) self.assertEqual(repo.organization, self.org) self.assertEqual( repo.clone_url, 'https://gitlab.com/testorga/testrepo.git', ) self.assertEqual(repo.ssh_url, '[email protected]:testorga/testrepo.git') self.assertEqual(repo.html_url, 'https://gitlab.com/testorga/testrepo') self.assertTrue(repo.admin) self.assertFalse(repo.private) def test_make_private_project_fail(self): repo = self.service.create_repository( self.get_private_repo_data(), organization=self.org, privacy=self.privacy, ) self.assertIsNone(repo) def test_make_private_project_success(self): repo = self.service.create_repository( self.get_private_repo_data(), organization=self.org, privacy=constants.PRIVATE, ) self.assertIsInstance(repo, RemoteRepository) self.assertTrue(repo.private, True) def test_make_organization(self): org = self.service.create_organization(self.group_response_data) self.assertIsInstance(org, RemoteOrganization) self.assertEqual(org.slug, 'testorga') self.assertEqual(org.name, 'Test Orga') self.assertEqual( org.avatar_url, 'https://secure.gravatar.com/avatar/test', ) self.assertEqual(org.url, 'https://gitlab.com/testorga') @override_settings(DEFAULT_PRIVACY_LEVEL='private') def test_make_private_project(self): """ Test ability to import ``public`` repositories under ``private`` level. """ data = self.repo_response_data.copy() data['visibility'] = 'public' with mock.patch('readthedocs.oauth.services.gitlab.GitLabService.is_owned_by') as m: # yapf: disable m.return_value = True repo = self.service.create_repository(data, organization=self.org) self.assertIsNotNone(repo) def test_setup_webhook(self): success, response = self.service.setup_webhook(self.project) self.assertFalse(success) self.assertIsNone(response)