diff --git a/ide/api/git.py b/ide/api/git.py index b7960702..3d7d62e1 100644 --- a/ide/api/git.py +++ b/ide/api/git.py @@ -61,16 +61,6 @@ def set_project_repo(request, project_id): except: pass - # Just clear the repo if none specified. - if repo == '': - project.github_repo = None - project.github_branch = None - project.github_last_sync = None - project.github_last_commit = None - project.github_hook_uuid = None - project.save() - return json_response({'exists': True, 'access': True, 'updated': True, 'branch_exists': True}) - if not ide.git.git_verify_tokens(request.user): return json_failure("No GitHub tokens on file.") @@ -153,4 +143,4 @@ def remove_hooks(repo, s): if hook.name != 'web': continue if s in hook.config['url']: - hook.delete() \ No newline at end of file + hook.delete() diff --git a/ide/api/test_git.py b/ide/api/test_git.py new file mode 100644 index 00000000..93f70536 --- /dev/null +++ b/ide/api/test_git.py @@ -0,0 +1,404 @@ +""" +Tests in this file can be run with python manage.py ide/api/ +""" + +import json +from django.http import HttpResponse +from django.test import TestCase +from mock import call, patch, MagicMock, Mock + +# These two decorators must be patched before the git module is loaded as +# decorators are applied upon module loading. + +patch('django.contrib.auth.decorators.login_required', lambda x: x).start() +patch('django.views.decorators.http.require_POST', lambda x: x).start() + +import git + + +@patch('ide.api.git.get_object_or_404') +class GithubPushPullTest(TestCase): + def setUp(self): + self.project_id = 12345 + + self.test_commit_message = 'A test commit message, for testing' + self.request = Mock() + self.request.user = "test_user" + self.request.POST = {'commit_message': self.test_commit_message} + + self.task = Mock() + self.task.task_id = 98765 + + self.project = Mock() + self.project.id = 222222 + + @patch('ide.api.git.do_github_push') + def test_github_push(self, github_push_mock, get_object_mock): + github_push_mock.delay.return_value = self.task + get_object_mock.return_value = self.project + + http_response = git.github_push(self.request, self.project_id) + + self.assertEqual(98765, json.loads(http_response.content)['task_id']) + github_push_mock.delay.assert_called_once_with(222222, self.test_commit_message) + get_object_mock.assert_called_once_with(git.Project, owner='test_user', pk=12345) + + @patch('ide.api.git.do_github_pull') + def test_github_pull(self, github_pull_mock, get_object_mock): + github_pull_mock.delay.return_value = self.task + get_object_mock.return_value = self.project + + http_response = git.github_pull(self.request, self.project_id) + + self.assertEqual(98765, json.loads(http_response.content)['task_id']) + github_pull_mock.delay.assert_called_once_with(222222) + get_object_mock.assert_called_once_with(git.Project, owner='test_user', pk=12345) + +@patch('ide.git.get_github') +@patch('ide.api.git.get_object_or_404') +class SetProjectRepoTest(TestCase): + def set_up_expected_content(self, access, updated, branch_exists, exists): + content_string = ('{{"access": {}, "success": true, "updated": {},' + ' "branch_exists": {}, "exists": {}}}').format( + *map(lambda x: str(x).lower(), + [access, updated, branch_exists, exists])) + return content_string + + def setUp(self): + self.project_id = 12345 + self.project = Mock() + self.project.github_repo = 'pebble/cloudpebble' + self.project.github_branch = 'test-branch' + self.project.github_hook_uuid = 55555 + self.project.id = 777777 + + self.request = Mock() + self.request.user = 'test-user' + self.request.POST = {'repo' : 'https://github.com/pebble/cloudpebble', + 'branch': 'test-branch', + 'auto_pull': '0', + 'auto_build': '0'} + + self.get_repo_mock = Mock() + + self.github_mock = Mock() + self.github_mock.get_repo.return_value = self.get_repo_mock + + def test_set_project_repo(self, get_object_mock, get_github_mock): + get_object_mock.return_value = self.project + get_github_mock.return_value = self.github_mock + + http_response = git.set_project_repo(self.request, self.project_id) + + expected_content = self.set_up_expected_content(True, True, True, True) + self.assertEquals(expected_content, http_response.content) + + get_github_mock.assert_called_once_with('test-user') + self.github_mock.get_repo.assert_called_once_with('pebble/cloudpebble') + get_object_mock.assert_called_once_with(git.Project, owner='test-user', pk=12345) + self.project.save.assert_called_once_with() + + def test_invalid_repo_url(self, get_object_mock, get_github_mock): + get_object_mock.return_value = self.project + + self.request.POST['repo'] = 'https://bad/repo/url.com' + + http_response = git.set_project_repo(self.request, self.project_id) + + + expected_content = '{"success": false, "error": "Invalid repo URL."}' + + self.assertEquals(expected_content, http_response.content) + get_object_mock.assert_called_once_with(git.Project, owner='test-user', pk=12345) + + def test_get_repo_exception(self, get_object_mock, get_github_mock): + get_object_mock.return_value = self.project + get_github_mock.return_value = self.github_mock + self.github_mock.get_repo.side_effect = git.UnknownObjectException('test exception','test get_repo') + + http_response = git.set_project_repo(self.request, self.project_id) + + expected_content = self.set_up_expected_content(False, False, False, False) + self.assertEquals(expected_content, http_response.content) + + get_github_mock.assert_called_once_with('test-user') + self.github_mock.get_repo.assert_called_once_with('pebble/cloudpebble') + get_object_mock.assert_called_once_with(git.Project, owner='test-user', pk=12345) + + + @patch('ide.git.git_verify_tokens') + @patch('ide.api.git.remove_hooks') + def test_remove_hooks_called(self, remove_hooks_mock, verify_tokens_mock, get_object_mock, get_github_mock): + self.project.github_repo = 'NOTpebble/NOTcloudpebble' + self.project.github_hook_uuid = 98765 + get_object_mock.return_value = self.project + get_github_mock.return_value = self.github_mock + verify_tokens_mock.return_value = False + + http_response = git.set_project_repo(self.request, self.project_id) + + expected_content = '{"success": false, "error": "No GitHub tokens on file."}' + self.assertEquals(expected_content, http_response.content) + + remove_hooks_mock.assert_called_once_with(self.get_repo_mock, 98765) + get_github_mock.assert_called_once_with('test-user') + self.github_mock.get_repo.assert_has_calls([call('pebble/cloudpebble'), call('NOTpebble/NOTcloudpebble')]) + get_object_mock.assert_called_once_with(git.Project, owner='test-user', pk=12345) + verify_tokens_mock.assert_called_once_with('test-user') + self.assertEqual(0, self.project.save.call_count) + + @patch('ide.git.git_verify_tokens') + @patch('ide.api.git.remove_hooks') + def test_git_token_verification_fails(self, remove_hooks_mock, verify_tokens_mock, get_object_mock, get_github_mock): + self.project.github_repo = 'NOTpebble/NOTcloudpebble' + self.project.github_hook_uuid = None + get_object_mock.return_value = self.project + get_github_mock.return_value = self.github_mock + verify_tokens_mock.return_value = False + + http_response = git.set_project_repo(self.request, self.project_id) + + expected_content = '{"success": false, "error": "No GitHub tokens on file."}' + self.assertEquals(expected_content, http_response.content) + + get_github_mock.assert_called_once_with('test-user') + self.github_mock.get_repo.assert_called_once_with('pebble/cloudpebble') + get_object_mock.assert_called_once_with(git.Project, owner='test-user', pk=12345) + self.assertEqual(0, remove_hooks_mock.call_count) + verify_tokens_mock.assert_called_once_with('test-user') + self.assertEqual(0, self.project.save.call_count) + + @patch('ide.git.git_verify_tokens') + @patch('ide.git.check_repo_access') + def test_check_repo_access_exception(self, check_repo_mock, verify_tokens_mock, get_object_mock, get_github_mock): + self.project.github_repo = 'NOTpebble/NOTcloudpebble' + self.project.github_hook_uuid = None + get_object_mock.return_value = self.project + get_github_mock.return_value = self.github_mock + verify_tokens_mock.return_value = True + check_repo_mock.side_effect = git.UnknownObjectException('test exception','test check_repo_access') + + http_response = git.set_project_repo(self.request, self.project_id) + + expected_content = self.set_up_expected_content(False, False, False, False) + self.assertEquals(expected_content, http_response.content) + + get_github_mock.assert_called_once_with('test-user') + self.github_mock.get_repo.assert_called_once_with('pebble/cloudpebble') + get_object_mock.assert_called_once_with(git.Project, owner='test-user', pk=12345) + verify_tokens_mock.assert_called_once_with('test-user') + check_repo_mock.assert_called_once_with('test-user','pebble/cloudpebble') + self.assertEqual(0, self.project.save.call_count) + + @patch('ide.git.git_verify_tokens') + @patch('ide.git.check_repo_access') + def test_no_repo_access(self, check_repo_mock, verify_tokens_mock, get_object_mock, get_github_mock): + self.project.github_repo = 'NOTpebble/NOTcloudpebble' + self.project.github_hook_uuid = None + get_object_mock.return_value = self.project + get_github_mock.return_value = self.github_mock + verify_tokens_mock.return_value = True + check_repo_mock.return_value = False + + http_response = git.set_project_repo(self.request, self.project_id) + + expected_content = self.set_up_expected_content(True, True, True, True) + self.assertEquals(expected_content, http_response.content) + + get_github_mock.assert_called_once_with('test-user') + self.github_mock.get_repo.assert_called_once_with('pebble/cloudpebble') + get_object_mock.assert_called_once_with(git.Project, owner='test-user', pk=12345) + verify_tokens_mock.assert_called_once_with('test-user') + check_repo_mock.assert_called_once_with('test-user','pebble/cloudpebble') + self.assertEqual(0, self.project.save.call_count) + + @patch('ide.git.git_verify_tokens') + @patch('ide.git.check_repo_access') + def test_repo_mismatch_repo_access(self, check_repo_mock, verify_tokens_mock, get_object_mock, get_github_mock): + self.project.github_repo = 'NOTpebble/NOTcloudpebble' + self.project.github_branch = 'NOT-test-branch' + self.project.github_last_sync = 'foo' + self.project.github_last_commit = 'bar' + self.project.github_hook_uuid = '' + get_object_mock.return_value = self.project + get_github_mock.return_value = self.github_mock + verify_tokens_mock.return_value = True + check_repo_mock.return_value = True + + http_response = git.set_project_repo(self.request, self.project_id) + + expected_content = self.set_up_expected_content(True, True, True, True) + self.assertEquals(expected_content, http_response.content) + + get_github_mock.assert_called_once_with('test-user') + self.github_mock.get_repo.assert_called_once_with('pebble/cloudpebble') + get_object_mock.assert_called_once_with(git.Project, owner='test-user', pk=12345) + verify_tokens_mock.assert_called_once_with('test-user') + check_repo_mock.assert_called_once_with('test-user','pebble/cloudpebble') + self.assertEqual('pebble/cloudpebble', self.project.github_repo) + self.assertEqual('test-branch', self.project.github_branch) + self.assertIsNone(self.project.github_last_sync) + self.assertIsNone(self.project.github_last_commit) + self.assertIsNone(self.project.github_hook_uuid) + self.project.save.assert_called_once_with() + + def test_repo_branch_does_not_match(self, get_object_mock, get_github_mock): + self.project.github_branch = 'NOT-test-branch' + get_object_mock.return_value = self.project + get_github_mock.return_value = self.github_mock + + http_response = git.set_project_repo(self.request, self.project_id) + + expected_content = self.set_up_expected_content(True, True, True, True) + self.assertEquals(expected_content, http_response.content) + + get_github_mock.assert_called_once_with('test-user') + self.github_mock.get_repo.assert_called_once_with('pebble/cloudpebble') + get_object_mock.assert_called_once_with(git.Project, owner='test-user', pk=12345) + self.assertEqual('test-branch', self.project.github_branch) + self.project.save.assert_called_once_with() + + def test_create_new_hook_uuid_exception(self, get_object_mock, get_github_mock): + self.project.github_hook_uuid = None + get_object_mock.return_value = self.project + get_github_mock.return_value = self.github_mock + self.request.POST['auto_pull'] = '1' + self.get_repo_mock.create_hook.side_effect = Exception('test exception raised by create_hook') + + http_response = git.set_project_repo(self.request, self.project_id) + + expected_content = '{"success": false, "error": "test exception raised by create_hook"}' + self.assertEquals(expected_content, http_response.content) + + get_github_mock.assert_called_once_with('test-user') + self.github_mock.get_repo.assert_called_once_with('pebble/cloudpebble') + get_object_mock.assert_called_once_with(git.Project, owner='test-user', pk=12345) + + self.assertIsNotNone(self.project.github_hook_uuid) + create_hook_url = 'http://example.com/ide/project/{}/github/push_hook?key={}'.format(self.project.id, + self.project.github_hook_uuid) + self.get_repo_mock.create_hook.assert_called_once_with('web', + {'url': create_hook_url, 'content_type': 'form'}, + ['push'], + True) + self.assertEqual(0, self.project.save.call_count) + + def test_create_new_uuid_hook_success(self, get_object_mock, get_github_mock): + self.project.github_hook_uuid = None + get_object_mock.return_value = self.project + get_github_mock.return_value = self.github_mock + self.request.POST['auto_pull'] = '1' + + http_response = git.set_project_repo(self.request, self.project_id) + + expected_content = self.set_up_expected_content(True, True, True, True) + self.assertEquals(expected_content, http_response.content) + + get_github_mock.assert_called_once_with('test-user') + self.github_mock.get_repo.assert_called_once_with('pebble/cloudpebble') + get_object_mock.assert_called_once_with(git.Project, owner='test-user', pk=12345) + + self.assertIsNotNone(self.project.github_hook_uuid) + create_hook_url = 'http://example.com/ide/project/{}/github/push_hook?key={}'.format(self.project.id, + self.project.github_hook_uuid) + self.get_repo_mock.create_hook.assert_called_once_with('web', + {'url': create_hook_url, 'content_type': 'form'}, + ['push'], + True) + self.project.save.assert_called_once_with() + + def test_auto_pull_false_remove_uuid_hook(self, get_object_mock, get_github_mock): + get_object_mock.return_value = self.project + get_github_mock.return_value = self.github_mock + self.project.github_hook_uuid = 98765 + + http_response = git.set_project_repo(self.request, self.project_id) + + expected_content = self.set_up_expected_content(True, True, True, True) + self.assertEquals(expected_content, http_response.content) + + get_github_mock.assert_called_once_with('test-user') + self.github_mock.get_repo.assert_called_once_with('pebble/cloudpebble') + get_object_mock.assert_called_once_with(git.Project, owner='test-user', pk=12345) + + self.assertIsNone(self.project.github_hook_uuid) + self.project.save.assert_called_once_with() + +@patch('ide.git.create_repo') +@patch('ide.api.git.get_object_or_404') +class CreateProjectRepoTest(TestCase): + def setUp(self): + self.project_id = 12345 + + self.test_exception = Exception('test create_repo exception') + + self.repo = Mock() + self.repo.full_name = 'test_full_repo_name' + self.repo.html_url = 'www.test.com/test.html' + + self.request = Mock() + self.request.user = "test_user" + self.request.POST = {'repo': 'test_repo', + 'description': 'a test description'} + + self.project = Mock() + self.project.id = 222222 + + def test_create_repo_error(self, get_object_mock, create_repo_mock): + get_object_mock.return_value = self.project + create_repo_mock.side_effect = self.test_exception + + http_response = git.create_project_repo(self.request, self.project_id) + + expected_content = '{"success": false, "error": "test create_repo exception"}' + + self.assertEquals(expected_content, http_response.content) + create_repo_mock.assert_called_once_with('test_user', 'test_repo', 'a test description') + get_object_mock.assert_called_once_with(git.Project, owner='test_user', pk=12345) + + def test_create_project_repo(self, get_object_mock, create_repo_mock): + get_object_mock.return_value = self.project + create_repo_mock.return_value = self.repo + + http_response = git.create_project_repo(self.request, self.project_id) + + expected_content = '{"repo": "www.test.com/test.html", "success": true}' + + self.assertEquals(expected_content, http_response.content) + self.assertEquals(self.repo.full_name, self.project.github_repo) + self.assertEquals('master', self.project.github_branch) + self.assertIsNone(self.project.github_last_sync) + self.assertIsNone(self.project.github_last_commit) + + self.project.save.called_once_with() + create_repo_mock.assert_called_once_with('test_user', 'test_repo', 'a test description') + get_object_mock.assert_called_once_with(git.Project, owner='test_user', pk=12345) + + +class RemoveHooksTest(TestCase): + def setUp(self): + self.mock_repo = MagicMock() + self.mock_hook = MagicMock() + self.mock_hook.name = "web" + self.mock_hook.config = {"url": ["test_string"]} + self.mock_repo.get_hooks.return_value = [self.mock_hook] + + def test_remove_hooks(self): + git.remove_hooks(self.mock_repo, "test_string") + + self.mock_repo.get_hooks.assert_called_once_with() + self.mock_hook.delete.assert_called_once_with() + + def test_remove_hook_not_web_not_deleted(self): + self.mock_hook.name = "foo" + + git.remove_hooks(self.mock_repo, "test_string") + + self.mock_repo.get_hooks.assert_called_once_with() + self.assertEqual(0, self.mock_hook.delete.call_count) + + def test_s_not_in_hook_not_deleted(self): + git.remove_hooks(self.mock_repo, "foo") + + self.mock_repo.get_hooks.assert_called_once_with() + self.assertEqual(0, self.mock_hook.delete.call_count) diff --git a/ide/run_tests.py b/ide/run_tests.py deleted file mode 100644 index 964ef0af..00000000 --- a/ide/run_tests.py +++ /dev/null @@ -1,10 +0,0 @@ -#!/ usr/bin/env python -import os -import sys - -if __name__ == "__main__": - sys.path.append("../") - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cloudpebble.settings") - - from django.core.management import execute_from_command_line - execute_from_command_line(sys.argv.append("test")) diff --git a/ide/test_git.py b/ide/test_git.py new file mode 100644 index 00000000..8ecbef0f --- /dev/null +++ b/ide/test_git.py @@ -0,0 +1,251 @@ +""" +Tests in this file can be run with python manage.py test ide/ +""" + +from django.conf import settings +from django.test import TestCase +from mock import MagicMock, Mock, patch, PropertyMock +import git + + +@patch('ide.git.git_verify_tokens') +class GitAuthCheckTest(TestCase): + def setUp(self): + self.f = Mock() + self.f.return_value = "test result" + + self.mock_user = MagicMock() + + def test_invalid_tokens(self, mock_verify_tokens): + mock_verify_tokens.return_value = False + g = git.git_auth_check(self.f) + + self.assertRaises(Exception, g, self.mock_user) + + def test_bad_credentials_expection(self, mock_verify_tokens): + mock_verify_tokens.return_value = True + self.f.side_effect = git.BadCredentialsException(None, None) + g = git.git_auth_check(self.f) + + self.assertRaises(git.BadCredentialsException, g, self.mock_user) + self.mock_user.github.delete.assert_called_once_with() + + def test_other_excpetion(self, mock_verify_tokens): + mock_verify_tokens.return_value = True + self.f.side_effect = Exception("Test exception") + g = git.git_auth_check(self.f) + + self.assertRaises(Exception, g, self.mock_user) + self.assertEqual(0, self.mock_user.github.delete.call_count) + + def test_successful_auth_check(self, mock_verify_tokens): + mock_verify_tokens.return_value = True + g = git.git_auth_check(self.f) + + self.assertEquals("test result", g(self.mock_user)) + self.assertEqual(0, self.mock_user.github.delete.call_count) + + +@patch('ide.git.urllib2.urlopen') +@patch('ide.git.json.loads') +@patch('ide.git.urllib2.Request') +class GitVerifyTokensTest(TestCase): + def setUp(self): + self.mock_user = MagicMock() + self.mock_user.github = Mock() + self.mock_user.github.token = "123456" + + self.mock_request = MagicMock() + + self.urlopen_read_result_mock = Mock() + self.urlopen_result_mock = Mock() + self.urlopen_result_mock.read.return_value = self.urlopen_read_result_mock + + def test_user_does_not_exist(self, request_mock, loads_mock, urlopen_mock): + error_raising_property = PropertyMock(side_effect=git.UserGithub.DoesNotExist(None)); + type(self.mock_user).github = error_raising_property + + self.assertFalse(git.git_verify_tokens(self.mock_user)) + + self.assertEqual(0, request_mock.call_count) + self.assertEqual(0, loads_mock.call_count) + self.assertEqual(0, urlopen_mock.call_count) + + def test_github_token_none(self, request_mock, loads_mock, urlopen_mock): + self.mock_user.github.token = None + + self.assertFalse(git.git_verify_tokens(self.mock_user)) + + self.assertEqual(0, request_mock.call_count) + self.assertEqual(0, loads_mock.call_count) + self.assertEqual(0, urlopen_mock.call_count) + + + def test_github_token_no_such_token(self, request_mock, loads_mock, urlopen_mock): + request_mock.return_value = self.mock_request + loads_mock.side_effect = git.urllib2.HTTPError("Squirrels not found", 404, None, None, None) + urlopen_mock.return_value = self.urlopen_result_mock + self.mock_user.github.delete = Mock() + + self.assertFalse(git.git_verify_tokens(self.mock_user)) + + request_mock.assert_called_once_with("https://api.github.com/applications/%s/tokens/%s" % + (settings.GITHUB_CLIENT_ID, self.mock_user.github.token)) + loads_mock.assert_called_once_with(self.urlopen_read_result_mock) + urlopen_mock.assert_called_once_with(self.mock_request) + self.urlopen_result_mock.read.assert_called_once_with() + self.mock_user.github.delete.assert_called_once_with() + + def test_other_http_error(self, request_mock, loads_mock, urlopen_mock): + request_mock.return_value = self.mock_request + loads_mock.side_effect = git.urllib2.HTTPError("Squirrels are black, not red", 406, None, None, None) + urlopen_mock.return_value = self.urlopen_result_mock + self.mock_user.github.delete = Mock() + + self.assertFalse(git.git_verify_tokens(self.mock_user)) + + request_mock.assert_called_once_with("https://api.github.com/applications/%s/tokens/%s" % + (settings.GITHUB_CLIENT_ID, self.mock_user.github.token)) + loads_mock.assert_called_once_with(self.urlopen_read_result_mock) + urlopen_mock.assert_called_once_with(self.mock_request) + self.urlopen_result_mock.read.assert_called_once_with() + self.assertEqual(0, self.mock_user.github.delete.call_count) + + def test_github_token_verified(self, request_mock, loads_mock, urlopen_mock): + request_mock.return_value = self.mock_request + urlopen_mock.return_value = self.urlopen_result_mock + + self.assertTrue(git.git_verify_tokens(self.mock_user)) + + request_mock.assert_called_once_with("https://api.github.com/applications/%s/tokens/%s" % + (settings.GITHUB_CLIENT_ID, self.mock_user.github.token)) + loads_mock.assert_called_once_with(self.urlopen_read_result_mock) + urlopen_mock.assert_called_once_with(self.mock_request) + self.urlopen_result_mock.read.assert_called_once_with() + + +class GetGithubTest(TestCase): + def setUp(self): + self.mock_user = Mock() + self.mock_user.github = Mock() + self.mock_user.github.token = "12345" + + @patch('ide.git.Github') + def test_get_github_basic(self, mock_github): + test_result = git.get_github(self.mock_user) + mock_github.assert_called_once_with( + "12345", + client_id=settings.GITHUB_CLIENT_ID, + client_secret=settings.GITHUB_CLIENT_SECRET) + + +class GetGithubTest(TestCase): + def setUp(self): + self.mock_user = Mock() + self.mock_user.github = Mock() + self.mock_user.github.token = "12345" + + @patch('ide.git.Github') + def test_get_github_basic(self, mock_github): + test_result = git.get_github(self.mock_user) + mock_github.assert_called_once_with( + "12345", + client_id=settings.GITHUB_CLIENT_ID, + client_secret=settings.GITHUB_CLIENT_SECRET) + + +@patch('ide.git.get_github') +class CheckRepoAccessTest(TestCase): + def setUp(self): + self.mock_repo = MagicMock() + + self.mock_github = MagicMock(spec=git.Github) + self.mock_github.get_repo.return_value = self.mock_repo + + self.mock_user = Mock() + self.mock_user.github = Mock() + self.mock_user.github.username = "FuzzyWuzzy" + + self.repo_name = "bear/bear_code" + + def test_repo_access(self, mock_get_github): + mock_get_github.return_value = self.mock_github + self.mock_repo.has_in_collaborators.return_value = True + + self.assertTrue(git.check_repo_access(self.mock_user, self.repo_name)) + + mock_get_github.assert_called_once_with(self.mock_user) + self.mock_github.get_repo.assert_called_once_with(self.repo_name) + + named_user = self.mock_repo.has_in_collaborators.call_args[0][0] + self.assertEquals(self.mock_user.github.username, named_user._login) + self.assertIsNone(named_user._requester) + self.assertFalse(named_user._CompletableGithubObject__completed) + + def test_no_repo_access(self, mock_get_github): + mock_get_github.return_value = self.mock_github + self.mock_repo.has_in_collaborators.return_value = False + + self.assertFalse(git.check_repo_access(self.mock_user, self.repo_name)) + + mock_get_github.assert_called_once_with(self.mock_user) + self.mock_github.get_repo.assert_called_once_with(self.repo_name) + + named_user = self.mock_repo.has_in_collaborators.call_args[0][0] + self.assertEquals(self.mock_user.github.username, named_user._login) + self.assertIsNone(named_user._requester) + self.assertFalse(named_user._CompletableGithubObject__completed) + + def test_get_repo_error(self, mock_get_github): + mock_get_github.return_value = self.mock_github + self.mock_github.get_repo.side_effect = git.UnknownObjectException(404, "Not Found") + + self.assertRaises(git.UnknownObjectException, + git.check_repo_access, + self.mock_user, + self.repo_name) + + mock_get_github.assert_called_once_with(self.mock_user) + self.mock_github.get_repo.assert_called_once_with(self.repo_name) + self.assertEqual(0, self.mock_repo.call_count) + + +class UrlToReposTest(TestCase): + def test_basic_url_to_repo(self): + """ + Tests that a simple repo url is correctly recognized. + """ + username, reponame = git.url_to_repo("https://github.com/pebble/cloudpebble") + self.assertEqual("pebble", username) + self.assertEqual("cloudpebble", reponame) + + def test_strange_url_to_repo(self): + """ + Tests that a non-standard repo url is correctly recognized. + """ + username, reponame = git.url_to_repo("git://github.com:foo/bar.git") + self.assertEqual("foo", username) + self.assertEqual("bar", reponame) + + + def test_bad_url_to_repo(self): + """ + Tests that a entirely different url returns None. + """ + self.assertEqual(None, git.url_to_repo("http://www.cuteoverload.com")) + + +@patch('ide.git.get_github') +@patch('ide.git.git_verify_tokens') +class CreateRepoTest(TestCase): + def test_expected_call(self, mock_verify_tokens, mock_get_github): + mock_user = MagicMock() + mock_github = Mock() + mock_github.get_user = Mock(return_value=mock_user) + mock_get_github.return_value = mock_github + + self.assertTrue(git.create_repo("user", "repo", "description")) + + mock_verify_tokens.assert_called_once_with("user") + mock_get_github.assert_called_once_with("user") + mock_user.create_repo.assert_called_once_with("repo", description="description", auto_init=True) diff --git a/ide/tests.py b/ide/tests.py deleted file mode 100644 index 4ed77355..00000000 --- a/ide/tests.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Tests in this file can be run with run_tests.py -""" - -from django.test import TestCase -import git - - -class UrlToReposTest(TestCase): - def test_basic_url_to_repo(self): - """ - Tests that a simple repo url is correctly recognized. - """ - username, reponame = git.url_to_repo("https://github.com/pebble/cloudpebble") - self.assertEqual("pebble", username) - self.assertEqual("cloudpebble", reponame) - - def test_strange_url_to_repo(self): - """ - Tests that a non-standard repo url is correctly recognized. - """ - username, reponame = git.url_to_repo("git://github.com:foo/bar.git") - self.assertEqual("foo", username) - self.assertEqual("bar", reponame) - - - def test_bad_url_to_repo(self): - """ - Tests that a entirely different url returns None. - """ - self.assertEqual(None, git.url_to_repo("http://www.cuteoverload.com")) diff --git a/run_all_tests.sh b/run_all_tests.sh new file mode 100755 index 00000000..d19e3127 --- /dev/null +++ b/run_all_tests.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +python manage.py test