From 58863abb4e2ddcc1d2ee42fb00013cf9f68c95b7 Mon Sep 17 00:00:00 2001 From: Jerry Sun Date: Thu, 1 Jun 2017 16:20:14 -0400 Subject: [PATCH 01/62] Convert test_comment_detail.py to pytest [OSF-8082] --- .../comments/views/test_comment_detail.py | 1274 +++++++++-------- 1 file changed, 695 insertions(+), 579 deletions(-) diff --git a/api_tests/comments/views/test_comment_detail.py b/api_tests/comments/views/test_comment_detail.py index f5fd146dade..7dd8486f49f 100644 --- a/api_tests/comments/views/test_comment_detail.py +++ b/api_tests/comments/views/test_comment_detail.py @@ -1,9 +1,8 @@ +import pytest + import mock from urlparse import urlparse -import pytest -from nose.tools import * # flake8: noqa - from framework.auth import core from framework.guid.model import Guid @@ -11,6 +10,7 @@ from api.base.settings import osf_settings from api_tests import utils as test_utils from tests.base import ApiTestCase +from addons.wiki.tests.factories import NodeWikiFactory from osf_tests.factories import ( ProjectFactory, AuthUserFactory, @@ -18,16 +18,85 @@ RegistrationFactory, PrivateLinkFactory, ) -from addons.wiki.tests.factories import NodeWikiFactory - +@pytest.mark.django_db class CommentDetailMixin(object): - def setUp(self): - super(CommentDetailMixin, self).setUp() - self.user = AuthUserFactory() - self.contributor = AuthUserFactory() - self.non_contributor = AuthUserFactory() + @pytest.fixture() + def user(self): + return AuthUserFactory() + + @pytest.fixture() + def contributor(self): + return AuthUserFactory() + + @pytest.fixture() + def non_contributor(self): + return AuthUserFactory() + + # private_project_with_comments + @pytest.fixture() + def private_project(self): + raise NotImplementedError + + @pytest.fixture() + def comment(self): + raise NotImplementedError + + @pytest.fixture() + def private_url(self): + raise NotImplementedError + + @pytest.fixture() + def payload(self): + raise NotImplementedError + + # public_project_with_comments + @pytest.fixture() + def public_project(self): + raise NotImplementedError + + @pytest.fixture() + def public_comment(self): + raise NotImplementedError + + @pytest.fixture() + def public_comment_reply(self): + raise NotImplementedError + + @pytest.fixture() + def public_url(self): + raise NotImplementedError + + @pytest.fixture() + def public_comment_payload(self): + raise NotImplementedError + + # registration_with_comments + @pytest.fixture() + def registration(self): + raise NotImplementedError + + @pytest.fixture() + def registration_url(self): + raise NotImplementedError + + @pytest.fixture() + def registration_comment(self): + raise NotImplementedError + + @pytest.fixture() + def comment_url(self): + raise NotImplementedError + + @pytest.fixture() + def registration_comment_reply(self): + raise NotImplementedError + + @pytest.fixture() + def replies_url(self): + raise NotImplementedError + def _set_up_payload(self, target_id, content='test', has_content=True): payload = { @@ -44,675 +113,722 @@ def _set_up_payload(self, target_id, content='test', has_content=True): payload['data']['attributes']['content'] = content return payload - def _set_up_private_project_with_comment(self): - raise NotImplementedError - - def _set_up_public_project_with_comment(self): - raise NotImplementedError - - def _set_up_registration_with_comment(self): - raise NotImplementedError - - def test_private_node_logged_in_contributor_can_view_comment(self): - self._set_up_private_project_with_comment() - res = self.app.get(self.private_url, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal(self.comment._id, res.json['data']['id']) - assert_equal(self.comment.content, res.json['data']['attributes']['content']) - - def test_private_node_logged_in_non_contributor_cannot_view_comment(self): - self._set_up_private_project_with_comment() - res = self.app.get(self.private_url, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - assert_equal(res.json['errors'][0]['detail'], 'You do not have permission to perform this action.') - - def test_private_node_logged_out_user_cannot_view_comment(self): - self._set_up_private_project_with_comment() - res = self.app.get(self.private_url, expect_errors=True) - assert_equal(res.status_code, 401) - assert_equal(res.json['errors'][0]['detail'], 'Authentication credentials were not provided.') - - def test_private_node_user_with_private_link_can_see_comment(self): - self._set_up_private_project_with_comment() + def test_private_node_comments_related_auth(self, app, user, contributor, non_contributor, comment, private_url): + # test_private_node_logged_in_contributor_can_view_comment + res = app.get(private_url, auth=user.auth) + assert res.status_code == 200 + assert comment._id == res.json['data']['id'] + assert comment.content == res.json['data']['attributes']['content'] + + # def test_private_node_logged_in_non_contributor_cannot_view_comment + res = app.get(private_url, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + + # def test_private_node_logged_out_user_cannot_view_comment + res = app.get(private_url, expect_errors=True) + assert res.status_code == 401 + assert res.json['errors'][0]['detail'] == 'Authentication credentials were not provided.' + + def test_private_node_user_with_private_and_anonymous_link_misc(self, app, private_project, comment): + # def test_private_node_user_with_private_link_can_see_comment private_link = PrivateLinkFactory(anonymous=False) - private_link.nodes.add(self.private_project) + private_link.nodes.add(private_project) private_link.save() - res = self.app.get('/{}comments/{}/'.format(API_BASE, self.comment._id), {'view_only': private_link.key}, expect_errors=True) - assert_equal(res.status_code, 200) - assert_equal(self.comment._id, res.json['data']['id']) - assert_equal(self.comment.content, res.json['data']['attributes']['content']) + res = app.get('/{}comments/{}/'.format(API_BASE, comment._id), {'view_only': private_link.key}, expect_errors=True) + assert res.status_code == 200 + assert comment._id == res.json['data']['id'] + assert comment.content == res.json['data']['attributes']['content'] - def test_private_node_user_with_anonymous_link_cannot_see_commenter_info(self): - self._set_up_private_project_with_comment() - private_link = PrivateLinkFactory(anonymous=True) - private_link.nodes.add(self.private_project) - private_link.save() - res = self.app.get('/{}comments/{}/'.format(API_BASE, self.comment._id), {'view_only': private_link.key}) - assert_equal(res.status_code, 200) - assert_equal(self.comment._id, res.json['data']['id']) - assert_equal(self.comment.content, res.json['data']['attributes']['content']) - assert_not_in('user', res.json['data']['relationships']) - - def test_private_node_user_with_anonymous_link_cannot_see_mention_info(self): - self._set_up_private_project_with_comment() - self.comment.content = 'test with [@username](userlink) and @mention' - self.comment.save() + # test_private_node_user_with_anonymous_link_cannot_see_commenter_info private_link = PrivateLinkFactory(anonymous=True) - private_link.nodes.add(self.private_project) + private_link.nodes.add(private_project) private_link.save() - res = self.app.get('/{}comments/{}/'.format(API_BASE, self.comment._id), {'view_only': private_link.key}) - assert_equal(res.status_code, 200) - assert_equal(self.comment._id, res.json['data']['id']) - assert_equal( 'test with @A User and @mention', res.json['data']['attributes']['content']) - - def test_public_node_logged_in_contributor_can_view_comment(self): - self._set_up_public_project_with_comment() - res = self.app.get(self.public_url, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal(self.public_comment._id, res.json['data']['id']) - assert_equal(self.public_comment.content, res.json['data']['attributes']['content']) - - def test_public_node_logged_in_non_contributor_can_view_comment(self): - self._set_up_public_project_with_comment() - res = self.app.get(self.public_url, auth=self.non_contributor.auth) - assert_equal(res.status_code, 200) - assert_equal(self.public_comment._id, res.json['data']['id']) - assert_equal(self.public_comment.content, res.json['data']['attributes']['content']) - - def test_public_node_logged_out_user_can_view_comment(self): - self._set_up_public_project_with_comment() - res = self.app.get(self.public_url) - assert_equal(res.status_code, 200) - assert_equal(self.public_comment._id, res.json['data']['id']) - assert_equal(self.public_comment.content, res.json['data']['attributes']['content']) - - def test_public_node_user_with_private_link_can_view_comment(self): - self._set_up_public_project_with_comment() + res = app.get('/{}comments/{}/'.format(API_BASE, comment._id), {'view_only': private_link.key}) + assert res.status_code == 200 + assert comment._id == res.json['data']['id'] + assert comment.content == res.json['data']['attributes']['content'] + assert 'user' not in res.json['data']['relationships'] + + # test_private_node_user_with_anonymous_link_cannot_see_mention_info + comment.content = 'test with [@username](userlink) and @mention' + comment.save() + res = app.get('/{}comments/{}/'.format(API_BASE, comment._id), {'view_only': private_link.key}) + assert res.status_code == 200 + assert comment._id == res.json['data']['id'] + assert 'test with @A User and @mention' == res.json['data']['attributes']['content'] + + def test_public_node_comment_auth_misc(self, app, user, non_contributor, public_project, public_url, public_comment, registration_comment, comment_url): + # test_public_node_logged_in_contributor_can_view_comment + res = app.get(public_url, auth=user.auth) + assert res.status_code == 200 + assert public_comment._id == res.json['data']['id'] + assert public_comment.content == res.json['data']['attributes']['content'] + + # test_public_node_logged_in_non_contributor_can_view_comment + res = app.get(public_url, auth=non_contributor.auth) + assert res.status_code == 200 + assert public_comment._id == res.json['data']['id'] + assert public_comment.content == res.json['data']['attributes']['content'] + + # test_public_node_logged_out_user_can_view_comment + res = app.get(public_url) + assert res.status_code == 200 + assert public_comment._id == res.json['data']['id'] + assert public_comment.content == res.json['data']['attributes']['content'] + + # test_registration_logged_in_contributor_can_view_comment + res = app.get(comment_url, auth=user.auth) + assert res.status_code == 200 + assert registration_comment._id == res.json['data']['id'] + assert registration_comment.content == res.json['data']['attributes']['content'] + + # test_public_node_user_with_private_link_can_view_comment private_link = PrivateLinkFactory(anonymous=False) - private_link.nodes.add(self.public_project) + private_link.nodes.add(public_project) private_link.save() - res = self.app.get('/{}comments/{}/'.format(API_BASE, self.public_comment._id), {'view_only': private_link.key}, expect_errors=True) - assert_equal(self.public_comment._id, res.json['data']['id']) - assert_equal(self.public_comment.content, res.json['data']['attributes']['content']) - - def test_registration_logged_in_contributor_can_view_comment(self): - self._set_up_registration_with_comment() - res = self.app.get(self.comment_url, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal(self.registration_comment._id, res.json['data']['id']) - assert_equal(self.registration_comment.content, res.json['data']['attributes']['content']) - - def test_comment_has_user_link(self): - self._set_up_public_project_with_comment() - res = self.app.get(self.public_url) - url = res.json['data']['relationships']['user']['links']['related']['href'] - expected_url = '/{}users/{}/'.format(API_BASE, self.user._id) - assert_equal(res.status_code, 200) - assert_equal(urlparse(url).path, expected_url) - - def test_comment_has_node_link(self): - self._set_up_public_project_with_comment() - res = self.app.get(self.public_url) - url = res.json['data']['relationships']['node']['links']['related']['href'] - expected_url = '/{}nodes/{}/'.format(API_BASE, self.public_project._id) - assert_equal(res.status_code, 200) - assert_equal(urlparse(url).path, expected_url) - - def test_registration_comment_has_node_link(self): - self._set_up_registration_with_comment() - res = self.app.get(self.comment_url, auth=self.user.auth) + res = app.get('/{}comments/{}/'.format(API_BASE, public_comment._id), {'view_only': private_link.key}, expect_errors=True) + assert public_comment._id == res.json['data']['id'] + assert public_comment.content == res.json['data']['attributes']['content'] + + def test_comment_has_multiple_links(self, app, user, public_url, public_project, public_comment, public_comment_reply, comment_url, registration): + res = app.get(public_url) + assert res.status_code == 200 + # test_comment_has_user_link + url_user = res.json['data']['relationships']['user']['links']['related']['href'] + expected_url = '/{}users/{}/'.format(API_BASE, user._id) + assert urlparse(url_user).path == expected_url + + # test_comment_has_node_link + url_node = res.json['data']['relationships']['node']['links']['related']['href'] + expected_url = '/{}nodes/{}/'.format(API_BASE, public_project._id) + assert urlparse(url_node).path == expected_url + + # test_comment_has_replies_link + url_replies = res.json['data']['relationships']['replies']['links']['related']['href'] + uri = test_utils.urlparse_drop_netloc(url_replies) + res_uri = app.get(uri) + assert res_uri.status_code == 200 + assert res_uri.json['data'][0]['type'] == 'comments' + + # test_comment_has_reports_link + url_reports = res.json['data']['relationships']['reports']['links']['related']['href'] + expected_url = '/{}comments/{}/reports/'.format(API_BASE, public_comment._id) + assert urlparse(url_reports).path == expected_url + + # test_registration_comment_has_node_link + res = app.get(comment_url, auth=user.auth) url = res.json['data']['relationships']['node']['links']['related']['href'] - expected_url = '/{}registrations/{}/'.format(API_BASE, self.registration._id) - assert_equal(res.status_code, 200) - assert_equal(urlparse(url).path, expected_url) - - def test_comment_has_replies_link(self): - self._set_up_public_project_with_comment() - res = self.app.get(self.public_url) - assert_equal(res.status_code, 200) - url = res.json['data']['relationships']['replies']['links']['related']['href'] - uri = test_utils.urlparse_drop_netloc(url) - res = self.app.get(uri) - assert_equal(res.status_code, 200) - assert_equal(res.json['data'][0]['type'], 'comments') - - def test_comment_has_reports_link(self): - self._set_up_public_project_with_comment() - res = self.app.get(self.public_url) - url = res.json['data']['relationships']['reports']['links']['related']['href'] - expected_url = '/{}comments/{}/reports/'.format(API_BASE, self.public_comment._id) - assert_equal(res.status_code, 200) - assert_equal(urlparse(url).path, expected_url) - - def test_private_node_only_logged_in_contributor_commenter_can_update_comment(self): - self._set_up_private_project_with_comment() - res = self.app.put_json_api(self.private_url, self.payload, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal(self.payload['data']['attributes']['content'], res.json['data']['attributes']['content']) - - def test_private_node_logged_in_non_contributor_cannot_update_comment(self): - self._set_up_private_project_with_comment() - res = self.app.put_json_api(self.private_url, self.payload, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - assert_equal(res.json['errors'][0]['detail'], 'You do not have permission to perform this action.') - - def test_private_node_logged_out_user_cannot_update_comment(self): - self._set_up_private_project_with_comment() - res = self.app.put_json_api(self.private_url, self.payload, expect_errors=True) - assert_equal(res.status_code, 401) - assert_equal(res.json['errors'][0]['detail'], 'Authentication credentials were not provided.') - - def test_public_node_only_contributor_commenter_can_update_comment(self): - self._set_up_public_project_with_comment() - res = self.app.put_json_api(self.public_url, self.public_comment_payload, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal(self.public_comment_payload['data']['attributes']['content'], res.json['data']['attributes']['content']) - - def test_public_node_contributor_cannot_update_other_users_comment(self): - self._set_up_public_project_with_comment() - res = self.app.put_json_api(self.public_url, self.public_comment_payload, auth=self.contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - assert_equal(res.json['errors'][0]['detail'], 'You do not have permission to perform this action.') - - def test_public_node_non_contributor_cannot_update_other_users_comment(self): - self._set_up_public_project_with_comment() - res = self.app.put_json_api(self.public_url, self.public_comment_payload, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - assert_equal(res.json['errors'][0]['detail'], 'You do not have permission to perform this action.') - - def test_public_node_logged_out_user_cannot_update_comment(self): - self._set_up_public_project_with_comment() - res = self.app.put_json_api(self.public_url, self.public_comment_payload, expect_errors=True) - assert_equal(res.status_code, 401) - assert_equal(res.json['errors'][0]['detail'], 'Authentication credentials were not provided.') - - def test_update_comment_cannot_exceed_max_length(self): - self._set_up_private_project_with_comment() + expected_url = '/{}registrations/{}/'.format(API_BASE, registration._id) + assert res.status_code == 200 + assert urlparse(url).path == expected_url + + def test_private_node_comment_auth_misc(self, app, user, non_contributor, private_url, payload): + # test_private_node_only_logged_in_contributor_commenter_can_update_comment + res = app.put_json_api(private_url, payload, auth=user.auth) + assert res.status_code == 200 + assert payload['data']['attributes']['content'] == res.json['data']['attributes']['content'] + + # test_private_node_logged_in_non_contributor_cannot_update_comment + res = app.put_json_api(private_url, payload, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + + # test_private_node_logged_out_user_cannot_update_comment + res = app.put_json_api(private_url, payload, expect_errors=True) + assert res.status_code == 401 + assert res.json['errors'][0]['detail'] == 'Authentication credentials were not provided.' + + def test_public_node_comment_auth_misc(self, app, user, contributor, non_contributor, public_url, public_comment, public_comment_payload): + # test_public_node_only_contributor_commenter_can_update_comment + res = app.put_json_api(public_url, public_comment_payload, auth=user.auth) + assert res.status_code == 200 + assert public_comment_payload['data']['attributes']['content'] == res.json['data']['attributes']['content'] + + # test_public_node_contributor_cannot_update_other_users_comment + res = app.put_json_api(public_url, public_comment_payload, auth=contributor.auth, expect_errors=True) + assert res.status_code == 403 + assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + + # test_public_node_non_contributor_cannot_update_other_users_comment + res = app.put_json_api(public_url, public_comment_payload, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + + # test_public_node_logged_out_user_cannot_update_comment + res = app.put_json_api(public_url, public_comment_payload, expect_errors=True) + assert res.status_code == 401 + assert res.json['errors'][0]['detail'] == 'Authentication credentials were not provided.' + + def test_update_comment_misc(self, app, user, private_url, comment): + # test_update_comment_cannot_exceed_max_length content = ('c' * (osf_settings.COMMENT_MAXLENGTH + 3)) - payload = self._set_up_payload(self.comment._id, content=content) - res = self.app.put_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], + payload = self._set_up_payload(comment._id, content=content) + res = app.put_json_api(private_url, payload, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert (res.json['errors'][0]['detail'] == 'Ensure this field has no more than {} characters.'.format(str(osf_settings.COMMENT_MAXLENGTH))) - def test_update_comment_cannot_be_empty(self): - self._set_up_private_project_with_comment() - payload = self._set_up_payload(self.comment._id, content='') - res = self.app.put_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], 'This field may not be blank.') - - def test_private_node_only_logged_in_contributor_commenter_can_delete_comment(self): - self._set_up_private_project_with_comment() - res = self.app.delete_json_api(self.private_url, auth=self.user.auth) - assert_equal(res.status_code, 204) - - def test_private_node_only_logged_in_contributor_commenter_can_delete_own_reply(self): - self._set_up_private_project_with_comment() - reply_target = Guid.load(self.comment._id) - reply = CommentFactory(node=self.private_project, target=reply_target, user=self.user) + # test_update_comment_cannot_be_empty + payload = self._set_up_payload(comment._id, content='') + res = app.put_json_api(private_url, payload, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'This field may not be blank.' + + def test_private_node_only_logged_in_contributor_commenter_can_delete_comment(self, app, user, private_url): + res = app.delete_json_api(private_url, auth=user.auth) + assert res.status_code == 204 + + def test_private_node_only_logged_in_contributor_commenter_can_delete_own_reply(self, app, user, private_project, comment): + reply_target = Guid.load(comment._id) + reply = CommentFactory(node=private_project, target=reply_target, user=user) reply_url = '/{}comments/{}/'.format(API_BASE, reply._id) - res = self.app.delete_json_api(reply_url, auth=self.user.auth) - assert_equal(res.status_code, 204) + res = app.delete_json_api(reply_url, auth=user.auth) + assert res.status_code == 204 - def test_private_node_only_logged_in_contributor_commenter_can_undelete_own_reply(self): - self._set_up_private_project_with_comment() - reply_target = Guid.load(self.comment._id) - reply = CommentFactory(node=self.private_project, target=reply_target, user=self.user) + def test_private_node_only_logged_in_contributor_commenter_can_undelete_own_reply(self, app, user, private_project, comment): + reply_target = Guid.load(comment._id) + reply = CommentFactory(node=private_project, target=reply_target, user=user) reply_url = '/{}comments/{}/'.format(API_BASE, reply._id) reply.is_deleted = True reply.save() payload = self._set_up_payload(reply._id, has_content=False) - res = self.app.patch_json_api(reply_url, payload, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_false(res.json['data']['attributes']['deleted']) - assert_equal(res.json['data']['attributes']['content'], reply.content) - - def test_private_node_contributor_cannot_delete_other_users_comment(self): - self._set_up_private_project_with_comment() - res = self.app.delete_json_api(self.private_url, auth=self.contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - assert_equal(res.json['errors'][0]['detail'], 'You do not have permission to perform this action.') - - def test_private_node_non_contributor_cannot_delete_comment(self): - self._set_up_private_project_with_comment() - res = self.app.delete_json_api(self.private_url, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - assert_equal(res.json['errors'][0]['detail'], 'You do not have permission to perform this action.') - - def test_private_node_logged_out_user_cannot_delete_comment(self): - self._set_up_private_project_with_comment() - res = self.app.delete_json_api(self.private_url, expect_errors=True) - assert_equal(res.status_code, 401) - - def test_private_node_user_cannot_delete_already_deleted_comment(self): - self._set_up_private_project_with_comment() - self.comment.is_deleted = True - self.comment.save() - res = self.app.delete_json_api(self.private_url, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], 'Comment already deleted.') - - def test_private_node_only_logged_in_contributor_commenter_can_undelete_comment(self): - self._set_up_private_project_with_comment() - self.comment.is_deleted = True - self.comment.save() - url = '/{}comments/{}/'.format(API_BASE, self.comment._id) - payload = self._set_up_payload(self.comment._id, has_content=False) - res = self.app.patch_json_api(url, payload, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_false(res.json['data']['attributes']['deleted']) - assert_equal(res.json['data']['attributes']['content'], self.comment.content) - - def test_private_node_contributor_cannot_undelete_other_users_comment(self): - self._set_up_private_project_with_comment() - self.comment.is_deleted = True - self.comment.save() - url = '/{}comments/{}/'.format(API_BASE, self.comment._id) - payload = self._set_up_payload(self.comment._id, has_content=False) - res = self.app.patch_json_api(url, payload, auth=self.contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - - def test_private_node_non_contributor_cannot_undelete_comment(self): - self._set_up_private_project_with_comment() - self.comment.is_deleted = True - self.comment.save() - url = '/{}comments/{}/'.format(API_BASE, self.comment._id) - payload = self._set_up_payload(self.comment._id, has_content=False) - res = self.app.patch_json_api(url, payload, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - - def test_private_node_logged_out_user_cannot_undelete_comment(self): - self._set_up_private_project_with_comment() - self.comment.is_deleted = True - self.comment.save() - url = '/{}comments/{}/'.format(API_BASE, self.comment._id) - payload = self._set_up_payload(self.comment._id, has_content=False) - res = self.app.patch_json_api(url, payload, expect_errors=True) - assert_equal(res.status_code, 401) - - def test_public_node_only_logged_in_contributor_commenter_can_delete_comment(self): - self._set_up_public_project_with_comment() - res = self.app.delete_json_api(self.public_url, auth=self.user.auth) - assert_equal(res.status_code, 204) - - def test_public_node_contributor_cannot_delete_other_users_comment(self): - self._set_up_public_project_with_comment() - res = self.app.delete_json_api(self.public_url, auth=self.contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - assert_equal(res.json['errors'][0]['detail'], 'You do not have permission to perform this action.') - - def test_public_node_non_contributor_cannot_delete_other_users_comment(self): - self._set_up_public_project_with_comment() - res = self.app.delete_json_api(self.public_url, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - assert_equal(res.json['errors'][0]['detail'], 'You do not have permission to perform this action.') - - def test_public_node_logged_out_user_cannot_delete_comment(self): - self._set_up_public_project_with_comment() - res = self.app.delete_json_api(self.public_url, expect_errors=True) - assert_equal(res.status_code, 401) - assert_equal(res.json['errors'][0]['detail'], 'Authentication credentials were not provided.') - - def test_public_node_user_cannot_delete_already_deleted_comment(self): - self._set_up_public_project_with_comment() - self.public_comment.is_deleted = True - self.public_comment.save() - res = self.app.delete_json_api(self.public_url, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], 'Comment already deleted.') - - def test_private_node_only_logged_in_commenter_can_view_deleted_comment(self): - self._set_up_private_project_with_comment() - self.comment.is_deleted = True - self.comment.save() - url = '/{}comments/{}/'.format(API_BASE, self.comment._id) - res = self.app.get(url, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal(res.json['data']['attributes']['content'], self.comment.content) - - def test_private_node_contributor_cannot_see_other_users_deleted_comment(self): - self._set_up_private_project_with_comment() - self.comment.is_deleted = True - self.comment.save() - url = '/{}comments/{}/'.format(API_BASE, self.comment._id) - res = self.app.get(url, auth=self.contributor.auth) - assert_equal(res.status_code, 200) - assert_is_none(res.json['data']['attributes']['content']) - - def test_private_node_logged_out_user_cannot_see_deleted_comment(self): - self._set_up_private_project_with_comment() - self.comment.is_deleted = True - self.comment.save() - url = '/{}comments/{}/'.format(API_BASE, self.comment._id) - res = self.app.get(url, expect_errors=True) - assert_equal(res.status_code, 401) - assert_equal(res.json['errors'][0]['detail'], 'Authentication credentials were not provided.') - - def test_private_node_view_only_link_user_cannot_see_deleted_comment(self): - self._set_up_private_project_with_comment() - self.comment.is_deleted = True - self.comment.save() + res = app.patch_json_api(reply_url, payload, auth=user.auth) + assert res.status_code == 200 + assert not res.json['data']['attributes']['deleted'] + assert res.json['data']['attributes']['content'] == reply.content + + def test_private_node_cannot_delete_comment_situation(self, app, user, contributor, non_contributor, private_url, comment): + # def test_private_node_contributor_cannot_delete_other_users_comment(self): + res = app.delete_json_api(private_url, auth=contributor.auth, expect_errors=True) + assert res.status_code == 403 + assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + + # def test_private_node_non_contributor_cannot_delete_comment(self): + res = app.delete_json_api(private_url, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + + # def test_private_node_logged_out_user_cannot_delete_comment(self): + res = app.delete_json_api(private_url, expect_errors=True) + assert res.status_code == 401 + + # def test_private_node_user_cannot_delete_already_deleted_comment(self): + comment.is_deleted = True + comment.save() + res = app.delete_json_api(private_url, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'Comment already deleted.' + + def test_private_node_only_logged_in_contributor_commenter_can_undelete_comment(self, app, user, comment): + comment.is_deleted = True + comment.save() + url = '/{}comments/{}/'.format(API_BASE, comment._id) + payload = self._set_up_payload(comment._id, has_content=False) + res = app.patch_json_api(url, payload, auth=user.auth) + assert res.status_code == 200 + assert not res.json['data']['attributes']['deleted'] + assert res.json['data']['attributes']['content'] == comment.content + + def test_private_node_cannot_undelete_comment_situation(self, app, user, contributor, non_contributor, comment): + comment.is_deleted = True + comment.save() + url = '/{}comments/{}/'.format(API_BASE, comment._id) + payload = self._set_up_payload(comment._id, has_content=False) + + # test_private_node_contributor_cannot_undelete_other_users_comment + res = app.patch_json_api(url, payload, auth=contributor.auth, expect_errors=True) + assert res.status_code == 403 + + # test_private_node_non_contributor_cannot_undelete_comment + res = app.patch_json_api(url, payload, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + + # test_private_node_logged_out_user_cannot_undelete_comment + res = app.patch_json_api(url, payload, expect_errors=True) + assert res.status_code == 401 + + def test_public_node_only_logged_in_contributor_commenter_can_delete_comment(self, app, user, public_url): + res = app.delete_json_api(public_url, auth=user.auth) + assert res.status_code == 204 + + def test_public_node_cannot_delete_comment_situations(self, app, user, contributor, non_contributor, public_url, public_comment): + # test_public_node_contributor_cannot_delete_other_users_comment + res = app.delete_json_api(public_url, auth=contributor.auth, expect_errors=True) + assert res.status_code == 403 + assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + + # test_public_node_non_contributor_cannot_delete_other_users_comment + res = app.delete_json_api(public_url, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + + # test_public_node_logged_out_user_cannot_delete_comment + res = app.delete_json_api(public_url, expect_errors=True) + assert res.status_code == 401 + assert res.json['errors'][0]['detail'] == 'Authentication credentials were not provided.' + + # test_public_node_user_cannot_delete_already_deleted_comment + public_comment.is_deleted = True + public_comment.save() + res = app.delete_json_api(public_url, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'Comment already deleted.' + + def test_private_node_deleted_comment_auth_misc(self, app, user, contributor, comment, private_project): + comment.is_deleted = True + comment.save() + + # test_private_node_only_logged_in_commenter_can_view_deleted_comment + url = '/{}comments/{}/'.format(API_BASE, comment._id) + res = app.get(url, auth=user.auth) + assert res.status_code == 200 + assert res.json['data']['attributes']['content'] == comment.content + + # test_private_node_contributor_cannot_see_other_users_deleted_comment + url = '/{}comments/{}/'.format(API_BASE, comment._id) + res = app.get(url, auth=contributor.auth) + assert res.status_code == 200 + assert res.json['data']['attributes']['content'] is None + # test_private_node_logged_out_user_cannot_see_deleted_comment + url = '/{}comments/{}/'.format(API_BASE, comment._id) + res = app.get(url, expect_errors=True) + assert res.status_code == 401 + assert res.json['errors'][0]['detail'] == 'Authentication credentials were not provided.' + + # test_private_node_view_only_link_user_cannot_see_deleted_comment private_link = PrivateLinkFactory(anonymous=False) - private_link.nodes.add(self.private_project) + private_link.nodes.add(private_project) private_link.save() - res = self.app.get('/{}comments/{}/'.format(API_BASE, self.comment._id), {'view_only': private_link.key}, expect_errors=True) - assert_equal(res.status_code, 200) - assert_is_none(res.json['data']['attributes']['content']) - - def test_private_node_anonymous_view_only_link_user_cannot_see_deleted_comment(self): - self._set_up_private_project_with_comment() - self.comment.is_deleted = True - self.comment.save() + res = app.get('/{}comments/{}/'.format(API_BASE, comment._id), {'view_only': private_link.key}, expect_errors=True) + assert res.status_code == 200 + assert res.json['data']['attributes']['content'] is None + # test_private_node_anonymous_view_only_link_user_cannot_see_deleted_comment anonymous_link = PrivateLinkFactory(anonymous=True) - anonymous_link.nodes.add(self.private_project) + anonymous_link.nodes.add(private_project) anonymous_link.save() - res = self.app.get('/{}comments/{}/'.format(API_BASE, self.comment._id), {'view_only': anonymous_link.key}, expect_errors=True) - assert_equal(res.status_code, 200) - assert_is_none(res.json['data']['attributes']['content']) - - def test_public_node_only_logged_in_commenter_can_view_deleted_comment(self): - self._set_up_public_project_with_comment() - self.public_comment.is_deleted = True - self.public_comment.save() - url = '/{}comments/{}/'.format(API_BASE, self.public_comment._id) - res = self.app.get(url, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal(res.json['data']['attributes']['content'], self.public_comment.content) - - def test_public_node_contributor_cannot_view_other_users_deleted_comment(self): - self._set_up_public_project_with_comment() - self.public_comment.is_deleted = True - self.public_comment.save() - url = '/{}comments/{}/'.format(API_BASE, self.public_comment._id) - res = self.app.get(url, auth=self.contributor.auth) - assert_equal(res.status_code, 200) - assert_is_none(res.json['data']['attributes']['content']) - - def test_public_node_non_contributor_cannot_view_other_users_deleted_comment(self): - self._set_up_public_project_with_comment() - self.public_comment.is_deleted = True - self.public_comment.save() - url = '/{}comments/{}/'.format(API_BASE, self.public_comment._id) - res = self.app.get(url, auth=self.non_contributor.auth) - assert_equal(res.status_code, 200) - assert_is_none(res.json['data']['attributes']['content']) - - def test_public_node_logged_out_user_cannot_view_deleted_comments(self): - self._set_up_public_project_with_comment() - self.public_comment.is_deleted = True - self.public_comment.save() - url = '/{}comments/{}/'.format(API_BASE, self.public_comment._id) - res = self.app.get(url) - assert_equal(res.status_code, 200) - assert_is_none(res.json['data']['attributes']['content']) - - def test_public_node_view_only_link_user_cannot_see_deleted_comment(self): - self._set_up_public_project_with_comment() - self.public_comment.is_deleted = True - self.public_comment.save() + res = app.get('/{}comments/{}/'.format(API_BASE, comment._id), {'view_only': anonymous_link.key}, expect_errors=True) + assert res.status_code == 200 + assert res.json['data']['attributes']['content'] is None + + def test_public_node_deleted_comments_auth_misc(self, app, user, contributor, non_contributor, public_project, public_comment): + public_comment.is_deleted = True + public_comment.save() + url = '/{}comments/{}/'.format(API_BASE, public_comment._id) + + # test_public_node_only_logged_in_commenter_can_view_deleted_comment + res = app.get(url, auth=user.auth) + assert res.status_code == 200 + assert res.json['data']['attributes']['content'] == public_comment.content + + # test_public_node_contributor_cannot_view_other_users_deleted_comment + res = app.get(url, auth=contributor.auth) + assert res.status_code == 200 + assert res.json['data']['attributes']['content'] is None + + # test_public_node_non_contributor_cannot_view_other_users_deleted_comment + res = app.get(url, auth=non_contributor.auth) + assert res.status_code == 200 + assert res.json['data']['attributes']['content'] is None + + # test_public_node_logged_out_user_cannot_view_deleted_comments + res = app.get(url) + assert res.status_code == 200 + assert res.json['data']['attributes']['content'] is None + + # test_public_node_view_only_link_user_cannot_see_deleted_comment private_link = PrivateLinkFactory(anonymous=False) - private_link.nodes.add(self.public_project) + private_link.nodes.add(public_project) private_link.save() - res = self.app.get('/{}comments/{}/'.format(API_BASE, self.public_comment._id), {'view_only': private_link.key}, expect_errors=True) - assert_equal(res.status_code, 200) - assert_is_none(res.json['data']['attributes']['content']) - - -class TestCommentDetailView(CommentDetailMixin, ApiTestCase): - - def _set_up_private_project_with_comment(self): - self.private_project = ProjectFactory.create(is_public=False, creator=self.user) - self.private_project.add_contributor(self.contributor, save=True) - self.comment = CommentFactory(node=self.private_project, user=self.user) - self.private_url = '/{}comments/{}/'.format(API_BASE, self.comment._id) - self.payload = self._set_up_payload(self.comment._id) - - def _set_up_public_project_with_comment(self): - self.public_project = ProjectFactory.create(is_public=True, creator=self.user) - self.public_project.add_contributor(self.contributor, save=True) - self.public_comment = CommentFactory(node=self.public_project, user=self.user) - reply_target = Guid.load(self.public_comment._id) - self.public_comment_reply = CommentFactory(node=self.public_project, target=reply_target, user=self.user) - self.public_url = '/{}comments/{}/'.format(API_BASE, self.public_comment._id) - self.public_comment_payload = self._set_up_payload(self.public_comment._id) - - def _set_up_registration_with_comment(self): - self.registration = RegistrationFactory(creator=self.user) - self.registration_url = '/{}registrations/{}/'.format(API_BASE, self.registration._id) - self.registration_comment = CommentFactory(node=self.registration, user=self.user) - self.comment_url = '/{}comments/{}/'.format(API_BASE, self.registration_comment._id) - reply_target = Guid.load(self.registration_comment._id) - self.registration_comment_reply = CommentFactory(node=self.registration, target=reply_target, user=self.user) - self.replies_url = '/{}registrations/{}/comments/?filter[target]={}'.format(API_BASE, self.registration._id, self.registration_comment._id) - - def test_comment_has_target_link_with_correct_type(self): - self._set_up_public_project_with_comment() - res = self.app.get(self.public_url) + res = app.get('/{}comments/{}/'.format(API_BASE, public_comment._id), {'view_only': private_link.key}, expect_errors=True) + assert res.status_code == 200 + assert res.json['data']['attributes']['content'] is None + + +class TestCommentDetailView(CommentDetailMixin): + + # private_project_with_comments + @pytest.fixture() + def private_project(self, user, contributor): + private_project = ProjectFactory.create(is_public=False, creator=user) + private_project.add_contributor(contributor, save=True) + return private_project + + @pytest.fixture() + def comment(self, user, private_project): + return CommentFactory(node=private_project, user=user) + + @pytest.fixture() + def private_url(self, comment): + return '/{}comments/{}/'.format(API_BASE, comment._id) + + @pytest.fixture() + def payload(self, comment): + return self._set_up_payload(comment._id) + + # public_project_with_comments + @pytest.fixture() + def public_project(self, user, contributor): + public_project = ProjectFactory.create(is_public=True, creator=user) + public_project.add_contributor(contributor, save=True) + return public_project + + @pytest.fixture() + def public_comment(self, user, public_project): + return CommentFactory(node=public_project, user=user) + + @pytest.fixture() + def public_comment_reply(self, user, public_comment, public_project): + reply_target = Guid.load(public_comment._id) + return CommentFactory(node=public_project, target=reply_target, user=user) + + @pytest.fixture() + def public_url(self, public_comment): + return '/{}comments/{}/'.format(API_BASE, public_comment._id) + + @pytest.fixture() + def public_comment_payload(self, public_comment): + return self._set_up_payload(public_comment._id) + + # registration_with_comments + @pytest.fixture() + def registration(self, user): + return RegistrationFactory(creator=user) + + @pytest.fixture() + def registration_url(self, registration): + return '/{}registrations/{}/'.format(API_BASE, registration._id) + + @pytest.fixture() + def registration_comment(self, user, registration): + return CommentFactory(node=registration, user=user) + + @pytest.fixture() + def comment_url(self, registration_comment): + return '/{}comments/{}/'.format(API_BASE, registration_comment._id) + + @pytest.fixture() + def registration_comment_reply(self, user, registration, registration_comment): + reply_target = Guid.load(registration_comment._id) + return CommentFactory(node=registration, target=reply_target, user=user) + + @pytest.fixture() + def replies_url(self, registration, registration_comment): + return '/{}registrations/{}/comments/?filter[target]={}'.format(API_BASE, registration._id, registration_comment._id) + + + def test_comment_has_target_link_with_correct_type(self, app, public_url, public_project): + res = app.get(public_url) url = res.json['data']['relationships']['target']['links']['related']['href'] - expected_url = '/{}nodes/{}/'.format(API_BASE, self.public_project._id) + expected_url = '/{}nodes/{}/'.format(API_BASE, public_project._id) target_type = res.json['data']['relationships']['target']['links']['related']['meta']['type'] expected_type = 'nodes' - assert_equal(res.status_code, 200) - assert_equal(urlparse(url).path, expected_url) - assert_equal(target_type, expected_type) + assert res.status_code == 200 + assert urlparse(url).path == expected_url + assert target_type == expected_type - def test_public_node_non_contributor_commenter_can_update_comment(self): + def test_public_node_non_contributor_commenter_can_update_comment(self, app, non_contributor): project = ProjectFactory(is_public=True, comment_level='public') - comment = CommentFactory(node=project, user=self.non_contributor) + comment = CommentFactory(node=project, user=non_contributor) url = '/{}comments/{}/'.format(API_BASE, comment._id) payload = self._set_up_payload(comment._id) - res = self.app.put_json_api(url, payload, auth=self.non_contributor.auth) - assert_equal(res.status_code, 200) - assert_equal(payload['data']['attributes']['content'], res.json['data']['attributes']['content']) + res = app.put_json_api(url, payload, auth=non_contributor.auth) + assert res.status_code == 200 + assert payload['data']['attributes']['content'] == res.json['data']['attributes']['content'] - def test_public_node_non_contributor_commenter_cannot_update_own_comment_if_comment_level_private(self): + def test_public_node_non_contributor_commenter_cannot_update_own_comment_if_comment_level_private(self, app, non_contributor): project = ProjectFactory(is_public=True, comment_level='public') - comment = CommentFactory(node=project, user=self.non_contributor) + comment = CommentFactory(node=project, user=non_contributor) project.comment_level = 'private' project.save() url = '/{}comments/{}/'.format(API_BASE, comment._id) payload = self._set_up_payload(comment._id) - res = self.app.put_json_api(url, payload, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - assert_equal(res.json['errors'][0]['detail'], 'You do not have permission to perform this action.') + res = app.put_json_api(url, payload, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' - def test_public_node_non_contributor_commenter_can_delete_comment(self): + def test_public_node_non_contributor_commenter_can_delete_comment(self, app, non_contributor): project = ProjectFactory(is_public=True) - comment = CommentFactory(node=project, user=self.non_contributor) + comment = CommentFactory(node=project, user=non_contributor) url = '/{}comments/{}/'.format(API_BASE, comment._id) - res = self.app.delete_json_api(url, auth=self.non_contributor.auth) - assert_equal(res.status_code, 204) + res = app.delete_json_api(url, auth=non_contributor.auth) + assert res.status_code == 204 - def test_registration_comment_has_usable_replies_relationship_link(self): - self._set_up_registration_with_comment() - res = self.app.get(self.registration_url, auth=self.user.auth) - assert_equal(res.status_code, 200) + def test_registration_comment_has_usable_replies_relationship_link(self, app, user, registration_url, registration_comment_reply): + res = app.get(registration_url, auth=user.auth) + assert res.status_code == 200 comments_url = res.json['data']['relationships']['comments']['links']['related']['href'] comments_uri = test_utils.urlparse_drop_netloc(comments_url) - comments_res = self.app.get(comments_uri, auth=self.user.auth) - assert_equal(comments_res.status_code, 200) + comments_res = app.get(comments_uri, auth=user.auth) + assert comments_res.status_code == 200 replies_url = comments_res.json['data'][0]['relationships']['replies']['links']['related']['href'] replies_uri = test_utils.urlparse_drop_netloc(replies_url) - replies_res = self.app.get(replies_uri, auth=self.user.auth) + replies_res = app.get(replies_uri, auth=user.auth) node_url = comments_res.json['data'][0]['relationships']['node']['links']['related']['href'] node_uri = test_utils.urlparse_drop_netloc(node_url) - assert_equal(node_uri, self.registration_url) + assert node_uri == registration_url - def test_registration_comment_has_usable_node_relationship_link(self): - self._set_up_registration_with_comment() - res = self.app.get(self.registration_url, auth=self.user.auth) - assert_equal(res.status_code, 200) + def test_registration_comment_has_usable_node_relationship_link(self, app, user, registration, registration_url, registration_comment_reply): + res = app.get(registration_url, auth=user.auth) + assert res.status_code == 200 comments_url = res.json['data']['relationships']['comments']['links']['related']['href'] comments_uri = test_utils.urlparse_drop_netloc(comments_url) - comments_res = self.app.get(comments_uri, auth=self.user.auth) - assert_equal(comments_res.status_code, 200) + comments_res = app.get(comments_uri, auth=user.auth) + assert comments_res.status_code == 200 node_url = comments_res.json['data'][0]['relationships']['node']['links']['related']['href'] node_uri = test_utils.urlparse_drop_netloc(node_url) - node_res = self.app.get(node_uri, auth=self.user.auth) - assert_in(self.registration._id, node_res.json['data']['id']) - - -class TestFileCommentDetailView(CommentDetailMixin, ApiTestCase): - - def _set_up_private_project_with_comment(self): - self.private_project = ProjectFactory.create(is_public=False, creator=self.user, comment_level='private') - self.private_project.add_contributor(self.contributor, save=True) - self.file = test_utils.create_test_file(self.private_project, self.user) - self.comment = CommentFactory(node=self.private_project, target=self.file.get_guid(), user=self.user) - self.private_url = '/{}comments/{}/'.format(API_BASE, self.comment._id) - self.payload = self._set_up_payload(self.comment._id) - - def _set_up_public_project_with_comment(self): - self.public_project = ProjectFactory.create(is_public=True, creator=self.user, comment_level='private') - self.public_project.add_contributor(self.contributor, save=True) - self.public_file = test_utils.create_test_file(self.public_project, self.user) - self.public_comment = CommentFactory(node=self.public_project, target=self.public_file.get_guid(), user=self.user) - reply_target = Guid.load(self.public_comment._id) - self.public_comment_reply = CommentFactory(node=self.public_project, target=reply_target, user=self.user) - self.public_url = '/{}comments/{}/'.format(API_BASE, self.public_comment._id) - self.public_comment_payload = self._set_up_payload(self.public_comment._id) - - def _set_up_registration_with_comment(self): - self.registration = RegistrationFactory(creator=self.user, comment_level='private') - self.registration_file = test_utils.create_test_file(self.registration, self.user) - self.registration_comment = CommentFactory(node=self.registration, target=self.registration_file.get_guid(), user=self.user) - self.comment_url = '/{}comments/{}/'.format(API_BASE, self.registration_comment._id) - reply_target = Guid.load(self.registration_comment._id) - self.registration_comment_reply = CommentFactory(node=self.registration, target=reply_target, user=self.user) - - def test_file_comment_has_target_link_with_correct_type(self): - self._set_up_public_project_with_comment() - res = self.app.get(self.public_url) + node_res = app.get(node_uri, auth=user.auth) + assert registration._id in node_res.json['data']['id'] + +class TestFileCommentDetailView(CommentDetailMixin): + # private_project_with_comments + @pytest.fixture() + def private_project(self, user, contributor): + private_project = ProjectFactory.create(is_public=False, creator=user) + private_project.add_contributor(contributor, save=True) + return private_project + + @pytest.fixture() + def file(self, user, private_project): + return test_utils.create_test_file(private_project, user) + + @pytest.fixture() + def comment(self, user, private_project, file): + return CommentFactory(node=private_project, target=file.get_guid(), user=user) + + @pytest.fixture() + def private_url(self, comment): + return '/{}comments/{}/'.format(API_BASE, comment._id) + + @pytest.fixture() + def payload(self, comment): + return self._set_up_payload(comment._id) + + # public_project_with_comments + @pytest.fixture() + def public_project(self, user, contributor): + public_project = ProjectFactory.create(is_public=True, creator=user, comment_level='private') + public_project.add_contributor(contributor, save=True) + return public_project + + @pytest.fixture() + def public_file(self, user, public_project): + return test_utils.create_test_file(public_project, user) + + @pytest.fixture() + def public_comment(self, user, public_project, public_file): + return CommentFactory(node=public_project, target=public_file.get_guid(), user=user) + + @pytest.fixture() + def public_comment_reply(self, user, public_comment, public_project): + reply_target = Guid.load(public_comment._id) + return CommentFactory(node=public_project, target=reply_target, user=user) + + @pytest.fixture() + def public_url(self, public_comment): + return '/{}comments/{}/'.format(API_BASE, public_comment._id) + + @pytest.fixture() + def public_comment_payload(self, public_comment): + return self._set_up_payload(public_comment._id) + + # registration_with_comments + @pytest.fixture() + def registration(self, user): + return RegistrationFactory(creator=user, comment_level='private') + + @pytest.fixture() + def registration_file(self, user, registration): + return test_utils.create_test_file(registration, user) + + @pytest.fixture() + def registration_comment(self, user, registration, registration_file): + return CommentFactory(node=registration, target=registration_file.get_guid(), user=user) + + @pytest.fixture() + def comment_url(self, registration_comment): + return '/{}comments/{}/'.format(API_BASE, registration_comment._id) + + @pytest.fixture() + def registration_comment_reply(self, user, registration, registration_comment): + reply_target = Guid.load(registration_comment._id) + return CommentFactory(node=registration, target=reply_target, user=user) + + + def test_file_comment_has_target_link_with_correct_type(self, app, public_url, public_file): + res = app.get(public_url) url = res.json['data']['relationships']['target']['links']['related']['href'] - expected_url = '/{}files/{}/'.format(API_BASE, self.public_file._id) + expected_url = '/{}files/{}/'.format(API_BASE, public_file._id) target_type = res.json['data']['relationships']['target']['links']['related']['meta']['type'] expected_type = 'files' - assert_equal(res.status_code, 200) - assert_equal(urlparse(url).path, expected_url) - assert_equal(target_type, expected_type) + assert res.status_code == 200 + assert urlparse(url).path == expected_url + assert target_type == expected_type - def test_public_node_non_contributor_commenter_can_update_file_comment(self): + def test_public_node_non_contributor_commenter_can_update_file_comment(self, app, non_contributor): project = ProjectFactory(is_public=True) test_file = test_utils.create_test_file(project, project.creator) - comment = CommentFactory(node=project, target=test_file.get_guid(), user=self.non_contributor) + comment = CommentFactory(node=project, target=test_file.get_guid(), user=non_contributor) url = '/{}comments/{}/'.format(API_BASE, comment._id) payload = self._set_up_payload(comment._id) - res = self.app.put_json_api(url, payload, auth=self.non_contributor.auth) - assert_equal(res.status_code, 200) - assert_equal(payload['data']['attributes']['content'], res.json['data']['attributes']['content']) + res = app.put_json_api(url, payload, auth=non_contributor.auth) + assert res.status_code == 200 + assert payload['data']['attributes']['content'] == res.json['data']['attributes']['content'] - def test_public_node_non_contributor_commenter_cannot_update_own_file_comment_if_comment_level_private(self): + def test_public_node_non_contributor_commenter_cannot_update_own_file_comment_if_comment_level_private(self, app, non_contributor): project = ProjectFactory(is_public=True) test_file = test_utils.create_test_file(project, project.creator) - comment = CommentFactory(node=project, target=test_file.get_guid(), user=self.non_contributor) + comment = CommentFactory(node=project, target=test_file.get_guid(), user=non_contributor) project.comment_level = 'private' project.save() url = '/{}comments/{}/'.format(API_BASE, comment._id) payload = self._set_up_payload(comment._id) - res = self.app.put_json_api(url, payload, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - assert_equal(res.json['errors'][0]['detail'], 'You do not have permission to perform this action.') + res = app.put_json_api(url, payload, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' - def test_public_node_non_contributor_commenter_can_delete_file_comment(self): + def test_public_node_non_contributor_commenter_can_delete_file_comment(self, app, non_contributor): project = ProjectFactory(is_public=True, comment_level='public') test_file = test_utils.create_test_file(project, project.creator) - comment = CommentFactory(node=project, target=test_file.get_guid(), user=self.non_contributor) + comment = CommentFactory(node=project, target=test_file.get_guid(), user=non_contributor) url = '/{}comments/{}/'.format(API_BASE, comment._id) - res = self.app.delete_json_api(url, auth=self.non_contributor.auth) - assert_equal(res.status_code, 204) + res = app.delete_json_api(url, auth=non_contributor.auth) + assert res.status_code == 204 - def test_comment_detail_for_deleted_file_is_not_returned(self): - self._set_up_private_project_with_comment() + def test_comment_detail_for_deleted_file_is_not_returned(self, app, user, private_project, file, private_url): # Delete commented file - osfstorage = self.private_project.get_addon('osfstorage') + osfstorage = private_project.get_addon('osfstorage') root_node = osfstorage.get_root() - self.file.delete() - res = self.app.get(self.private_url, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 404) + file.delete() + res = app.get(private_url, auth=user.auth, expect_errors=True) + assert res.status_code == 404 -class TestWikiCommentDetailView(CommentDetailMixin, ApiTestCase): +class TestWikiCommentDetailView(CommentDetailMixin): + # private_project_with_comments + @pytest.fixture() + def private_project(self, user, contributor): + private_project = ProjectFactory.create(is_public=False, creator=user, comment_level='private') + private_project.add_contributor(contributor, save=True) + return private_project - def _set_up_private_project_with_comment(self): - self.private_project = ProjectFactory.create(is_public=False, creator=self.user, comment_level='private') - self.private_project.add_contributor(self.contributor, save=True) + @pytest.fixture() + def wiki(self, user, private_project): with mock.patch('osf.models.AbstractNode.update_search'): - self.wiki = NodeWikiFactory(node=self.private_project, user=self.user) - self.comment = CommentFactory(node=self.private_project, target=Guid.load(self.wiki._id), user=self.user) - self.private_url = '/{}comments/{}/'.format(API_BASE, self.comment._id) - self.payload = self._set_up_payload(self.comment._id) - - def _set_up_public_project_with_comment(self): - self.public_project = ProjectFactory.create(is_public=True, creator=self.user, comment_level='private') - self.public_project.add_contributor(self.contributor, save=True) + return NodeWikiFactory(node=private_project, user=user) + + @pytest.fixture() + def comment(self, user, private_project, wiki): + return CommentFactory(node=private_project, target=Guid.load(wiki._id), user=user) + + @pytest.fixture() + def private_url(self, comment): + return '/{}comments/{}/'.format(API_BASE, comment._id) + + @pytest.fixture() + def payload(self, comment): + return self._set_up_payload(comment._id) + + # public_project_with_comments + @pytest.fixture() + def public_project(self, user, contributor): + public_project = ProjectFactory.create(is_public=True, creator=user, comment_level='private') + public_project.add_contributor(contributor, save=True) + return public_project + + @pytest.fixture() + def public_wiki(self, user, public_project): with mock.patch('osf.models.AbstractNode.update_search'): - self.public_wiki = NodeWikiFactory(node=self.public_project, user=self.user) - self.public_comment = CommentFactory(node=self.public_project, target=Guid.load(self.public_wiki._id), user=self.user) - reply_target = Guid.load(self.public_comment._id) - self.public_comment_reply = CommentFactory(node=self.public_project, target=reply_target, user=self.user) - self.public_url = '/{}comments/{}/'.format(API_BASE, self.public_comment._id) - self.public_comment_payload = self._set_up_payload(self.public_comment._id) - - def _set_up_registration_with_comment(self): - self.registration = RegistrationFactory(creator=self.user, comment_level='private') + return NodeWikiFactory(node=public_project, user=user) + + @pytest.fixture() + def public_comment(self, user, public_project, public_wiki): + return CommentFactory(node=public_project, target=Guid.load(public_wiki._id), user=user) + + @pytest.fixture() + def public_comment_reply(self, user, public_comment, public_project): + reply_target = Guid.load(public_comment._id) + return CommentFactory(node=public_project, target=reply_target, user=user) + + @pytest.fixture() + def public_url(self, public_comment): + return '/{}comments/{}/'.format(API_BASE, public_comment._id) + + @pytest.fixture() + def public_comment_payload(self, public_comment): + return self._set_up_payload(public_comment._id) + + # registration_with_comments + @pytest.fixture() + def registration(self, user): + return RegistrationFactory(creator=user, comment_level='private') + + @pytest.fixture() + def registration_wiki(self, registration, user): with mock.patch('osf.models.AbstractNode.update_search'): - self.registration_wiki = NodeWikiFactory(node=self.registration, user=self.user) - self.registration_comment = CommentFactory(node=self.registration, target=Guid.load(self.registration_wiki._id), user=self.user) - self.comment_url = '/{}comments/{}/'.format(API_BASE, self.registration_comment._id) - reply_target = Guid.load(self.registration_comment._id) - self.registration_comment_reply = CommentFactory(node=self.registration, target=reply_target, user=self.user) - - def test_wiki_comment_has_target_link_with_correct_type(self): - self._set_up_public_project_with_comment() - res = self.app.get(self.public_url) + return NodeWikiFactory(node=registration, user=user) + + @pytest.fixture() + def registration_comment(self, user, registration, registration_wiki): + return CommentFactory(node=registration, target=Guid.load(registration_wiki._id), user=user) + + @pytest.fixture() + def comment_url(self, registration_comment): + return '/{}comments/{}/'.format(API_BASE, registration_comment._id) + + @pytest.fixture() + def registration_comment_reply(self, user, registration, registration_comment): + reply_target = Guid.load(registration_comment._id) + return CommentFactory(node=registration, target=reply_target, user=user) + + def test_wiki_comment_has_target_link_with_correct_type(self, app, public_url, public_wiki): + res = app.get(public_url) url = res.json['data']['relationships']['target']['links']['related']['href'] - expected_url = self.public_wiki.get_absolute_url() + expected_url = public_wiki.get_absolute_url() target_type = res.json['data']['relationships']['target']['links']['related']['meta']['type'] expected_type = 'wiki' - assert_equal(res.status_code, 200) - assert_equal(url, expected_url) - assert_equal(target_type, expected_type) + assert res.status_code == 200 + assert url == expected_url + assert target_type == expected_type - def test_public_node_non_contributor_commenter_can_update_wiki_comment(self): + def test_public_node_non_contributor_commenter_can_update_wiki_comment(self, app, user, non_contributor, ): project = ProjectFactory(is_public=True) - test_wiki = NodeWikiFactory(node=project, user=self.user) - comment = CommentFactory(node=project, target=Guid.load(test_wiki._id), user=self.non_contributor) + test_wiki = NodeWikiFactory(node=project, user=user) + comment = CommentFactory(node=project, target=Guid.load(test_wiki._id), user=non_contributor) url = '/{}comments/{}/'.format(API_BASE, comment._id) payload = self._set_up_payload(comment._id) - res = self.app.put_json_api(url, payload, auth=self.non_contributor.auth) - assert_equal(res.status_code, 200) - assert_equal(payload['data']['attributes']['content'], res.json['data']['attributes']['content']) + res = app.put_json_api(url, payload, auth=non_contributor.auth) + assert res.status_code == 200 + assert payload['data']['attributes']['content'] == res.json['data']['attributes']['content'] - def test_public_node_non_contributor_commenter_cannot_update_own_wiki_comment_if_comment_level_private(self): + def test_public_node_non_contributor_commenter_cannot_update_own_wiki_comment_if_comment_level_private(self, app, user, non_contributor): project = ProjectFactory(is_public=True) - test_wiki = NodeWikiFactory(node=project, user=self.user) - comment = CommentFactory(node=project, target=Guid.load(test_wiki._id), user=self.non_contributor) + test_wiki = NodeWikiFactory(node=project, user=user) + comment = CommentFactory(node=project, target=Guid.load(test_wiki._id), user=non_contributor) project.comment_level = 'private' project.save() url = '/{}comments/{}/'.format(API_BASE, comment._id) payload = self._set_up_payload(comment._id) - res = self.app.put_json_api(url, payload, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - assert_equal(res.json['errors'][0]['detail'], 'You do not have permission to perform this action.') + res = app.put_json_api(url, payload, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' - def test_public_node_non_contributor_commenter_can_delete_wiki_comment(self): + def test_public_node_non_contributor_commenter_can_delete_wiki_comment(self, app, user, non_contributor): project = ProjectFactory(is_public=True, comment_level='public') - test_wiki = NodeWikiFactory(node=project, user=self.user) - comment = CommentFactory(node=project, target=Guid.load(test_wiki._id), user=self.non_contributor) + test_wiki = NodeWikiFactory(node=project, user=user) + comment = CommentFactory(node=project, target=Guid.load(test_wiki._id), user=non_contributor) url = '/{}comments/{}/'.format(API_BASE, comment._id) - res = self.app.delete_json_api(url, auth=self.non_contributor.auth) - assert_equal(res.status_code, 204) + res = app.delete_json_api(url, auth=non_contributor.auth) + assert res.status_code == 204 - def test_comment_detail_for_deleted_wiki_is_not_returned(self): - self._set_up_private_project_with_comment() + def test_comment_detail_for_deleted_wiki_is_not_returned(self, app, user, wiki, private_url, private_project): # Delete commented wiki page - self.private_project.delete_node_wiki(self.wiki.page_name, core.Auth(self.user)) - res = self.app.get(self.private_url, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 404) + private_project.delete_node_wiki(wiki.page_name, core.Auth(user)) + res = app.get(private_url, auth=user.auth, expect_errors=True) + assert res.status_code == 404 From e6b56e759bd2849e4add48cd9963c67af0a77136 Mon Sep 17 00:00:00 2001 From: Jerry Sun Date: Fri, 2 Jun 2017 13:23:34 -0400 Subject: [PATCH 02/62] Convert all .py in api_tests/files into pytest --- .../views/test_comment_report_detail.py | 522 ++++++++++-------- .../views/test_comment_report_list.py | 497 ++++++++++------- 2 files changed, 583 insertions(+), 436 deletions(-) diff --git a/api_tests/comments/views/test_comment_report_detail.py b/api_tests/comments/views/test_comment_report_detail.py index 266f66e9425..0e26347ef80 100644 --- a/api_tests/comments/views/test_comment_report_detail.py +++ b/api_tests/comments/views/test_comment_report_detail.py @@ -1,28 +1,36 @@ -import mock import pytest + +import mock from django.utils import timezone -from nose.tools import * # flake8: noqa from datetime import datetime from framework.guid.model import Guid - from api.base.settings.defaults import API_BASE from api_tests import utils as test_utils from tests.base import ApiTestCase from osf_tests.factories import ProjectFactory, AuthUserFactory, CommentFactory from addons.wiki.tests.factories import NodeWikiFactory - +@pytest.mark.django_db class ReportDetailViewMixin(object): - def setUp(self): - super(ReportDetailViewMixin, self).setUp() - self.user = AuthUserFactory() - self.contributor = AuthUserFactory() - self.non_contributor = AuthUserFactory() - self.payload = { + @pytest.fixture() + def user(self): + return AuthUserFactory() + + @pytest.fixture() + def contributor(self): + return AuthUserFactory() + + @pytest.fixture() + def non_contributor(self): + return AuthUserFactory() + + @pytest.fixture() + def payload(self, user): + payload = { 'data': { - 'id': self.user._id, + 'id': user._id, 'type': 'comment_reports', 'attributes': { 'category': 'spam', @@ -30,125 +38,131 @@ def setUp(self): } } } + return payload - def _set_up_private_project_comment_reports(self): + # check if all necessary features are setup in subclass + @pytest.fixture() + def private_project(self): raise NotImplementedError - def _set_up_public_project_comment_reports(self): + @pytest.fixture() + def comment(self): raise NotImplementedError - def test_private_node_reporting_contributor_can_view_report_detail(self): - self._set_up_private_project_comment_reports() - res = self.app.get(self.private_url, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal(res.json['data']['id'], self.user._id) - - def test_private_node_reported_contributor_cannot_view_report_detail(self): - self._set_up_private_project_comment_reports() - res = self.app.get(self.private_url, auth=self.contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - - def test_private_node_logged_in_non_contributor_cannot_view_report_detail(self): - self._set_up_private_project_comment_reports() - res = self.app.get(self.private_url, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - - def test_private_node_logged_out_contributor_cannot_view_report_detail(self): - self._set_up_private_project_comment_reports() - res = self.app.get(self.private_url, expect_errors=True) - assert_equal(res.status_code, 401) - - def test_public_node_reporting_contributor_can_view_report_detail(self): - self._set_up_public_project_comment_reports() - res = self.app.get(self.public_url, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal(res.json['data']['id'], self.user._id) - - def test_public_node_reported_contributor_cannot_view_report_detail(self): - self._set_up_public_project_comment_reports() - res = self.app.get(self.public_url, auth=self.contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - - def test_public_node_logged_in_non_contributor_cannot_view_other_users_report_detail(self): - self._set_up_public_project_comment_reports() - res = self.app.get(self.public_url, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - - def test_public_node_logged_out_contributor_cannot_view_report_detail(self): - self._set_up_public_project_comment_reports() - res = self.app.get(self.public_url, expect_errors=True) - assert_equal(res.status_code, 401) - - def test_public_node_logged_in_non_contributor_reporter_can_view_own_report_detail(self): - self._set_up_public_project_comment_reports() - self.public_comment.reports[self.non_contributor._id] = { + @pytest.fixture() + def private_url(self): + raise NotImplementedError + + @pytest.fixture() + def public_project(self): + raise NotImplementedError + + @pytest.fixture() + def public_comment(self): + raise NotImplementedError + + @pytest.fixture() + def public_url(self): + raise NotImplementedError + + def test_private_node_view_report_detail_auth_misc(self, app, user, contributor, non_contributor, private_url): + # test_private_node_reporting_contributor_can_view_report_detail + res = app.get(private_url, auth=user.auth) + assert res.status_code == 200 + assert res.json['data']['id'] == user._id + + # test_private_node_reported_contributor_cannot_view_report_detail + res = app.get(private_url, auth=contributor.auth, expect_errors=True) + assert res.status_code == 403 + + # test_private_node_logged_in_non_contributor_cannot_view_report_detail + res = app.get(private_url, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + + # test_private_node_logged_out_contributor_cannot_view_report_detail + res = app.get(private_url, expect_errors=True) + assert res.status_code == 401 + + def test_public_node_view_report_detail_auth_misc(self, app, user, contributor, non_contributor, public_url): + # test_public_node_reporting_contributor_can_view_report_detail + res = app.get(public_url, auth=user.auth) + assert res.status_code == 200 + assert res.json['data']['id'] == user._id + + # test_public_node_reported_contributor_cannot_view_report_detail + res = app.get(public_url, auth=contributor.auth, expect_errors=True) + assert res.status_code == 403 + + # test_public_node_logged_in_non_contributor_cannot_view_other_users_report_detail + res = app.get(public_url, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + + # test_public_node_logged_out_contributor_cannot_view_report_detail + res = app.get(public_url, expect_errors=True) + assert res.status_code == 401 + + def test_public_node_logged_in_non_contributor_reporter_can_view_own_report_detail(self, app, non_contributor, public_comment): + public_comment.reports[non_contributor._id] = { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, } - self.public_comment.save() - url = '/{}comments/{}/reports/{}/'.format(API_BASE, self.public_comment._id, self.non_contributor._id) - res = self.app.get(url, auth=self.non_contributor.auth) - assert_equal(res.status_code, 200) - - def test_private_node_reporting_contributor_can_update_report_detail(self): - self._set_up_private_project_comment_reports() - res = self.app.put_json_api(self.private_url, self.payload, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal(res.json['data']['id'], self.user._id) - assert_equal(res.json['data']['attributes']['message'], self.payload['data']['attributes']['message']) - - def test_private_node_reported_contributor_cannot_update_report_detail(self): - self._set_up_private_project_comment_reports() - res = self.app.put_json_api(self.private_url, self.payload, auth=self.contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - - def test_private_node_logged_in_non_contributor_cannot_update_report_detail(self): - self._set_up_private_project_comment_reports() - res = self.app.put_json_api(self.private_url, self.payload, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - - def test_private_node_logged_out_contributor_cannot_update_detail(self): - self._set_up_private_project_comment_reports() - res = self.app.put_json_api(self.private_url, self.payload, expect_errors=True) - assert_equal(res.status_code, 401) - - def test_public_node_reporting_contributor_can_update_detail(self): - self._set_up_public_project_comment_reports() - res = self.app.put_json_api(self.public_url, self.payload, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal(res.json['data']['id'], self.user._id) - assert_equal(res.json['data']['attributes']['message'], self.payload['data']['attributes']['message']) - - def test_public_node_reported_contributor_cannot_update_detail(self): - self._set_up_public_project_comment_reports() - res = self.app.put_json_api(self.public_url, self.payload, auth=self.contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - - def test_public_node_logged_in_non_contributor_cannot_update_other_users_report_detail(self): - self._set_up_public_project_comment_reports() - res = self.app.put_json_api(self.public_url, self.payload, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - - def test_public_node_logged_out_contributor_cannot_update_report_detail(self): - self._set_up_public_project_comment_reports() - res = self.app.put_json_api(self.public_url, self.payload, expect_errors=True) - assert_equal(res.status_code, 401) - - def test_public_node_logged_in_non_contributor_reporter_can_update_own_report_detail(self): - self._set_up_public_project_comment_reports() - self.public_comment.reports[self.non_contributor._id] = { + public_comment.save() + url = '/{}comments/{}/reports/{}/'.format(API_BASE, public_comment._id, non_contributor._id) + res = app.get(url, auth=non_contributor.auth) + assert res.status_code == 200 + + def test_private_node_update_report_detail_auth_misc(self, app, user, contributor, non_contributor, payload, private_url): + # test_private_node_reported_contributor_cannot_update_report_detail + res = app.put_json_api(private_url, payload, auth=contributor.auth, expect_errors=True) + assert res.status_code == 403 + + # test_private_node_logged_in_non_contributor_cannot_update_report_detail + res = app.put_json_api(private_url, payload, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + + # test_private_node_logged_out_contributor_cannot_update_detail + res = app.put_json_api(private_url, payload, expect_errors=True) + assert res.status_code == 401 + + # test_private_node_reporting_contributor_can_update_report_detail + res = app.put_json_api(private_url, payload, auth=user.auth) + assert res.status_code == 200 + assert res.json['data']['id'] == user._id + assert res.json['data']['attributes']['message'] == payload['data']['attributes']['message'] + + def test_public_node_update_report_detail_auth_misc(self, app, user, contributor, non_contributor, payload, public_url): + # test_public_node_reported_contributor_cannot_update_detail + res = app.put_json_api(public_url, payload, auth=contributor.auth, expect_errors=True) + assert res.status_code == 403 + + # test_public_node_logged_in_non_contributor_cannot_update_other_users_report_detail + res = app.put_json_api(public_url, payload, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + + # test_public_node_logged_out_contributor_cannot_update_report_detail + res = app.put_json_api(public_url, payload, expect_errors=True) + assert res.status_code == 401 + + # test_public_node_reporting_contributor_can_update_detail + res = app.put_json_api(public_url, payload, auth=user.auth) + assert res.status_code == 200 + assert res.json['data']['id'] == user._id + assert res.json['data']['attributes']['message'] == payload['data']['attributes']['message'] + + def test_public_node_logged_in_non_contributor_reporter_can_update_own_report_detail(self, app, non_contributor, public_comment): + public_comment.reports[non_contributor._id] = { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, } - self.public_comment.save() - url = '/{}comments/{}/reports/{}/'.format(API_BASE, self.public_comment._id, self.non_contributor._id) + public_comment.save() + url = '/{}comments/{}/reports/{}/'.format(API_BASE, public_comment._id, non_contributor._id) payload = { 'data': { - 'id': self.non_contributor._id, + 'id': non_contributor._id, 'type': 'comment_reports', 'attributes': { 'category': 'spam', @@ -156,161 +170,225 @@ def test_public_node_logged_in_non_contributor_reporter_can_update_own_report_de } } } - res = self.app.put_json_api(url, payload, auth=self.non_contributor.auth) - assert_equal(res.status_code, 200) - assert_equal(res.json['data']['attributes']['message'], payload['data']['attributes']['message']) - - def test_private_node_reporting_contributor_can_delete_report_detail(self): - self._set_up_private_project_comment_reports() - comment = CommentFactory.build(node=self.private_project, user=self.contributor, target=self.comment.target) - comment.reports = {self.user._id: { + res = app.put_json_api(url, payload, auth=non_contributor.auth) + assert res.status_code == 200 + assert res.json['data']['attributes']['message'] == payload['data']['attributes']['message'] + + def test_private_node_delete_report_detail_auth_misc(self, app, user, contributor, non_contributor, private_project, payload, private_url, comment): + # test_private_node_reported_contributor_cannot_delete_report_detail + res = app.delete_json_api(private_url, auth=contributor.auth, expect_errors=True) + assert res.status_code == 403 + + # test_private_node_logged_in_non_contributor_cannot_delete_report_detail + res = app.delete_json_api(private_url, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + + # test_private_node_logged_out_contributor_cannot_delete_detail + res = app.delete_json_api(private_url, expect_errors=True) + assert res.status_code == 401 + + # test_private_node_reporting_contributor_can_delete_report_detail + comment_new = CommentFactory.build(node=private_project, user=contributor, target=comment.target) + comment_new.reports = {user._id: { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, }} - comment.save() - url = '/{}comments/{}/reports/{}/'.format(API_BASE, comment._id, self.user._id) - res = self.app.delete_json_api(url, auth=self.user.auth) - assert_equal(res.status_code, 204) - - def test_private_node_reported_contributor_cannot_delete_report_detail(self): - self._set_up_private_project_comment_reports() - res = self.app.delete_json_api(self.private_url, auth=self.contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - - def test_private_node_logged_in_non_contributor_cannot_delete_report_detail(self): - self._set_up_private_project_comment_reports() - res = self.app.delete_json_api(self.private_url, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - - def test_private_node_logged_out_contributor_cannot_delete_detail(self): - self._set_up_private_project_comment_reports() - res = self.app.delete_json_api(self.private_url, expect_errors=True) - assert_equal(res.status_code, 401) - - def test_public_node_reporting_contributor_can_delete_detail(self): - self._set_up_public_project_comment_reports() - res = self.app.delete_json_api(self.public_url, auth=self.user.auth) - assert_equal(res.status_code, 204) - - def test_public_node_reported_contributor_cannot_delete_detail(self): - self._set_up_public_project_comment_reports() - res = self.app.delete_json_api(self.public_url, auth=self.contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - - def test_public_node_logged_in_non_contributor_cannot_delete_other_users_report_detail(self): - self._set_up_public_project_comment_reports() - res = self.app.delete_json_api(self.public_url, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - - def test_public_node_logged_out_contributor_cannot_delete_report_detail(self): - self._set_up_public_project_comment_reports() - res = self.app.delete_json_api(self.public_url, expect_errors=True) - assert_equal(res.status_code, 401) - - def test_public_node_logged_in_non_contributor_reporter_can_delete_own_report_detail(self): - self._set_up_public_project_comment_reports() - self.public_comment.reports[self.non_contributor._id] = { + comment_new.save() + url = '/{}comments/{}/reports/{}/'.format(API_BASE, comment_new._id, user._id) + res = app.delete_json_api(url, auth=user.auth) + assert res.status_code == 204 + + def test_public_node_delete_report_detail_auth_misc(self, app, user, contributor, non_contributor, public_url): + + # test_public_node_reported_contributor_cannot_delete_detail + res = app.delete_json_api(public_url, auth=contributor.auth, expect_errors=True) + assert res.status_code == 403 + + # test_public_node_logged_in_non_contributor_cannot_delete_other_users_report_detail + res = app.delete_json_api(public_url, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + + # test_public_node_logged_out_contributor_cannot_delete_report_detail + res = app.delete_json_api(public_url, expect_errors=True) + assert res.status_code == 401 + + # test_public_node_reporting_contributor_can_delete_detail + res = app.delete_json_api(public_url, auth=user.auth) + assert res.status_code == 204 + + def test_public_node_logged_in_non_contributor_reporter_can_delete_own_report_detail(self, app, non_contributor, public_comment): + public_comment.reports[non_contributor._id] = { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, } - self.public_comment.save() - url = '/{}comments/{}/reports/{}/'.format(API_BASE, self.public_comment._id, self.non_contributor._id) - res = self.app.delete_json_api(url, auth=self.non_contributor.auth) - assert_equal(res.status_code, 204) + public_comment.save() + url = '/{}comments/{}/reports/{}/'.format(API_BASE, public_comment._id, non_contributor._id) + res = app.delete_json_api(url, auth=non_contributor.auth) + assert res.status_code == 204 -class TestReportDetailView(ReportDetailViewMixin, ApiTestCase): +class TestReportDetailView(ReportDetailViewMixin): - def _set_up_private_project_comment_reports(self): - self.private_project = ProjectFactory.create(is_public=False, creator=self.user) - self.private_project.add_contributor(contributor=self.contributor, save=True) - self.comment = CommentFactory.build(node=self.private_project, user=self.contributor) - self.comment.reports = {self.user._id: { + # private_project_comment_reports + @pytest.fixture() + def private_project(self, user, contributor): + private_project = ProjectFactory.create(is_public=False, creator=user) + private_project.add_contributor(contributor = contributor, save=True) + return private_project + + @pytest.fixture() + def comment(self, user, contributor, private_project): + comment = CommentFactory(node=private_project, user=contributor) + comment.reports = {user._id: { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, }} - self.comment.save() - self.private_url = '/{}comments/{}/reports/{}/'.format(API_BASE, self.comment._id, self.user._id) - - def _set_up_public_project_comment_reports(self): - self.public_project = ProjectFactory.create(is_public=True, creator=self.user) - self.public_project.add_contributor(contributor=self.contributor, save=True) - self.public_comment = CommentFactory.build(node=self.public_project, user=self.contributor) - self.public_comment.reports = {self.user._id: { + comment.save() + return comment + + @pytest.fixture() + def private_url(self, user, comment): + return '/{}comments/{}/reports/{}/'.format(API_BASE, comment._id, user._id) + + # public_project_comment_reports + @pytest.fixture() + def public_project(self, user, contributor): + public_project = ProjectFactory.create(is_public=True, creator=user) + public_project.add_contributor(contributor = contributor, save=True) + return public_project + + @pytest.fixture() + def public_comment(self, user, contributor, public_project): + public_comment = CommentFactory(node=public_project, user=contributor) + public_comment.reports = {user._id: { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, }} - self.public_comment.save() - self.public_url = '/{}comments/{}/reports/{}/'.format(API_BASE, self.public_comment._id, self.user._id) - - -class TestFileCommentReportDetailView(ReportDetailViewMixin, ApiTestCase): - - def _set_up_private_project_comment_reports(self): - self.private_project = ProjectFactory.create(is_public=False, creator=self.user) - self.private_project.add_contributor(contributor=self.contributor, save=True) - self.file = test_utils.create_test_file(self.private_project, self.user) - self.comment = CommentFactory.build(node=self.private_project, target=self.file.get_guid(), user=self.contributor) - self.comment.reports = {self.user._id: { + public_comment.save() + return public_comment + + @pytest.fixture() + def public_url(self, user, public_comment): + return '/{}comments/{}/reports/{}/'.format(API_BASE, public_comment._id, user._id) + +class TestFileCommentReportDetailView(ReportDetailViewMixin): + + # private_project_comment_reports + @pytest.fixture() + def private_project(self, user, contributor): + private_project = ProjectFactory.create(is_public=False, creator=user) + private_project.add_contributor(contributor=contributor, save=True) + return private_project + + @pytest.fixture() + def file(self, user, private_project): + return test_utils.create_test_file(private_project, user) + + @pytest.fixture() + def comment(self, user, contributor, private_project, file): + comment = CommentFactory(node=private_project, target=file.get_guid(), user=contributor) + comment.reports = {user._id: { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, }} - self.comment.save() - self.private_url = '/{}comments/{}/reports/{}/'.format(API_BASE, self.comment._id, self.user._id) - - def _set_up_public_project_comment_reports(self): - self.public_project = ProjectFactory.create(is_public=True, creator=self.user) - self.public_project.add_contributor(contributor=self.contributor, save=True) - self.public_file = test_utils.create_test_file(self.public_project, self.user) - self.public_comment = CommentFactory.build(node=self.public_project, target=self.public_file.get_guid(), user=self.contributor) - self.public_comment.reports = {self.user._id: { + comment.save() + return comment + + @pytest.fixture() + def private_url(self, user, comment): + return '/{}comments/{}/reports/{}/'.format(API_BASE, comment._id, user._id) + + # public_project_comment_reports + @pytest.fixture() + def public_project(self, user, contributor): + public_project = ProjectFactory.create(is_public=True, creator=user) + public_project.add_contributor(contributor = contributor, save=True) + return public_project + + @pytest.fixture() + def public_file(self, user, public_project): + return test_utils.create_test_file(public_project, user) + + @pytest.fixture() + def public_comment(self, user, contributor, public_project, public_file): + public_comment = CommentFactory(node=public_project, target=public_file.get_guid(), user=contributor) + public_comment.reports = {user._id: { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, }} - self.public_comment.save() - self.public_url = '/{}comments/{}/reports/{}/'.format(API_BASE, self.public_comment._id, self.user._id) + public_comment.save() + return public_comment + + @pytest.fixture() + def public_url(self, user, public_comment): + return '/{}comments/{}/reports/{}/'.format(API_BASE, public_comment._id, user._id) +class TestWikiCommentReportDetailView(ReportDetailViewMixin): -class TestWikiCommentReportDetailView(ReportDetailViewMixin, ApiTestCase): + # private_project_comment_reports + @pytest.fixture() + def private_project(self, user, contributor): + private_project = ProjectFactory.create(is_public=False, creator=user) + private_project.add_contributor(contributor=contributor, save=True) + return private_project - def _set_up_private_project_comment_reports(self): - self.private_project = ProjectFactory.create(is_public=False, creator=self.user) - self.private_project.add_contributor(contributor=self.contributor, save=True) + @pytest.fixture() + def wiki(self, user, private_project): with mock.patch('osf.models.AbstractNode.update_search'): - self.wiki = NodeWikiFactory(node=self.private_project, user=self.user) - self.comment = CommentFactory.build(node=self.private_project, target=Guid.load(self.wiki._id), user=self.contributor) - self.comment.reports = {self.user._id: { + return NodeWikiFactory(node=private_project, user=user) + + @pytest.fixture() + def comment(self, user, contributor, private_project, wiki): + comment = CommentFactory(node=private_project, target=Guid.load(wiki._id), user=contributor) + comment.reports = {user._id: { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, }} - self.comment.save() - self.private_url = '/{}comments/{}/reports/{}/'.format(API_BASE, self.comment._id, self.user._id) + comment.save() + return comment + + @pytest.fixture() + def private_url(self, user, comment): + return '/{}comments/{}/reports/{}/'.format(API_BASE, comment._id, user._id) + + # public_project_comment_reports + @pytest.fixture() + def public_project(self, user, contributor): + public_project = ProjectFactory.create(is_public=True, creator=user) + public_project.add_contributor(contributor = contributor, save=True) + return public_project - def _set_up_public_project_comment_reports(self): - self.public_project = ProjectFactory.create(is_public=True, creator=self.user) - self.public_project.add_contributor(contributor=self.contributor, save=True) + @pytest.fixture() + def public_wiki(self, user, public_project): with mock.patch('osf.models.AbstractNode.update_search'): - self.public_wiki = NodeWikiFactory(node=self.public_project, user=self.user) - self.public_comment = CommentFactory.build(node=self.public_project, target=Guid.load(self.public_wiki._id), user=self.contributor) - self.public_comment.reports = {self.user._id: { + return NodeWikiFactory(node=public_project, user=user) + + @pytest.fixture() + def public_comment(self, user, contributor, public_project, public_wiki): + public_comment = CommentFactory(node=public_project, target=Guid.load(public_wiki._id), user=contributor) + public_comment.reports = {user._id: { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, }} - self.public_comment.save() - self.public_url = '/{}comments/{}/reports/{}/'.format(API_BASE, self.public_comment._id, self.user._id) + public_comment.save() + return public_comment + + @pytest.fixture() + def public_url(self, user, public_comment): + return '/{}comments/{}/reports/{}/'.format(API_BASE, public_comment._id, user._id) diff --git a/api_tests/comments/views/test_comment_report_list.py b/api_tests/comments/views/test_comment_report_list.py index 0a772d31349..72dd2590706 100644 --- a/api_tests/comments/views/test_comment_report_list.py +++ b/api_tests/comments/views/test_comment_report_list.py @@ -1,27 +1,36 @@ -import mock import pytest + +import mock from django.utils import timezone -from nose.tools import * # flake8: noqa from datetime import datetime from framework.guid.model import Guid - from api.base.settings.defaults import API_BASE from api_tests import utils as test_utils from tests.base import ApiTestCase from osf_tests.factories import ProjectFactory, AuthUserFactory, CommentFactory from addons.wiki.tests.factories import NodeWikiFactory - +@pytest.mark.django_db class CommentReportsMixin(object): - def setUp(self): - super(CommentReportsMixin, self).setUp() - self.user = AuthUserFactory() - self.contributor = AuthUserFactory() - self.non_contributor = AuthUserFactory() - self.payload = { + @pytest.fixture() + def user(self): + return AuthUserFactory() + + @pytest.fixture() + def contributor(self): + return AuthUserFactory() + + @pytest.fixture() + def non_contributor(self): + return AuthUserFactory() + + @pytest.fixture() + def payload(self, user): + payload = { 'data': { + 'id': user._id, 'type': 'comment_reports', 'attributes': { 'category': 'spam', @@ -29,97 +38,85 @@ def setUp(self): } } } + return payload - def _set_up_private_project_comment_reports(self): - raise NotImplementedError - - def _set_up_public_project_comment_reports(self, comment_level='public'): - raise NotImplementedError + def test_private_node_view_reports_auth_misc(self, app, user, contributor, non_contributor, private_url): + # test_private_node_logged_out_user_cannot_view_reports + res = app.get(private_url, expect_errors=True) + assert res.status_code == 401 - def test_private_node_logged_out_user_cannot_view_reports(self): - self._set_up_private_project_comment_reports() - res = self.app.get(self.private_url, expect_errors=True) - assert_equal(res.status_code, 401) + # test_private_node_logged_in_non_contributor_cannot_view_reports + res = app.get(private_url, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 - def test_private_node_logged_in_non_contributor_cannot_view_reports(self): - self._set_up_private_project_comment_reports() - res = self.app.get(self.private_url, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - - def test_private_node_only_reporting_user_can_view_reports(self): - self._set_up_private_project_comment_reports() - res = self.app.get(self.private_url, auth=self.user.auth) - assert_equal(res.status_code, 200) + # test_private_node_only_reporting_user_can_view_reports + res = app.get(private_url, auth=user.auth) + assert res.status_code == 200 report_json = res.json['data'] report_ids = [report['id'] for report in report_json] - assert_equal(len(report_json), 1) - assert_in(self.user._id, report_ids) + assert len(report_json) == 1 + assert user._id in report_ids - def test_private_node_reported_user_does_not_see_report(self): - self._set_up_private_project_comment_reports() - res = self.app.get(self.private_url, auth=self.contributor.auth) - assert_equal(res.status_code, 200) + # test_private_node_reported_user_does_not_see_report + res = app.get(private_url, auth=contributor.auth) + assert res.status_code == 200 report_json = res.json['data'] report_ids = [report['id'] for report in report_json] - assert_equal(len(report_json), 0) - assert_not_in(self.contributor._id, report_ids) + assert len(report_json) == 0 + assert contributor._id not in report_ids + + def test_public_node_view_report_auth_misc(self, app, user, contributor, non_contributor, public_url): + # test_public_node_logged_out_user_cannot_view_reports + res = app.get(public_url, expect_errors=True) + assert res.status_code == 401 - def test_public_node_only_reporting_contributor_can_view_report(self): - self._set_up_public_project_comment_reports() - res = self.app.get(self.public_url, auth=self.user.auth) - assert_equal(res.status_code, 200) + # test_public_node_only_reporting_contributor_can_view_report + res = app.get(public_url, auth=user.auth) + assert res.status_code == 200 report_json = res.json['data'] report_ids = [report['id'] for report in report_json] - assert_equal(len(report_json), 1) - assert_in(self.user._id, report_ids) + assert len(report_json) == 1 + assert user._id in report_ids - def test_public_node_reported_user_does_not_see_report(self): - self._set_up_public_project_comment_reports() - res = self.app.get(self.public_url, auth=self.contributor.auth) - assert_equal(res.status_code, 200) + # test_public_node_reported_user_does_not_see_report + res = app.get(public_url, auth=contributor.auth) + assert res.status_code == 200 report_json = res.json['data'] report_ids = [report['id'] for report in report_json] - assert_equal(len(report_json), 0) - assert_not_in(self.contributor._id, report_ids) + assert len(report_json) == 0 + assert contributor._id not in report_ids - def test_public_node_non_contributor_does_not_see_other_user_reports(self): - self._set_up_public_project_comment_reports() - res = self.app.get(self.public_url, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 200) + # test_public_node_non_contributor_does_not_see_other_user_reports + res = app.get(public_url, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 200 report_json = res.json['data'] report_ids = [report['id'] for report in report_json] - assert_equal(len(report_json), 0) - assert_not_in(self.non_contributor._id, report_ids) + assert len(report_json) == 0 + assert non_contributor._id not in report_ids - def test_public_node_non_contributor_reporter_can_view_own_report(self): - self._set_up_public_project_comment_reports() - self.public_comment.reports[self.non_contributor._id] = { + def test_public_node_non_contributor_reporter_can_view_own_report(self, app, non_contributor, public_comment, public_url): + public_comment.reports[non_contributor._id] = { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, } - self.public_comment.save() - res = self.app.get(self.public_url, auth=self.non_contributor.auth) - assert_equal(res.status_code, 200) + public_comment.save() + res = app.get(public_url, auth=non_contributor.auth) + assert res.status_code == 200 report_json = res.json['data'] report_ids = [report['id'] for report in report_json] - assert_equal(len(report_json), 1) - assert_in(self.non_contributor._id, report_ids) - - def test_public_node_logged_out_user_cannot_view_reports(self): - self._set_up_public_project_comment_reports() - res = self.app.get(self.public_url, expect_errors=True) - assert_equal(res.status_code, 401) - - def test_public_node_private_comment_level_non_contributor_cannot_see_reports(self): - self._set_up_public_project_comment_reports(comment_level='private') - res = self.app.get(self.public_url, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - assert_equal(res.json['errors'][0]['detail'], 'You do not have permission to perform this action.') - - def test_report_comment_invalid_type(self): - self._set_up_private_project_comment_reports() + assert len(report_json) == 1 + assert non_contributor._id in report_ids + + @pytest.mark.parametrize('comment_level', ['private']) + def test_public_node_private_comment_level_non_contributor_cannot_see_reports(self, app, non_contributor, public_url, comment_level): + res = app.get(public_url, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + + def test_invalid_report_comment(self, app, user, private_url): + # test_report_comment_invalid_type payload = { 'data': { 'type': 'Not a valid type.', @@ -129,11 +126,10 @@ def test_report_comment_invalid_type(self): } } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 409) + res = app.post_json_api(private_url, payload, auth=user.auth, expect_errors=True) + assert res.status_code == 409 - def test_report_comment_no_type(self): - self._set_up_private_project_comment_reports() + # test_report_comment_no_type payload = { 'data': { 'type': '', @@ -143,13 +139,12 @@ def test_report_comment_no_type(self): } } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], 'This field may not be blank.') - assert_equal(res.json['errors'][0]['source']['pointer'], '/data/type') + res = app.post_json_api(private_url, payload, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'This field may not be blank.' + assert res.json['errors'][0]['source']['pointer'] == '/data/type' - def test_report_comment_invalid_spam_category(self): - self._set_up_private_project_comment_reports() + # test_report_comment_invalid_spam_category category = 'Not a valid category' payload = { 'data': { @@ -160,14 +155,14 @@ def test_report_comment_invalid_spam_category(self): } } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], '\"' + category + '\"' + ' is not a valid choice.') + res = app.post_json_api(private_url, payload, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == '\"' + category + '\"' + ' is not a valid choice.' - def test_report_comment_allow_blank_message(self): - self._set_up_private_project_comment_reports() - comment = CommentFactory(node=self.private_project, user=self.contributor, target=self.comment.target) - url = '/{}comments/{}/reports/'.format(API_BASE, comment._id) + def test_report_comment_allow_blank_message(self, app, user, contributor, private_project, comment): + + comment_new = CommentFactory(node=private_project, user=contributor, target=comment.target) + url = '/{}comments/{}/reports/'.format(API_BASE, comment_new._id) payload = { 'data': { 'type': 'comment_reports', @@ -177,168 +172,242 @@ def test_report_comment_allow_blank_message(self): } } } - res = self.app.post_json_api(url, payload, auth=self.user.auth) - assert_equal(res.status_code, 201) - assert_equal(res.json['data']['id'], self.user._id) - assert_equal(res.json['data']['attributes']['message'], payload['data']['attributes']['message']) - - def test_private_node_logged_out_user_cannot_report_comment(self): - self._set_up_private_project_comment_reports() - res = self.app.post_json_api(self.private_url, self.payload, expect_errors=True) - assert_equal(res.status_code, 401) - - def test_private_node_logged_in_non_contributor_cannot_report_comment(self): - self._set_up_private_project_comment_reports() - res = self.app.post_json_api(self.private_url, self.payload, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - - def test_private_node_logged_in_contributor_can_report_comment(self): - self._set_up_private_project_comment_reports() - comment = CommentFactory(node=self.private_project, user=self.contributor, target=self.comment.target) - url = '/{}comments/{}/reports/'.format(API_BASE, comment._id) - res = self.app.post_json_api(url, self.payload, auth=self.user.auth) - assert_equal(res.status_code, 201) - assert_equal(res.json['data']['id'], self.user._id) - - def test_user_cannot_report_own_comment(self): - self._set_up_private_project_comment_reports() - res = self.app.post_json_api(self.private_url, self.payload, auth=self.contributor.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], 'You cannot report your own comment.') - - def test_user_cannot_report_comment_twice(self): - self._set_up_private_project_comment_reports() + res = app.post_json_api(url, payload, auth=user.auth) + assert res.status_code == 201 + assert res.json['data']['id'] == user._id + assert res.json['data']['attributes']['message'] == payload['data']['attributes']['message'] + + def test_private_node_report_comment_auth_misc(self, app, user, contributor, non_contributor, private_project, private_url, comment, payload): + + # test_private_node_logged_out_user_cannot_report_comment + res = app.post_json_api(private_url, payload, expect_errors=True) + assert res.status_code == 401 + + # test_private_node_logged_in_non_contributor_cannot_report_comment + res = app.post_json_api(private_url, payload, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + + # test_private_node_logged_in_contributor_can_report_comment + comment_new = CommentFactory(node=private_project, user=contributor, target=comment.target) + url = '/{}comments/{}/reports/'.format(API_BASE, comment_new._id) + res = app.post_json_api(url, payload, auth=user.auth) + assert res.status_code == 201 + assert res.json['data']['id'] == user._id + + def test_user_cannot_report_comment_condition(self, app, user, contributor, private_url, payload): + # test_user_cannot_report_own_comment + res = app.post_json_api(private_url, payload, auth=contributor.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'You cannot report your own comment.' + + # test_user_cannot_report_comment_twice # User cannot report the comment again - res = self.app.post_json_api(self.private_url, self.payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], 'Comment already reported.') - - def test_public_node_logged_out_user_cannot_report_comment(self): - self._set_up_public_project_comment_reports() - res = self.app.post_json_api(self.public_url, self.payload, expect_errors=True) - assert_equal(res.status_code, 401) - - def test_public_node_contributor_can_report_comment(self): - self._set_up_public_project_comment_reports() - comment = CommentFactory(node=self.public_project, user=self.contributor, target=self.public_comment.target) - url = '/{}comments/{}/reports/'.format(API_BASE, comment._id) + res = app.post_json_api(private_url, payload, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'Comment already reported.' + + def test_public_node_report_comment_auth_misc(self, app, user, contributor, non_contributor, public_project, public_url, public_comment, payload): + # def test_public_node_logged_out_user_cannot_report_comment(self): + res = app.post_json_api(public_url, payload, expect_errors=True) + assert res.status_code == 401 - res = self.app.post_json_api(url, self.payload, auth=self.user.auth) - assert_equal(res.status_code, 201) - assert_equal(res.json['data']['id'], self.user._id) + # def test_public_node_contributor_can_report_comment(self): + comment = CommentFactory(node=public_project, user=contributor, target=public_comment.target) + url = '/{}comments/{}/reports/'.format(API_BASE, comment._id) + res = app.post_json_api(url, payload, auth=user.auth) + assert res.status_code == 201 + assert res.json['data']['id'] == user._id - def test_public_node_non_contributor_can_report_comment(self): + # def test_public_node_non_contributor_can_report_comment(self): """ Test that when a public project allows any osf user to comment (comment_level == 'public), non-contributors can also report comments. """ - self._set_up_public_project_comment_reports() - res = self.app.post_json_api(self.public_url, self.payload, auth=self.non_contributor.auth) - assert_equal(res.status_code, 201) - assert_equal(res.json['data']['id'], self.non_contributor._id) - - def test_public_node_private_comment_level_non_contributor_cannot_report_comment(self): - self._set_up_public_project_comment_reports(comment_level='private') - res = self.app.get(self.public_url, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - assert_equal(res.json['errors'][0]['detail'], 'You do not have permission to perform this action.') - - -class TestCommentReportsView(CommentReportsMixin, ApiTestCase): - - def _set_up_private_project_comment_reports(self): - self.private_project = ProjectFactory.create(is_public=False, creator=self.user) - self.private_project.add_contributor(contributor=self.contributor, save=True) - self.comment = CommentFactory.build(node=self.private_project, user=self.contributor) - self.comment.reports = self.comment.reports or {} - self.comment.reports[self.user._id] = { + res = app.post_json_api(public_url, payload, auth=non_contributor.auth) + assert res.status_code == 201 + assert res.json['data']['id'] == non_contributor._id + + @pytest.mark.parametrize('comment_level', ['private']) + def test_public_node_private_comment_level_non_contributor_cannot_report_comment(self, app, non_contributor, comment_level, public_url): + res = app.get(public_url, auth=non_contributor.auth, expect_errors=True) + assert res.status_code == 403 + assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + +class TestCommentReportsView(CommentReportsMixin): + # private_project_comment_reports + @pytest.fixture() + def private_project(self, user, contributor): + private_project = ProjectFactory.create(is_public=False, creator=user) + private_project.add_contributor(contributor=contributor, save=True) + return private_project + + @pytest.fixture() + def comment(self, user, contributor, private_project): + comment = CommentFactory(node=private_project, user=contributor) + comment.reports = comment.reports or {} + comment.reports[user._id] = { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, } - self.comment.save() - self.private_url = '/{}comments/{}/reports/'.format(API_BASE, self.comment._id) - - def _set_up_public_project_comment_reports(self, comment_level='public'): - self.public_project = ProjectFactory.create(is_public=True, creator=self.user, comment_level=comment_level) - self.public_project.add_contributor(contributor=self.contributor, save=True) - self.public_comment = CommentFactory.build(node=self.public_project, user=self.contributor) - self.public_comment.reports = self.public_comment.reports or {} - self.public_comment.reports[self.user._id] = { + comment.save() + return comment + + @pytest.fixture() + def private_url(self, user, comment): + return '/{}comments/{}/reports/'.format(API_BASE, comment._id) + + # public_project_comment_reports + @pytest.fixture() + def public_project(self, user, contributor, comment_level): + public_project = ProjectFactory.create(is_public=True, creator=user, comment_level=comment_level) + public_project.add_contributor(contributor=contributor, save=True) + return public_project + + @pytest.fixture() + def public_comment(self, user, contributor, public_project): + public_comment = CommentFactory(node=public_project, user=contributor) + public_comment.reports = public_comment.reports or {} + public_comment.reports[user._id] = { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, } - self.public_comment.save() - self.public_url = '/{}comments/{}/reports/'.format(API_BASE, self.public_comment._id) + public_comment.save() + return public_comment + + @pytest.fixture() + def public_url(self, user, public_comment): + return '/{}comments/{}/reports/'.format(API_BASE, public_comment._id) + + @pytest.fixture() + def comment_level(self): + return 'public' +class TestWikiCommentReportsView(CommentReportsMixin): -class TestWikiCommentReportsView(CommentReportsMixin, ApiTestCase): + # private_project_comment_reports + @pytest.fixture() + def private_project(self, user, contributor): + private_project = ProjectFactory.create(is_public=False, creator=user) + private_project.add_contributor(contributor=contributor, save=True) + return private_project - def _set_up_private_project_comment_reports(self): - self.private_project = ProjectFactory.create(is_public=False, creator=self.user) - self.private_project.add_contributor(contributor=self.contributor, save=True) + @pytest.fixture() + def wiki(self, user, private_project): with mock.patch('osf.models.AbstractNode.update_search'): - self.wiki = NodeWikiFactory(node=self.private_project, user=self.user) - self.comment = CommentFactory.build(node=self.private_project, target=Guid.load(self.wiki._id), user=self.contributor) - self.comment.reports = self.comment.reports or {} - self.comment.reports[self.user._id] = { + return NodeWikiFactory(node=private_project, user=user) + + @pytest.fixture() + def comment(self, user, contributor, private_project, wiki): + comment = CommentFactory(node=private_project, target=Guid.load(wiki._id), user=contributor) + comment.reports = comment.reports or {} + comment.reports[user._id] = { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, } - self.comment.save() - self.private_url = '/{}comments/{}/reports/'.format(API_BASE, self.comment._id) - - def _set_up_public_project_comment_reports(self, comment_level='public'): - self.public_project = ProjectFactory.create(is_public=True, creator=self.user, comment_level=comment_level) - self.public_project.add_contributor(contributor=self.contributor, save=True) + comment.save() + return comment + + @pytest.fixture() + def private_url(self, user, comment): + return '/{}comments/{}/reports/'.format(API_BASE, comment._id) + + # public_project_comment_reports + @pytest.fixture() + def public_project(self, user, contributor, comment_level): + public_project = ProjectFactory.create(is_public=True, creator=user, comment_level=comment_level) + public_project.add_contributor(contributor=contributor, save=True) + return public_project + + @pytest.fixture() + def public_wiki(self, user, public_project): with mock.patch('osf.models.AbstractNode.update_search'): - self.public_wiki = NodeWikiFactory(node=self.public_project, user=self.user) - self.public_comment = CommentFactory.build(node=self.public_project, target=Guid.load(self.public_wiki._id), user=self.contributor) - self.public_comment.reports = self.public_comment.reports or {} - self.public_comment.reports[self.user._id] = { + return NodeWikiFactory(node=public_project, user=user) + + @pytest.fixture() + def public_comment(self, user, contributor, public_project, public_wiki): + public_comment = CommentFactory(node=public_project, target=Guid.load(public_wiki._id), user=contributor) + public_comment.reports = public_comment.reports or {} + public_comment.reports[user._id] = { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, } - self.public_comment.save() - self.public_url = '/{}comments/{}/reports/'.format(API_BASE, self.public_comment._id) - -class TestFileCommentReportsView(CommentReportsMixin, ApiTestCase): - - def _set_up_private_project_comment_reports(self): - self.private_project = ProjectFactory.create(is_public=False, creator=self.user) - self.private_project.add_contributor(contributor=self.contributor, save=True) - self.file = test_utils.create_test_file(self.private_project, self.user) - self.comment = CommentFactory.build(node=self.private_project, target=self.file.get_guid(), user=self.contributor) - self.comment.reports = self.comment.reports or {} - self.comment.reports[self.user._id] = { + public_comment.save() + return public_comment + + @pytest.fixture() + def public_url(self, user, public_comment): + return '/{}comments/{}/reports/'.format(API_BASE, public_comment._id) + + @pytest.fixture() + def comment_level(self): + return 'public' + +class TestFileCommentReportsView(CommentReportsMixin): + + # private_project_comment_reports + @pytest.fixture() + def private_project(self, user, contributor): + private_project = ProjectFactory.create(is_public=False, creator=user) + private_project.add_contributor(contributor=contributor, save=True) + return private_project + + @pytest.fixture() + def file(self, user, private_project): + return test_utils.create_test_file(private_project, user) + + @pytest.fixture() + def comment(self, user, contributor, private_project, file): + comment = CommentFactory(node=private_project, target=file.get_guid(), user=contributor) + comment.reports = comment.reports or {} + comment.reports[user._id] = { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, } - self.comment.save() - self.private_url = '/{}comments/{}/reports/'.format(API_BASE, self.comment._id) - - def _set_up_public_project_comment_reports(self, comment_level='public'): - self.public_project = ProjectFactory.create(is_public=True, creator=self.user, comment_level=comment_level) - self.public_project.add_contributor(contributor=self.contributor, save=True) - self.public_file = test_utils.create_test_file(self.public_project, self.user) - self.public_comment = CommentFactory.build(node=self.public_project, target=self.public_file.get_guid(), user=self.contributor) - self.public_comment.reports = self.public_comment.reports or {} - self.public_comment.reports[self.user._id] = { + comment.save() + return comment + + @pytest.fixture() + def private_url(self, user, comment): + return '/{}comments/{}/reports/'.format(API_BASE, comment._id) + + # public_project_comment_reports + @pytest.fixture() + def public_project(self, user, contributor, comment_level): + public_project = ProjectFactory.create(is_public=True, creator=user, comment_level=comment_level) + public_project.add_contributor(contributor=contributor, save=True) + return public_project + + @pytest.fixture() + def public_file(self, user, public_project): + return test_utils.create_test_file(public_project, user) + + @pytest.fixture() + def public_comment(self, user, contributor, public_project, public_file): + public_comment = CommentFactory(node=public_project, target=public_file.get_guid(), user=contributor) + public_comment.reports = public_comment.reports or {} + public_comment.reports[user._id] = { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, } - self.public_comment.save() - self.public_url = '/{}comments/{}/reports/'.format(API_BASE, self.public_comment._id) + public_comment.save() + return public_comment + @pytest.fixture() + def public_url(self, user, public_comment): + return '/{}comments/{}/reports/'.format(API_BASE, public_comment._id) + @pytest.fixture() + def comment_level(self): + return 'public' From 02632a95562336e16b2690753c96be8fbb3db0cd Mon Sep 17 00:00:00 2001 From: Jerry Sun Date: Fri, 2 Jun 2017 13:46:47 -0400 Subject: [PATCH 03/62] Check if subclass implements necessary features --- .../comments/views/test_comment_detail.py | 2 +- .../views/test_comment_report_list.py | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/api_tests/comments/views/test_comment_detail.py b/api_tests/comments/views/test_comment_detail.py index 7dd8486f49f..fdd4eb1c919 100644 --- a/api_tests/comments/views/test_comment_detail.py +++ b/api_tests/comments/views/test_comment_detail.py @@ -34,7 +34,7 @@ def contributor(self): def non_contributor(self): return AuthUserFactory() - # private_project_with_comments + # check if all necessary fixtures are setup by subclass @pytest.fixture() def private_project(self): raise NotImplementedError diff --git a/api_tests/comments/views/test_comment_report_list.py b/api_tests/comments/views/test_comment_report_list.py index 72dd2590706..2555f100b83 100644 --- a/api_tests/comments/views/test_comment_report_list.py +++ b/api_tests/comments/views/test_comment_report_list.py @@ -40,6 +40,35 @@ def payload(self, user): } return payload + # check if all necessary features are setup in subclass + @pytest.fixture() + def private_project(self): + raise NotImplementedError + + @pytest.fixture() + def comment(self): + raise NotImplementedError + + @pytest.fixture() + def private_url(self): + raise NotImplementedError + + @pytest.fixture() + def public_project(self): + raise NotImplementedError + + @pytest.fixture() + def public_comment(self): + raise NotImplementedError + + @pytest.fixture() + def public_url(self): + raise NotImplementedError + + @pytest.fixture() + def comment_level(self): + raise NotImplementedError + def test_private_node_view_reports_auth_misc(self, app, user, contributor, non_contributor, private_url): # test_private_node_logged_out_user_cannot_view_reports res = app.get(private_url, expect_errors=True) From 89490327828e1045a3b9f50d05893d95365e104a Mon Sep 17 00:00:00 2001 From: Jerry Sun Date: Fri, 2 Jun 2017 13:50:27 -0400 Subject: [PATCH 04/62] Fix import conflicts for Guid --- api_tests/comments/views/test_comment_report_detail.py | 2 +- api_tests/comments/views/test_comment_report_list.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api_tests/comments/views/test_comment_report_detail.py b/api_tests/comments/views/test_comment_report_detail.py index 0e26347ef80..1d2d96b0381 100644 --- a/api_tests/comments/views/test_comment_report_detail.py +++ b/api_tests/comments/views/test_comment_report_detail.py @@ -4,7 +4,7 @@ from django.utils import timezone from datetime import datetime -from framework.guid.model import Guid +from osf.model import Guid from api.base.settings.defaults import API_BASE from api_tests import utils as test_utils from tests.base import ApiTestCase diff --git a/api_tests/comments/views/test_comment_report_list.py b/api_tests/comments/views/test_comment_report_list.py index 2555f100b83..42b6d952fbb 100644 --- a/api_tests/comments/views/test_comment_report_list.py +++ b/api_tests/comments/views/test_comment_report_list.py @@ -4,7 +4,7 @@ from django.utils import timezone from datetime import datetime -from framework.guid.model import Guid +from osf.model import Guid from api.base.settings.defaults import API_BASE from api_tests import utils as test_utils from tests.base import ApiTestCase From c49d28ba2cad6fd320ac53858657dd4c3c54bbc5 Mon Sep 17 00:00:00 2001 From: Jerry Sun Date: Fri, 2 Jun 2017 13:52:05 -0400 Subject: [PATCH 05/62] Fix import conflicts for Guid --- api_tests/comments/views/test_comment_report_detail.py | 2 +- api_tests/comments/views/test_comment_report_list.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api_tests/comments/views/test_comment_report_detail.py b/api_tests/comments/views/test_comment_report_detail.py index 1d2d96b0381..941f9472a0a 100644 --- a/api_tests/comments/views/test_comment_report_detail.py +++ b/api_tests/comments/views/test_comment_report_detail.py @@ -4,7 +4,7 @@ from django.utils import timezone from datetime import datetime -from osf.model import Guid +from osf.models import Guid from api.base.settings.defaults import API_BASE from api_tests import utils as test_utils from tests.base import ApiTestCase diff --git a/api_tests/comments/views/test_comment_report_list.py b/api_tests/comments/views/test_comment_report_list.py index 42b6d952fbb..6f4fa1a012d 100644 --- a/api_tests/comments/views/test_comment_report_list.py +++ b/api_tests/comments/views/test_comment_report_list.py @@ -4,7 +4,7 @@ from django.utils import timezone from datetime import datetime -from osf.model import Guid +from osf.models import Guid from api.base.settings.defaults import API_BASE from api_tests import utils as test_utils from tests.base import ApiTestCase From 8aa1105a4f54fa2b18d5f7490ab90cca594dee63 Mon Sep 17 00:00:00 2001 From: Jerry Sun Date: Fri, 2 Jun 2017 13:53:11 -0400 Subject: [PATCH 06/62] Fix import conflicts for Guid --- api_tests/comments/views/test_comment_report_detail.py | 1 + api_tests/comments/views/test_comment_report_list.py | 1 + 2 files changed, 2 insertions(+) diff --git a/api_tests/comments/views/test_comment_report_detail.py b/api_tests/comments/views/test_comment_report_detail.py index 941f9472a0a..bcb9ba0e180 100644 --- a/api_tests/comments/views/test_comment_report_detail.py +++ b/api_tests/comments/views/test_comment_report_detail.py @@ -5,6 +5,7 @@ from datetime import datetime from osf.models import Guid + from api.base.settings.defaults import API_BASE from api_tests import utils as test_utils from tests.base import ApiTestCase diff --git a/api_tests/comments/views/test_comment_report_list.py b/api_tests/comments/views/test_comment_report_list.py index 6f4fa1a012d..1c63a59a03e 100644 --- a/api_tests/comments/views/test_comment_report_list.py +++ b/api_tests/comments/views/test_comment_report_list.py @@ -5,6 +5,7 @@ from datetime import datetime from osf.models import Guid + from api.base.settings.defaults import API_BASE from api_tests import utils as test_utils from tests.base import ApiTestCase From 3de533e8601d43046440a0f04367b5d32ced015f Mon Sep 17 00:00:00 2001 From: Jerry Sun Date: Fri, 2 Jun 2017 14:02:33 -0400 Subject: [PATCH 07/62] Fix import conflicts for Guid --- api_tests/comments/views/test_comment_detail.py | 1 - api_tests/comments/views/test_comment_report_detail.py | 1 - api_tests/comments/views/test_comment_report_list.py | 1 - 3 files changed, 3 deletions(-) diff --git a/api_tests/comments/views/test_comment_detail.py b/api_tests/comments/views/test_comment_detail.py index fdd4eb1c919..6acf78fc01c 100644 --- a/api_tests/comments/views/test_comment_detail.py +++ b/api_tests/comments/views/test_comment_detail.py @@ -2,7 +2,6 @@ import mock from urlparse import urlparse - from framework.auth import core from framework.guid.model import Guid diff --git a/api_tests/comments/views/test_comment_report_detail.py b/api_tests/comments/views/test_comment_report_detail.py index bcb9ba0e180..941f9472a0a 100644 --- a/api_tests/comments/views/test_comment_report_detail.py +++ b/api_tests/comments/views/test_comment_report_detail.py @@ -5,7 +5,6 @@ from datetime import datetime from osf.models import Guid - from api.base.settings.defaults import API_BASE from api_tests import utils as test_utils from tests.base import ApiTestCase diff --git a/api_tests/comments/views/test_comment_report_list.py b/api_tests/comments/views/test_comment_report_list.py index 1c63a59a03e..6f4fa1a012d 100644 --- a/api_tests/comments/views/test_comment_report_list.py +++ b/api_tests/comments/views/test_comment_report_list.py @@ -5,7 +5,6 @@ from datetime import datetime from osf.models import Guid - from api.base.settings.defaults import API_BASE from api_tests import utils as test_utils from tests.base import ApiTestCase From b0ac16d7f98f5c8bbd035980c24dae03365f2884 Mon Sep 17 00:00:00 2001 From: Jerry Sun Date: Fri, 2 Jun 2017 14:05:20 -0400 Subject: [PATCH 08/62] Fix import conflicts for Guid --- api_tests/comments/views/test_comment_detail.py | 3 +-- api_tests/comments/views/test_comment_report_detail.py | 1 - api_tests/comments/views/test_comment_report_list.py | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/api_tests/comments/views/test_comment_detail.py b/api_tests/comments/views/test_comment_detail.py index fdd4eb1c919..1d8f72760f6 100644 --- a/api_tests/comments/views/test_comment_detail.py +++ b/api_tests/comments/views/test_comment_detail.py @@ -4,8 +4,7 @@ from urlparse import urlparse from framework.auth import core -from framework.guid.model import Guid - +from osf.models import Guid from api.base.settings.defaults import API_BASE from api.base.settings import osf_settings from api_tests import utils as test_utils diff --git a/api_tests/comments/views/test_comment_report_detail.py b/api_tests/comments/views/test_comment_report_detail.py index bcb9ba0e180..941f9472a0a 100644 --- a/api_tests/comments/views/test_comment_report_detail.py +++ b/api_tests/comments/views/test_comment_report_detail.py @@ -5,7 +5,6 @@ from datetime import datetime from osf.models import Guid - from api.base.settings.defaults import API_BASE from api_tests import utils as test_utils from tests.base import ApiTestCase diff --git a/api_tests/comments/views/test_comment_report_list.py b/api_tests/comments/views/test_comment_report_list.py index 1c63a59a03e..6f4fa1a012d 100644 --- a/api_tests/comments/views/test_comment_report_list.py +++ b/api_tests/comments/views/test_comment_report_list.py @@ -5,7 +5,6 @@ from datetime import datetime from osf.models import Guid - from api.base.settings.defaults import API_BASE from api_tests import utils as test_utils from tests.base import ApiTestCase From 0557e5782b82e9f376fb95f329c1588f64a2ac72 Mon Sep 17 00:00:00 2001 From: Jerry Sun Date: Fri, 2 Jun 2017 14:06:24 -0400 Subject: [PATCH 09/62] Fix import conflicts for Guid --- api_tests/comments/views/test_comment_detail.py | 1 + 1 file changed, 1 insertion(+) diff --git a/api_tests/comments/views/test_comment_detail.py b/api_tests/comments/views/test_comment_detail.py index bbdff744051..1d8f72760f6 100644 --- a/api_tests/comments/views/test_comment_detail.py +++ b/api_tests/comments/views/test_comment_detail.py @@ -2,6 +2,7 @@ import mock from urlparse import urlparse + from framework.auth import core from osf.models import Guid from api.base.settings.defaults import API_BASE From eead2834a5e2dccab610c83a659a3975f9911e68 Mon Sep 17 00:00:00 2001 From: Rheisen Dennis Date: Tue, 6 Jun 2017 11:19:14 -0400 Subject: [PATCH 10/62] add rest_framework/exceptions, clean import statements, modify fixtures --- .../comments/views/test_comment_detail.py | 141 ++++++++++-------- .../views/test_comment_report_detail.py | 3 +- .../views/test_comment_report_list.py | 8 +- 3 files changed, 85 insertions(+), 67 deletions(-) diff --git a/api_tests/comments/views/test_comment_detail.py b/api_tests/comments/views/test_comment_detail.py index 201a70228d8..b9450ca3469 100644 --- a/api_tests/comments/views/test_comment_detail.py +++ b/api_tests/comments/views/test_comment_detail.py @@ -2,6 +2,7 @@ import mock from urlparse import urlparse +from rest_framework import exceptions from framework.auth import core from osf.models import Guid from api.base.settings.defaults import API_BASE @@ -95,22 +96,40 @@ def registration_comment_reply(self): def replies_url(self): raise NotImplementedError - - def _set_up_payload(self, target_id, content='test', has_content=True): - payload = { - 'data': { - 'id': target_id, - 'type': 'comments', - 'attributes': { - 'content': 'Updating this comment', - 'deleted': False + @pytest.fixture() + def set_up_payload(self): + def payload(target_id, content='test', has_content=True): + payload = { + 'data': { + 'id': target_id, + 'type': 'comments', + 'attributes': { + 'content': 'Updating this comment', + 'deleted': False + } } } - } - if has_content: - payload['data']['attributes']['content'] = content + if has_content: + payload['data']['attributes']['content'] = content + return payload return payload + + # def _set_up_payload(self, target_id, content='test', has_content=True): + # payload = { + # 'data': { + # 'id': target_id, + # 'type': 'comments', + # 'attributes': { + # 'content': 'Updating this comment', + # 'deleted': False + # } + # } + # } + # if has_content: + # payload['data']['attributes']['content'] = content + # return payload + def test_private_node_comments_related_auth(self, app, user, contributor, non_contributor, comment, private_url): # test_private_node_logged_in_contributor_can_view_comment res = app.get(private_url, auth=user.auth) @@ -121,12 +140,12 @@ def test_private_node_comments_related_auth(self, app, user, contributor, non_co # def test_private_node_logged_in_non_contributor_cannot_view_comment res = app.get(private_url, auth=non_contributor.auth, expect_errors=True) assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail # def test_private_node_logged_out_user_cannot_view_comment res = app.get(private_url, expect_errors=True) assert res.status_code == 401 - assert res.json['errors'][0]['detail'] == 'Authentication credentials were not provided.' + assert res.json['errors'][0]['detail'] == exceptions.NotAuthenticated.default_detail def test_private_node_user_with_private_and_anonymous_link_misc(self, app, private_project, comment): # def test_private_node_user_with_private_link_can_see_comment @@ -230,12 +249,12 @@ def test_private_node_comment_auth_misc(self, app, user, non_contributor, privat # test_private_node_logged_in_non_contributor_cannot_update_comment res = app.put_json_api(private_url, payload, auth=non_contributor.auth, expect_errors=True) assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail # test_private_node_logged_out_user_cannot_update_comment res = app.put_json_api(private_url, payload, expect_errors=True) assert res.status_code == 401 - assert res.json['errors'][0]['detail'] == 'Authentication credentials were not provided.' + assert res.json['errors'][0]['detail'] == exceptions.NotAuthenticated.default_detail def test_public_node_comment_auth_misc(self, app, user, contributor, non_contributor, public_url, public_comment, public_comment_payload): # test_public_node_only_contributor_commenter_can_update_comment @@ -246,29 +265,29 @@ def test_public_node_comment_auth_misc(self, app, user, contributor, non_contrib # test_public_node_contributor_cannot_update_other_users_comment res = app.put_json_api(public_url, public_comment_payload, auth=contributor.auth, expect_errors=True) assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail # test_public_node_non_contributor_cannot_update_other_users_comment res = app.put_json_api(public_url, public_comment_payload, auth=non_contributor.auth, expect_errors=True) assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail # test_public_node_logged_out_user_cannot_update_comment res = app.put_json_api(public_url, public_comment_payload, expect_errors=True) assert res.status_code == 401 - assert res.json['errors'][0]['detail'] == 'Authentication credentials were not provided.' + assert res.json['errors'][0]['detail'] == exceptions.NotAuthenticated.default_detail - def test_update_comment_misc(self, app, user, private_url, comment): + def test_update_comment_misc(self, app, user, private_url, comment, set_up_payload): # test_update_comment_cannot_exceed_max_length content = ('c' * (osf_settings.COMMENT_MAXLENGTH + 3)) - payload = self._set_up_payload(comment._id, content=content) + payload = set_up_payload(comment._id, content=content) res = app.put_json_api(private_url, payload, auth=user.auth, expect_errors=True) assert res.status_code == 400 assert (res.json['errors'][0]['detail'] == 'Ensure this field has no more than {} characters.'.format(str(osf_settings.COMMENT_MAXLENGTH))) # test_update_comment_cannot_be_empty - payload = self._set_up_payload(comment._id, content='') + payload = set_up_payload(comment._id, content='') res = app.put_json_api(private_url, payload, auth=user.auth, expect_errors=True) assert res.status_code == 400 assert res.json['errors'][0]['detail'] == 'This field may not be blank.' @@ -284,13 +303,13 @@ def test_private_node_only_logged_in_contributor_commenter_can_delete_own_reply( res = app.delete_json_api(reply_url, auth=user.auth) assert res.status_code == 204 - def test_private_node_only_logged_in_contributor_commenter_can_undelete_own_reply(self, app, user, private_project, comment): + def test_private_node_only_logged_in_contributor_commenter_can_undelete_own_reply(self, app, user, private_project, comment, set_up_payload): reply_target = Guid.load(comment._id) reply = CommentFactory(node=private_project, target=reply_target, user=user) reply_url = '/{}comments/{}/'.format(API_BASE, reply._id) reply.is_deleted = True reply.save() - payload = self._set_up_payload(reply._id, has_content=False) + payload = set_up_payload(reply._id, has_content=False) res = app.patch_json_api(reply_url, payload, auth=user.auth) assert res.status_code == 200 assert not res.json['data']['attributes']['deleted'] @@ -300,12 +319,12 @@ def test_private_node_cannot_delete_comment_situation(self, app, user, contribut # def test_private_node_contributor_cannot_delete_other_users_comment(self): res = app.delete_json_api(private_url, auth=contributor.auth, expect_errors=True) assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail # def test_private_node_non_contributor_cannot_delete_comment(self): res = app.delete_json_api(private_url, auth=non_contributor.auth, expect_errors=True) assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail # def test_private_node_logged_out_user_cannot_delete_comment(self): res = app.delete_json_api(private_url, expect_errors=True) @@ -318,21 +337,21 @@ def test_private_node_cannot_delete_comment_situation(self, app, user, contribut assert res.status_code == 400 assert res.json['errors'][0]['detail'] == 'Comment already deleted.' - def test_private_node_only_logged_in_contributor_commenter_can_undelete_comment(self, app, user, comment): + def test_private_node_only_logged_in_contributor_commenter_can_undelete_comment(self, app, user, comment, set_up_payload): comment.is_deleted = True comment.save() url = '/{}comments/{}/'.format(API_BASE, comment._id) - payload = self._set_up_payload(comment._id, has_content=False) + payload = set_up_payload(comment._id, has_content=False) res = app.patch_json_api(url, payload, auth=user.auth) assert res.status_code == 200 assert not res.json['data']['attributes']['deleted'] assert res.json['data']['attributes']['content'] == comment.content - def test_private_node_cannot_undelete_comment_situation(self, app, user, contributor, non_contributor, comment): + def test_private_node_cannot_undelete_comment_situation(self, app, user, contributor, non_contributor, comment, set_up_payload): comment.is_deleted = True comment.save() url = '/{}comments/{}/'.format(API_BASE, comment._id) - payload = self._set_up_payload(comment._id, has_content=False) + payload = set_up_payload(comment._id, has_content=False) # test_private_node_contributor_cannot_undelete_other_users_comment res = app.patch_json_api(url, payload, auth=contributor.auth, expect_errors=True) @@ -354,17 +373,17 @@ def test_public_node_cannot_delete_comment_situations(self, app, user, contribut # test_public_node_contributor_cannot_delete_other_users_comment res = app.delete_json_api(public_url, auth=contributor.auth, expect_errors=True) assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail # test_public_node_non_contributor_cannot_delete_other_users_comment res = app.delete_json_api(public_url, auth=non_contributor.auth, expect_errors=True) assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail # test_public_node_logged_out_user_cannot_delete_comment res = app.delete_json_api(public_url, expect_errors=True) assert res.status_code == 401 - assert res.json['errors'][0]['detail'] == 'Authentication credentials were not provided.' + assert res.json['errors'][0]['detail'] == exceptions.NotAuthenticated.default_detail # test_public_node_user_cannot_delete_already_deleted_comment public_comment.is_deleted = True @@ -393,7 +412,7 @@ def test_private_node_deleted_comment_auth_misc(self, app, user, contributor, co url = '/{}comments/{}/'.format(API_BASE, comment._id) res = app.get(url, expect_errors=True) assert res.status_code == 401 - assert res.json['errors'][0]['detail'] == 'Authentication credentials were not provided.' + assert res.json['errors'][0]['detail'] == exceptions.NotAuthenticated.default_detail # test_private_node_view_only_link_user_cannot_see_deleted_comment private_link = PrivateLinkFactory(anonymous=False) @@ -467,8 +486,8 @@ def private_url(self, comment): return '/{}comments/{}/'.format(API_BASE, comment._id) @pytest.fixture() - def payload(self, comment): - return self._set_up_payload(comment._id) + def payload(self, comment, set_up_payload): + return set_up_payload(comment._id) # public_project_with_comments @pytest.fixture() @@ -491,8 +510,8 @@ def public_url(self, public_comment): return '/{}comments/{}/'.format(API_BASE, public_comment._id) @pytest.fixture() - def public_comment_payload(self, public_comment): - return self._set_up_payload(public_comment._id) + def public_comment_payload(self, public_comment, set_up_payload): + return set_up_payload(public_comment._id) # registration_with_comments @pytest.fixture() @@ -531,25 +550,25 @@ def test_comment_has_target_link_with_correct_type(self, app, public_url, public assert urlparse(url).path == expected_url assert target_type == expected_type - def test_public_node_non_contributor_commenter_can_update_comment(self, app, non_contributor): + def test_public_node_non_contributor_commenter_can_update_comment(self, app, non_contributor, set_up_payload): project = ProjectFactory(is_public=True, comment_level='public') comment = CommentFactory(node=project, user=non_contributor) url = '/{}comments/{}/'.format(API_BASE, comment._id) - payload = self._set_up_payload(comment._id) + payload = set_up_payload(comment._id) res = app.put_json_api(url, payload, auth=non_contributor.auth) assert res.status_code == 200 assert payload['data']['attributes']['content'] == res.json['data']['attributes']['content'] - def test_public_node_non_contributor_commenter_cannot_update_own_comment_if_comment_level_private(self, app, non_contributor): + def test_public_node_non_contributor_commenter_cannot_update_own_comment_if_comment_level_private(self, app, non_contributor, set_up_payload): project = ProjectFactory(is_public=True, comment_level='public') comment = CommentFactory(node=project, user=non_contributor) project.comment_level = 'private' project.save() url = '/{}comments/{}/'.format(API_BASE, comment._id) - payload = self._set_up_payload(comment._id) + payload = set_up_payload(comment._id) res = app.put_json_api(url, payload, auth=non_contributor.auth, expect_errors=True) assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail def test_public_node_non_contributor_commenter_can_delete_comment(self, app, non_contributor): project = ProjectFactory(is_public=True) @@ -605,8 +624,8 @@ def private_url(self, comment): return '/{}comments/{}/'.format(API_BASE, comment._id) @pytest.fixture() - def payload(self, comment): - return self._set_up_payload(comment._id) + def payload(self, comment, set_up_payload): + return set_up_payload(comment._id) # public_project_with_comments @pytest.fixture() @@ -633,8 +652,8 @@ def public_url(self, public_comment): return '/{}comments/{}/'.format(API_BASE, public_comment._id) @pytest.fixture() - def public_comment_payload(self, public_comment): - return self._set_up_payload(public_comment._id) + def public_comment_payload(self, public_comment, set_up_payload): + return set_up_payload(public_comment._id) # registration_with_comments @pytest.fixture() @@ -669,27 +688,27 @@ def test_file_comment_has_target_link_with_correct_type(self, app, public_url, p assert urlparse(url).path == expected_url assert target_type == expected_type - def test_public_node_non_contributor_commenter_can_update_file_comment(self, app, non_contributor): + def test_public_node_non_contributor_commenter_can_update_file_comment(self, app, non_contributor, set_up_payload): project = ProjectFactory(is_public=True) test_file = test_utils.create_test_file(project, project.creator) comment = CommentFactory(node=project, target=test_file.get_guid(), user=non_contributor) url = '/{}comments/{}/'.format(API_BASE, comment._id) - payload = self._set_up_payload(comment._id) + payload = set_up_payload(comment._id) res = app.put_json_api(url, payload, auth=non_contributor.auth) assert res.status_code == 200 assert payload['data']['attributes']['content'] == res.json['data']['attributes']['content'] - def test_public_node_non_contributor_commenter_cannot_update_own_file_comment_if_comment_level_private(self, app, non_contributor): + def test_public_node_non_contributor_commenter_cannot_update_own_file_comment_if_comment_level_private(self, app, non_contributor, set_up_payload): project = ProjectFactory(is_public=True) test_file = test_utils.create_test_file(project, project.creator) comment = CommentFactory(node=project, target=test_file.get_guid(), user=non_contributor) project.comment_level = 'private' project.save() url = '/{}comments/{}/'.format(API_BASE, comment._id) - payload = self._set_up_payload(comment._id) + payload = set_up_payload(comment._id) res = app.put_json_api(url, payload, auth=non_contributor.auth, expect_errors=True) assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail def test_public_node_non_contributor_commenter_can_delete_file_comment(self, app, non_contributor): project = ProjectFactory(is_public=True, comment_level='public') @@ -730,8 +749,8 @@ def private_url(self, comment): return '/{}comments/{}/'.format(API_BASE, comment._id) @pytest.fixture() - def payload(self, comment): - return self._set_up_payload(comment._id) + def payload(self, comment, set_up_payload): + return set_up_payload(comment._id) # public_project_with_comments @pytest.fixture() @@ -759,8 +778,8 @@ def public_url(self, public_comment): return '/{}comments/{}/'.format(API_BASE, public_comment._id) @pytest.fixture() - def public_comment_payload(self, public_comment): - return self._set_up_payload(public_comment._id) + def public_comment_payload(self, public_comment, set_up_payload): + return set_up_payload(public_comment._id) # registration_with_comments @pytest.fixture() @@ -795,27 +814,27 @@ def test_wiki_comment_has_target_link_with_correct_type(self, app, public_url, p assert url == expected_url assert target_type == expected_type - def test_public_node_non_contributor_commenter_can_update_wiki_comment(self, app, user, non_contributor, ): + def test_public_node_non_contributor_commenter_can_update_wiki_comment(self, app, user, non_contributor, set_up_payload): project = ProjectFactory(is_public=True) test_wiki = NodeWikiFactory(node=project, user=user) comment = CommentFactory(node=project, target=Guid.load(test_wiki._id), user=non_contributor) url = '/{}comments/{}/'.format(API_BASE, comment._id) - payload = self._set_up_payload(comment._id) + payload = set_up_payload(comment._id) res = app.put_json_api(url, payload, auth=non_contributor.auth) assert res.status_code == 200 assert payload['data']['attributes']['content'] == res.json['data']['attributes']['content'] - def test_public_node_non_contributor_commenter_cannot_update_own_wiki_comment_if_comment_level_private(self, app, user, non_contributor): + def test_public_node_non_contributor_commenter_cannot_update_own_wiki_comment_if_comment_level_private(self, app, user, non_contributor, set_up_payload): project = ProjectFactory(is_public=True) test_wiki = NodeWikiFactory(node=project, user=user) comment = CommentFactory(node=project, target=Guid.load(test_wiki._id), user=non_contributor) project.comment_level = 'private' project.save() url = '/{}comments/{}/'.format(API_BASE, comment._id) - payload = self._set_up_payload(comment._id) + payload = set_up_payload(comment._id) res = app.put_json_api(url, payload, auth=non_contributor.auth, expect_errors=True) assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail def test_public_node_non_contributor_commenter_can_delete_wiki_comment(self, app, user, non_contributor): project = ProjectFactory(is_public=True, comment_level='public') diff --git a/api_tests/comments/views/test_comment_report_detail.py b/api_tests/comments/views/test_comment_report_detail.py index 1e63c4e3146..6924ad112ac 100644 --- a/api_tests/comments/views/test_comment_report_detail.py +++ b/api_tests/comments/views/test_comment_report_detail.py @@ -27,7 +27,7 @@ def non_contributor(self): @pytest.fixture() def payload(self, user): - payload = { + return { 'data': { 'id': user._id, 'type': 'comment_reports', @@ -37,7 +37,6 @@ def payload(self, user): } } } - return payload # check if all necessary features are setup in subclass @pytest.fixture() diff --git a/api_tests/comments/views/test_comment_report_list.py b/api_tests/comments/views/test_comment_report_list.py index 26b6e672f22..1dc16fb54cd 100644 --- a/api_tests/comments/views/test_comment_report_list.py +++ b/api_tests/comments/views/test_comment_report_list.py @@ -3,6 +3,7 @@ from django.utils import timezone from datetime import datetime +from rest_framework import exceptions from osf.models import Guid from api.base.settings.defaults import API_BASE from api_tests import utils as test_utils @@ -27,7 +28,7 @@ def non_contributor(self): @pytest.fixture() def payload(self, user): - payload = { + return { 'data': { 'id': user._id, 'type': 'comment_reports', @@ -37,7 +38,6 @@ def payload(self, user): } } } - return payload # check if all necessary features are setup in subclass @pytest.fixture() @@ -141,7 +141,7 @@ def test_public_node_non_contributor_reporter_can_view_own_report(self, app, non def test_public_node_private_comment_level_non_contributor_cannot_see_reports(self, app, non_contributor, public_url, comment_level): res = app.get(public_url, auth=non_contributor.auth, expect_errors=True) assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail def test_invalid_report_comment(self, app, user, private_url): # test_report_comment_invalid_type @@ -259,7 +259,7 @@ def test_public_node_report_comment_auth_misc(self, app, user, contributor, non_ def test_public_node_private_comment_level_non_contributor_cannot_report_comment(self, app, non_contributor, comment_level, public_url): res = app.get(public_url, auth=non_contributor.auth, expect_errors=True) assert res.status_code == 403 - assert res.json['errors'][0]['detail'] == 'You do not have permission to perform this action.' + assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail class TestCommentReportsView(CommentReportsMixin): # private_project_comment_reports From c032b1556b0447fc8d8f642cfca42a91829d1e28 Mon Sep 17 00:00:00 2001 From: Rheisen Dennis Date: Wed, 21 Jun 2017 16:18:02 -0400 Subject: [PATCH 11/62] fix imports and follow naming conventions --- .../comments/views/test_comment_detail.py | 132 ++++++++---------- .../views/test_comment_report_detail.py | 83 +++++------ .../views/test_comment_report_list.py | 67 +++++---- 3 files changed, 138 insertions(+), 144 deletions(-) diff --git a/api_tests/comments/views/test_comment_detail.py b/api_tests/comments/views/test_comment_detail.py index b9450ca3469..1f0fa9a142b 100644 --- a/api_tests/comments/views/test_comment_detail.py +++ b/api_tests/comments/views/test_comment_detail.py @@ -1,15 +1,13 @@ -import pytest import mock +import pytest from urlparse import urlparse -from rest_framework import exceptions -from framework.auth import core -from osf.models import Guid +from addons.wiki.tests.factories import NodeWikiFactory from api.base.settings.defaults import API_BASE from api.base.settings import osf_settings from api_tests import utils as test_utils -from tests.base import ApiTestCase -from addons.wiki.tests.factories import NodeWikiFactory +from framework.auth import core +from osf.models import Guid from osf_tests.factories import ( ProjectFactory, AuthUserFactory, @@ -17,6 +15,8 @@ RegistrationFactory, PrivateLinkFactory, ) +from rest_framework import exceptions + @pytest.mark.django_db class CommentDetailMixin(object): @@ -30,7 +30,7 @@ def contributor(self): return AuthUserFactory() @pytest.fixture() - def non_contributor(self): + def non_contrib(self): return AuthUserFactory() # check if all necessary fixtures are setup by subclass @@ -114,31 +114,15 @@ def payload(target_id, content='test', has_content=True): return payload return payload - - # def _set_up_payload(self, target_id, content='test', has_content=True): - # payload = { - # 'data': { - # 'id': target_id, - # 'type': 'comments', - # 'attributes': { - # 'content': 'Updating this comment', - # 'deleted': False - # } - # } - # } - # if has_content: - # payload['data']['attributes']['content'] = content - # return payload - - def test_private_node_comments_related_auth(self, app, user, contributor, non_contributor, comment, private_url): + def test_private_node_comments_related_auth(self, app, user, contributor, non_contrib, comment, private_url): # test_private_node_logged_in_contributor_can_view_comment res = app.get(private_url, auth=user.auth) assert res.status_code == 200 assert comment._id == res.json['data']['id'] assert comment.content == res.json['data']['attributes']['content'] - # def test_private_node_logged_in_non_contributor_cannot_view_comment - res = app.get(private_url, auth=non_contributor.auth, expect_errors=True) + # def test_private_node_logged_in_non_contrib_cannot_view_comment + res = app.get(private_url, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail @@ -175,15 +159,15 @@ def test_private_node_user_with_private_and_anonymous_link_misc(self, app, priva assert comment._id == res.json['data']['id'] assert 'test with @A User and @mention' == res.json['data']['attributes']['content'] - def test_public_node_comment_auth_misc(self, app, user, non_contributor, public_project, public_url, public_comment, registration_comment, comment_url): + def test_public_node_comment_auth_misc(self, app, user, non_contrib, public_project, public_url, public_comment, registration_comment, comment_url): # test_public_node_logged_in_contributor_can_view_comment res = app.get(public_url, auth=user.auth) assert res.status_code == 200 assert public_comment._id == res.json['data']['id'] assert public_comment.content == res.json['data']['attributes']['content'] - # test_public_node_logged_in_non_contributor_can_view_comment - res = app.get(public_url, auth=non_contributor.auth) + # test_public_node_logged_in_non_contrib_can_view_comment + res = app.get(public_url, auth=non_contrib.auth) assert res.status_code == 200 assert public_comment._id == res.json['data']['id'] assert public_comment.content == res.json['data']['attributes']['content'] @@ -240,14 +224,14 @@ def test_comment_has_multiple_links(self, app, user, public_url, public_project, assert res.status_code == 200 assert urlparse(url).path == expected_url - def test_private_node_comment_auth_misc(self, app, user, non_contributor, private_url, payload): + def test_private_node_comment_auth_misc(self, app, user, non_contrib, private_url, payload): # test_private_node_only_logged_in_contributor_commenter_can_update_comment res = app.put_json_api(private_url, payload, auth=user.auth) assert res.status_code == 200 assert payload['data']['attributes']['content'] == res.json['data']['attributes']['content'] - # test_private_node_logged_in_non_contributor_cannot_update_comment - res = app.put_json_api(private_url, payload, auth=non_contributor.auth, expect_errors=True) + # test_private_node_logged_in_non_contrib_cannot_update_comment + res = app.put_json_api(private_url, payload, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail @@ -256,7 +240,7 @@ def test_private_node_comment_auth_misc(self, app, user, non_contributor, privat assert res.status_code == 401 assert res.json['errors'][0]['detail'] == exceptions.NotAuthenticated.default_detail - def test_public_node_comment_auth_misc(self, app, user, contributor, non_contributor, public_url, public_comment, public_comment_payload): + def test_public_node_comment_auth_misc(self, app, user, contributor, non_contrib, public_url, public_comment, public_comment_payload): # test_public_node_only_contributor_commenter_can_update_comment res = app.put_json_api(public_url, public_comment_payload, auth=user.auth) assert res.status_code == 200 @@ -267,8 +251,8 @@ def test_public_node_comment_auth_misc(self, app, user, contributor, non_contrib assert res.status_code == 403 assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail - # test_public_node_non_contributor_cannot_update_other_users_comment - res = app.put_json_api(public_url, public_comment_payload, auth=non_contributor.auth, expect_errors=True) + # test_public_node_non_contrib_cannot_update_other_users_comment + res = app.put_json_api(public_url, public_comment_payload, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail @@ -315,14 +299,14 @@ def test_private_node_only_logged_in_contributor_commenter_can_undelete_own_repl assert not res.json['data']['attributes']['deleted'] assert res.json['data']['attributes']['content'] == reply.content - def test_private_node_cannot_delete_comment_situation(self, app, user, contributor, non_contributor, private_url, comment): + def test_private_node_cannot_delete_comment_situation(self, app, user, contributor, non_contrib, private_url, comment): # def test_private_node_contributor_cannot_delete_other_users_comment(self): res = app.delete_json_api(private_url, auth=contributor.auth, expect_errors=True) assert res.status_code == 403 assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail - # def test_private_node_non_contributor_cannot_delete_comment(self): - res = app.delete_json_api(private_url, auth=non_contributor.auth, expect_errors=True) + # def test_private_node_non_contrib_cannot_delete_comment(self): + res = app.delete_json_api(private_url, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail @@ -347,7 +331,7 @@ def test_private_node_only_logged_in_contributor_commenter_can_undelete_comment( assert not res.json['data']['attributes']['deleted'] assert res.json['data']['attributes']['content'] == comment.content - def test_private_node_cannot_undelete_comment_situation(self, app, user, contributor, non_contributor, comment, set_up_payload): + def test_private_node_cannot_undelete_comment_situation(self, app, user, contributor, non_contrib, comment, set_up_payload): comment.is_deleted = True comment.save() url = '/{}comments/{}/'.format(API_BASE, comment._id) @@ -357,8 +341,8 @@ def test_private_node_cannot_undelete_comment_situation(self, app, user, contrib res = app.patch_json_api(url, payload, auth=contributor.auth, expect_errors=True) assert res.status_code == 403 - # test_private_node_non_contributor_cannot_undelete_comment - res = app.patch_json_api(url, payload, auth=non_contributor.auth, expect_errors=True) + # test_private_node_non_contrib_cannot_undelete_comment + res = app.patch_json_api(url, payload, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 # test_private_node_logged_out_user_cannot_undelete_comment @@ -369,14 +353,14 @@ def test_public_node_only_logged_in_contributor_commenter_can_delete_comment(sel res = app.delete_json_api(public_url, auth=user.auth) assert res.status_code == 204 - def test_public_node_cannot_delete_comment_situations(self, app, user, contributor, non_contributor, public_url, public_comment): + def test_public_node_cannot_delete_comment_situations(self, app, user, contributor, non_contrib, public_url, public_comment): # test_public_node_contributor_cannot_delete_other_users_comment res = app.delete_json_api(public_url, auth=contributor.auth, expect_errors=True) assert res.status_code == 403 assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail - # test_public_node_non_contributor_cannot_delete_other_users_comment - res = app.delete_json_api(public_url, auth=non_contributor.auth, expect_errors=True) + # test_public_node_non_contrib_cannot_delete_other_users_comment + res = app.delete_json_api(public_url, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail @@ -432,7 +416,7 @@ def test_private_node_deleted_comment_auth_misc(self, app, user, contributor, co assert res.status_code == 200 assert res.json['data']['attributes']['content'] is None - def test_public_node_deleted_comments_auth_misc(self, app, user, contributor, non_contributor, public_project, public_comment): + def test_public_node_deleted_comments_auth_misc(self, app, user, contributor, non_contrib, public_project, public_comment): public_comment.is_deleted = True public_comment.save() url = '/{}comments/{}/'.format(API_BASE, public_comment._id) @@ -448,8 +432,8 @@ def test_public_node_deleted_comments_auth_misc(self, app, user, contributor, no assert res.status_code == 200 assert res.json['data']['attributes']['content'] is None - # test_public_node_non_contributor_cannot_view_other_users_deleted_comment - res = app.get(url, auth=non_contributor.auth) + # test_public_node_non_contrib_cannot_view_other_users_deleted_comment + res = app.get(url, auth=non_contrib.auth) assert res.status_code == 200 assert res.json['data']['attributes']['content'] is None @@ -550,31 +534,31 @@ def test_comment_has_target_link_with_correct_type(self, app, public_url, public assert urlparse(url).path == expected_url assert target_type == expected_type - def test_public_node_non_contributor_commenter_can_update_comment(self, app, non_contributor, set_up_payload): + def test_public_node_non_contrib_commenter_can_update_comment(self, app, non_contrib, set_up_payload): project = ProjectFactory(is_public=True, comment_level='public') - comment = CommentFactory(node=project, user=non_contributor) + comment = CommentFactory(node=project, user=non_contrib) url = '/{}comments/{}/'.format(API_BASE, comment._id) payload = set_up_payload(comment._id) - res = app.put_json_api(url, payload, auth=non_contributor.auth) + res = app.put_json_api(url, payload, auth=non_contrib.auth) assert res.status_code == 200 assert payload['data']['attributes']['content'] == res.json['data']['attributes']['content'] - def test_public_node_non_contributor_commenter_cannot_update_own_comment_if_comment_level_private(self, app, non_contributor, set_up_payload): + def test_public_node_non_contrib_commenter_cannot_update_own_comment_if_comment_level_private(self, app, non_contrib, set_up_payload): project = ProjectFactory(is_public=True, comment_level='public') - comment = CommentFactory(node=project, user=non_contributor) + comment = CommentFactory(node=project, user=non_contrib) project.comment_level = 'private' project.save() url = '/{}comments/{}/'.format(API_BASE, comment._id) payload = set_up_payload(comment._id) - res = app.put_json_api(url, payload, auth=non_contributor.auth, expect_errors=True) + res = app.put_json_api(url, payload, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail - def test_public_node_non_contributor_commenter_can_delete_comment(self, app, non_contributor): + def test_public_node_non_contrib_commenter_can_delete_comment(self, app, non_contrib): project = ProjectFactory(is_public=True) - comment = CommentFactory(node=project, user=non_contributor) + comment = CommentFactory(node=project, user=non_contrib) url = '/{}comments/{}/'.format(API_BASE, comment._id) - res = app.delete_json_api(url, auth=non_contributor.auth) + res = app.delete_json_api(url, auth=non_contrib.auth) assert res.status_code == 204 def test_registration_comment_has_usable_replies_relationship_link(self, app, user, registration_url, registration_comment_reply): @@ -688,34 +672,34 @@ def test_file_comment_has_target_link_with_correct_type(self, app, public_url, p assert urlparse(url).path == expected_url assert target_type == expected_type - def test_public_node_non_contributor_commenter_can_update_file_comment(self, app, non_contributor, set_up_payload): + def test_public_node_non_contrib_commenter_can_update_file_comment(self, app, non_contrib, set_up_payload): project = ProjectFactory(is_public=True) test_file = test_utils.create_test_file(project, project.creator) - comment = CommentFactory(node=project, target=test_file.get_guid(), user=non_contributor) + comment = CommentFactory(node=project, target=test_file.get_guid(), user=non_contrib) url = '/{}comments/{}/'.format(API_BASE, comment._id) payload = set_up_payload(comment._id) - res = app.put_json_api(url, payload, auth=non_contributor.auth) + res = app.put_json_api(url, payload, auth=non_contrib.auth) assert res.status_code == 200 assert payload['data']['attributes']['content'] == res.json['data']['attributes']['content'] - def test_public_node_non_contributor_commenter_cannot_update_own_file_comment_if_comment_level_private(self, app, non_contributor, set_up_payload): + def test_public_node_non_contrib_commenter_cannot_update_own_file_comment_if_comment_level_private(self, app, non_contrib, set_up_payload): project = ProjectFactory(is_public=True) test_file = test_utils.create_test_file(project, project.creator) - comment = CommentFactory(node=project, target=test_file.get_guid(), user=non_contributor) + comment = CommentFactory(node=project, target=test_file.get_guid(), user=non_contrib) project.comment_level = 'private' project.save() url = '/{}comments/{}/'.format(API_BASE, comment._id) payload = set_up_payload(comment._id) - res = app.put_json_api(url, payload, auth=non_contributor.auth, expect_errors=True) + res = app.put_json_api(url, payload, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail - def test_public_node_non_contributor_commenter_can_delete_file_comment(self, app, non_contributor): + def test_public_node_non_contrib_commenter_can_delete_file_comment(self, app, non_contrib): project = ProjectFactory(is_public=True, comment_level='public') test_file = test_utils.create_test_file(project, project.creator) - comment = CommentFactory(node=project, target=test_file.get_guid(), user=non_contributor) + comment = CommentFactory(node=project, target=test_file.get_guid(), user=non_contrib) url = '/{}comments/{}/'.format(API_BASE, comment._id) - res = app.delete_json_api(url, auth=non_contributor.auth) + res = app.delete_json_api(url, auth=non_contrib.auth) assert res.status_code == 204 def test_comment_detail_for_deleted_file_is_not_returned(self, app, user, private_project, file, private_url): @@ -814,34 +798,34 @@ def test_wiki_comment_has_target_link_with_correct_type(self, app, public_url, p assert url == expected_url assert target_type == expected_type - def test_public_node_non_contributor_commenter_can_update_wiki_comment(self, app, user, non_contributor, set_up_payload): + def test_public_node_non_contrib_commenter_can_update_wiki_comment(self, app, user, non_contrib, set_up_payload): project = ProjectFactory(is_public=True) test_wiki = NodeWikiFactory(node=project, user=user) - comment = CommentFactory(node=project, target=Guid.load(test_wiki._id), user=non_contributor) + comment = CommentFactory(node=project, target=Guid.load(test_wiki._id), user=non_contrib) url = '/{}comments/{}/'.format(API_BASE, comment._id) payload = set_up_payload(comment._id) - res = app.put_json_api(url, payload, auth=non_contributor.auth) + res = app.put_json_api(url, payload, auth=non_contrib.auth) assert res.status_code == 200 assert payload['data']['attributes']['content'] == res.json['data']['attributes']['content'] - def test_public_node_non_contributor_commenter_cannot_update_own_wiki_comment_if_comment_level_private(self, app, user, non_contributor, set_up_payload): + def test_public_node_non_contrib_commenter_cannot_update_own_wiki_comment_if_comment_level_private(self, app, user, non_contrib, set_up_payload): project = ProjectFactory(is_public=True) test_wiki = NodeWikiFactory(node=project, user=user) - comment = CommentFactory(node=project, target=Guid.load(test_wiki._id), user=non_contributor) + comment = CommentFactory(node=project, target=Guid.load(test_wiki._id), user=non_contrib) project.comment_level = 'private' project.save() url = '/{}comments/{}/'.format(API_BASE, comment._id) payload = set_up_payload(comment._id) - res = app.put_json_api(url, payload, auth=non_contributor.auth, expect_errors=True) + res = app.put_json_api(url, payload, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail - def test_public_node_non_contributor_commenter_can_delete_wiki_comment(self, app, user, non_contributor): + def test_public_node_non_contrib_commenter_can_delete_wiki_comment(self, app, user, non_contrib): project = ProjectFactory(is_public=True, comment_level='public') test_wiki = NodeWikiFactory(node=project, user=user) - comment = CommentFactory(node=project, target=Guid.load(test_wiki._id), user=non_contributor) + comment = CommentFactory(node=project, target=Guid.load(test_wiki._id), user=non_contrib) url = '/{}comments/{}/'.format(API_BASE, comment._id) - res = app.delete_json_api(url, auth=non_contributor.auth) + res = app.delete_json_api(url, auth=non_contrib.auth) assert res.status_code == 204 def test_comment_detail_for_deleted_wiki_is_not_returned(self, app, user, wiki, private_url, private_project): diff --git a/api_tests/comments/views/test_comment_report_detail.py b/api_tests/comments/views/test_comment_report_detail.py index 6924ad112ac..fe3b95ff073 100644 --- a/api_tests/comments/views/test_comment_report_detail.py +++ b/api_tests/comments/views/test_comment_report_detail.py @@ -1,14 +1,19 @@ -import pytest -import mock -from django.utils import timezone from datetime import datetime -from osf.models import Guid +from django.utils import timezone +import mock +import pytest + +from addons.wiki.tests.factories import NodeWikiFactory from api.base.settings.defaults import API_BASE from api_tests import utils as test_utils -from tests.base import ApiTestCase -from osf_tests.factories import ProjectFactory, AuthUserFactory, CommentFactory -from addons.wiki.tests.factories import NodeWikiFactory +from osf.models import Guid +from osf_tests.factories import ( + ProjectFactory, + AuthUserFactory, + CommentFactory, +) + @pytest.mark.django_db class ReportDetailViewMixin(object): @@ -22,7 +27,7 @@ def contributor(self): return AuthUserFactory() @pytest.fixture() - def non_contributor(self): + def non_contrib(self): return AuthUserFactory() @pytest.fixture() @@ -63,7 +68,7 @@ def public_comment(self): def public_url(self): raise NotImplementedError - def test_private_node_view_report_detail_auth_misc(self, app, user, contributor, non_contributor, private_url): + def test_private_node_view_report_detail_auth_misc(self, app, user, contributor, non_contrib, private_url): # test_private_node_reporting_contributor_can_view_report_detail res = app.get(private_url, auth=user.auth) assert res.status_code == 200 @@ -73,15 +78,15 @@ def test_private_node_view_report_detail_auth_misc(self, app, user, contributor, res = app.get(private_url, auth=contributor.auth, expect_errors=True) assert res.status_code == 403 - # test_private_node_logged_in_non_contributor_cannot_view_report_detail - res = app.get(private_url, auth=non_contributor.auth, expect_errors=True) + # test_private_node_logged_in_non_contrib_cannot_view_report_detail + res = app.get(private_url, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 # test_private_node_logged_out_contributor_cannot_view_report_detail res = app.get(private_url, expect_errors=True) assert res.status_code == 401 - def test_public_node_view_report_detail_auth_misc(self, app, user, contributor, non_contributor, public_url): + def test_public_node_view_report_detail_auth_misc(self, app, user, contributor, non_contrib, public_url): # test_public_node_reporting_contributor_can_view_report_detail res = app.get(public_url, auth=user.auth) assert res.status_code == 200 @@ -91,33 +96,33 @@ def test_public_node_view_report_detail_auth_misc(self, app, user, contributor, res = app.get(public_url, auth=contributor.auth, expect_errors=True) assert res.status_code == 403 - # test_public_node_logged_in_non_contributor_cannot_view_other_users_report_detail - res = app.get(public_url, auth=non_contributor.auth, expect_errors=True) + # test_public_node_logged_in_non_contrib_cannot_view_other_users_report_detail + res = app.get(public_url, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 # test_public_node_logged_out_contributor_cannot_view_report_detail res = app.get(public_url, expect_errors=True) assert res.status_code == 401 - def test_public_node_logged_in_non_contributor_reporter_can_view_own_report_detail(self, app, non_contributor, public_comment): - public_comment.reports[non_contributor._id] = { + def test_public_node_logged_in_non_contrib_reporter_can_view_own_report_detail(self, app, non_contrib, public_comment): + public_comment.reports[non_contrib._id] = { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, } public_comment.save() - url = '/{}comments/{}/reports/{}/'.format(API_BASE, public_comment._id, non_contributor._id) - res = app.get(url, auth=non_contributor.auth) + url = '/{}comments/{}/reports/{}/'.format(API_BASE, public_comment._id, non_contrib._id) + res = app.get(url, auth=non_contrib.auth) assert res.status_code == 200 - def test_private_node_update_report_detail_auth_misc(self, app, user, contributor, non_contributor, payload, private_url): + def test_private_node_update_report_detail_auth_misc(self, app, user, contributor, non_contrib, payload, private_url): # test_private_node_reported_contributor_cannot_update_report_detail res = app.put_json_api(private_url, payload, auth=contributor.auth, expect_errors=True) assert res.status_code == 403 - # test_private_node_logged_in_non_contributor_cannot_update_report_detail - res = app.put_json_api(private_url, payload, auth=non_contributor.auth, expect_errors=True) + # test_private_node_logged_in_non_contrib_cannot_update_report_detail + res = app.put_json_api(private_url, payload, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 # test_private_node_logged_out_contributor_cannot_update_detail @@ -130,13 +135,13 @@ def test_private_node_update_report_detail_auth_misc(self, app, user, contributo assert res.json['data']['id'] == user._id assert res.json['data']['attributes']['message'] == payload['data']['attributes']['message'] - def test_public_node_update_report_detail_auth_misc(self, app, user, contributor, non_contributor, payload, public_url): + def test_public_node_update_report_detail_auth_misc(self, app, user, contributor, non_contrib, payload, public_url): # test_public_node_reported_contributor_cannot_update_detail res = app.put_json_api(public_url, payload, auth=contributor.auth, expect_errors=True) assert res.status_code == 403 - # test_public_node_logged_in_non_contributor_cannot_update_other_users_report_detail - res = app.put_json_api(public_url, payload, auth=non_contributor.auth, expect_errors=True) + # test_public_node_logged_in_non_contrib_cannot_update_other_users_report_detail + res = app.put_json_api(public_url, payload, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 # test_public_node_logged_out_contributor_cannot_update_report_detail @@ -149,18 +154,18 @@ def test_public_node_update_report_detail_auth_misc(self, app, user, contributor assert res.json['data']['id'] == user._id assert res.json['data']['attributes']['message'] == payload['data']['attributes']['message'] - def test_public_node_logged_in_non_contributor_reporter_can_update_own_report_detail(self, app, non_contributor, public_comment): - public_comment.reports[non_contributor._id] = { + def test_public_node_logged_in_non_contrib_reporter_can_update_own_report_detail(self, app, non_contrib, public_comment): + public_comment.reports[non_contrib._id] = { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, } public_comment.save() - url = '/{}comments/{}/reports/{}/'.format(API_BASE, public_comment._id, non_contributor._id) + url = '/{}comments/{}/reports/{}/'.format(API_BASE, public_comment._id, non_contrib._id) payload = { 'data': { - 'id': non_contributor._id, + 'id': non_contrib._id, 'type': 'comment_reports', 'attributes': { 'category': 'spam', @@ -168,17 +173,17 @@ def test_public_node_logged_in_non_contributor_reporter_can_update_own_report_de } } } - res = app.put_json_api(url, payload, auth=non_contributor.auth) + res = app.put_json_api(url, payload, auth=non_contrib.auth) assert res.status_code == 200 assert res.json['data']['attributes']['message'] == payload['data']['attributes']['message'] - def test_private_node_delete_report_detail_auth_misc(self, app, user, contributor, non_contributor, private_project, payload, private_url, comment): + def test_private_node_delete_report_detail_auth_misc(self, app, user, contributor, non_contrib, private_project, payload, private_url, comment): # test_private_node_reported_contributor_cannot_delete_report_detail res = app.delete_json_api(private_url, auth=contributor.auth, expect_errors=True) assert res.status_code == 403 - # test_private_node_logged_in_non_contributor_cannot_delete_report_detail - res = app.delete_json_api(private_url, auth=non_contributor.auth, expect_errors=True) + # test_private_node_logged_in_non_contrib_cannot_delete_report_detail + res = app.delete_json_api(private_url, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 # test_private_node_logged_out_contributor_cannot_delete_detail @@ -198,14 +203,14 @@ def test_private_node_delete_report_detail_auth_misc(self, app, user, contributo res = app.delete_json_api(url, auth=user.auth) assert res.status_code == 204 - def test_public_node_delete_report_detail_auth_misc(self, app, user, contributor, non_contributor, public_url): + def test_public_node_delete_report_detail_auth_misc(self, app, user, contributor, non_contrib, public_url): # test_public_node_reported_contributor_cannot_delete_detail res = app.delete_json_api(public_url, auth=contributor.auth, expect_errors=True) assert res.status_code == 403 - # test_public_node_logged_in_non_contributor_cannot_delete_other_users_report_detail - res = app.delete_json_api(public_url, auth=non_contributor.auth, expect_errors=True) + # test_public_node_logged_in_non_contrib_cannot_delete_other_users_report_detail + res = app.delete_json_api(public_url, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 # test_public_node_logged_out_contributor_cannot_delete_report_detail @@ -216,16 +221,16 @@ def test_public_node_delete_report_detail_auth_misc(self, app, user, contributor res = app.delete_json_api(public_url, auth=user.auth) assert res.status_code == 204 - def test_public_node_logged_in_non_contributor_reporter_can_delete_own_report_detail(self, app, non_contributor, public_comment): - public_comment.reports[non_contributor._id] = { + def test_public_node_logged_in_non_contrib_reporter_can_delete_own_report_detail(self, app, non_contrib, public_comment): + public_comment.reports[non_contrib._id] = { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, } public_comment.save() - url = '/{}comments/{}/reports/{}/'.format(API_BASE, public_comment._id, non_contributor._id) - res = app.delete_json_api(url, auth=non_contributor.auth) + url = '/{}comments/{}/reports/{}/'.format(API_BASE, public_comment._id, non_contrib._id) + res = app.delete_json_api(url, auth=non_contrib.auth) assert res.status_code == 204 diff --git a/api_tests/comments/views/test_comment_report_list.py b/api_tests/comments/views/test_comment_report_list.py index 1dc16fb54cd..c3ff0583865 100644 --- a/api_tests/comments/views/test_comment_report_list.py +++ b/api_tests/comments/views/test_comment_report_list.py @@ -1,15 +1,20 @@ -import pytest -import mock -from django.utils import timezone from datetime import datetime -from rest_framework import exceptions -from osf.models import Guid +from django.utils import timezone +import mock +import pytest + +from addons.wiki.tests.factories import NodeWikiFactory from api.base.settings.defaults import API_BASE from api_tests import utils as test_utils -from tests.base import ApiTestCase -from osf_tests.factories import ProjectFactory, AuthUserFactory, CommentFactory -from addons.wiki.tests.factories import NodeWikiFactory +from osf.models import Guid +from osf_tests.factories import ( + ProjectFactory, + AuthUserFactory, + CommentFactory, +) +from rest_framework import exceptions + @pytest.mark.django_db class CommentReportsMixin(object): @@ -23,7 +28,7 @@ def contributor(self): return AuthUserFactory() @pytest.fixture() - def non_contributor(self): + def non_contrib(self): return AuthUserFactory() @pytest.fixture() @@ -68,13 +73,13 @@ def public_url(self): def comment_level(self): raise NotImplementedError - def test_private_node_view_reports_auth_misc(self, app, user, contributor, non_contributor, private_url): + def test_private_node_view_reports_auth_misc(self, app, user, contributor, non_contrib, private_url): # test_private_node_logged_out_user_cannot_view_reports res = app.get(private_url, expect_errors=True) assert res.status_code == 401 - # test_private_node_logged_in_non_contributor_cannot_view_reports - res = app.get(private_url, auth=non_contributor.auth, expect_errors=True) + # test_private_node_logged_in_non_contrib_cannot_view_reports + res = app.get(private_url, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 # test_private_node_only_reporting_user_can_view_reports @@ -93,7 +98,7 @@ def test_private_node_view_reports_auth_misc(self, app, user, contributor, non_c assert len(report_json) == 0 assert contributor._id not in report_ids - def test_public_node_view_report_auth_misc(self, app, user, contributor, non_contributor, public_url): + def test_public_node_view_report_auth_misc(self, app, user, contributor, non_contrib, public_url): # test_public_node_logged_out_user_cannot_view_reports res = app.get(public_url, expect_errors=True) assert res.status_code == 401 @@ -114,32 +119,32 @@ def test_public_node_view_report_auth_misc(self, app, user, contributor, non_con assert len(report_json) == 0 assert contributor._id not in report_ids - # test_public_node_non_contributor_does_not_see_other_user_reports - res = app.get(public_url, auth=non_contributor.auth, expect_errors=True) + # test_public_node_non_contrib_does_not_see_other_user_reports + res = app.get(public_url, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 200 report_json = res.json['data'] report_ids = [report['id'] for report in report_json] assert len(report_json) == 0 - assert non_contributor._id not in report_ids + assert non_contrib._id not in report_ids - def test_public_node_non_contributor_reporter_can_view_own_report(self, app, non_contributor, public_comment, public_url): - public_comment.reports[non_contributor._id] = { + def test_public_node_non_contrib_reporter_can_view_own_report(self, app, non_contrib, public_comment, public_url): + public_comment.reports[non_contrib._id] = { 'category': 'spam', 'text': 'This is spam', 'date': timezone.now(), 'retracted': False, } public_comment.save() - res = app.get(public_url, auth=non_contributor.auth) + res = app.get(public_url, auth=non_contrib.auth) assert res.status_code == 200 report_json = res.json['data'] report_ids = [report['id'] for report in report_json] assert len(report_json) == 1 - assert non_contributor._id in report_ids + assert non_contrib._id in report_ids @pytest.mark.parametrize('comment_level', ['private']) - def test_public_node_private_comment_level_non_contributor_cannot_see_reports(self, app, non_contributor, public_url, comment_level): - res = app.get(public_url, auth=non_contributor.auth, expect_errors=True) + def test_public_node_private_comment_level_non_contrib_cannot_see_reports(self, app, non_contrib, public_url, comment_level): + res = app.get(public_url, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail @@ -205,14 +210,14 @@ def test_report_comment_allow_blank_message(self, app, user, contributor, privat assert res.json['data']['id'] == user._id assert res.json['data']['attributes']['message'] == payload['data']['attributes']['message'] - def test_private_node_report_comment_auth_misc(self, app, user, contributor, non_contributor, private_project, private_url, comment, payload): + def test_private_node_report_comment_auth_misc(self, app, user, contributor, non_contrib, private_project, private_url, comment, payload): # test_private_node_logged_out_user_cannot_report_comment res = app.post_json_api(private_url, payload, expect_errors=True) assert res.status_code == 401 - # test_private_node_logged_in_non_contributor_cannot_report_comment - res = app.post_json_api(private_url, payload, auth=non_contributor.auth, expect_errors=True) + # test_private_node_logged_in_non_contrib_cannot_report_comment + res = app.post_json_api(private_url, payload, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 # test_private_node_logged_in_contributor_can_report_comment @@ -234,7 +239,7 @@ def test_user_cannot_report_comment_condition(self, app, user, contributor, priv assert res.status_code == 400 assert res.json['errors'][0]['detail'] == 'Comment already reported.' - def test_public_node_report_comment_auth_misc(self, app, user, contributor, non_contributor, public_project, public_url, public_comment, payload): + def test_public_node_report_comment_auth_misc(self, app, user, contributor, non_contrib, public_project, public_url, public_comment, payload): # def test_public_node_logged_out_user_cannot_report_comment(self): res = app.post_json_api(public_url, payload, expect_errors=True) assert res.status_code == 401 @@ -246,18 +251,18 @@ def test_public_node_report_comment_auth_misc(self, app, user, contributor, non_ assert res.status_code == 201 assert res.json['data']['id'] == user._id - # def test_public_node_non_contributor_can_report_comment(self): + # def test_public_node_non_contrib_can_report_comment(self): """ Test that when a public project allows any osf user to comment (comment_level == 'public), non-contributors can also report comments. """ - res = app.post_json_api(public_url, payload, auth=non_contributor.auth) + res = app.post_json_api(public_url, payload, auth=non_contrib.auth) assert res.status_code == 201 - assert res.json['data']['id'] == non_contributor._id + assert res.json['data']['id'] == non_contrib._id @pytest.mark.parametrize('comment_level', ['private']) - def test_public_node_private_comment_level_non_contributor_cannot_report_comment(self, app, non_contributor, comment_level, public_url): - res = app.get(public_url, auth=non_contributor.auth, expect_errors=True) + def test_public_node_private_comment_level_non_contrib_cannot_report_comment(self, app, non_contrib, comment_level, public_url): + res = app.get(public_url, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail From e2e94a50280a5328c42e87fdcf45b14bbe828d13 Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Thu, 6 Jul 2017 09:55:25 -0400 Subject: [PATCH 12/62] Convert institutions auth to pytests --- .../views/test_institution_auth.py | 152 ++++++++++-------- 1 file changed, 81 insertions(+), 71 deletions(-) diff --git a/api_tests/institutions/views/test_institution_auth.py b/api_tests/institutions/views/test_institution_auth.py index ba591caebd2..157232d2673 100644 --- a/api_tests/institutions/views/test_institution_auth.py +++ b/api_tests/institutions/views/test_institution_auth.py @@ -1,122 +1,132 @@ import pytest -from nose.tools import * # flake8: noqa import json import jwt import jwe - from modularodm import Q -from tests.base import ApiTestCase -from tests.base import capture_signals -from osf_tests.factories import InstitutionFactory, UserFactory - from api.base import settings from api.base.settings.defaults import API_BASE from framework.auth import signals +from osf_tests.factories import ( + InstitutionFactory, + UserFactory, +) from osf.models import OSFUser as User +from tests.base import capture_signals - -class TestInstitutionAuth(ApiTestCase): - def setUp(self): - super(TestInstitutionAuth, self).setUp() - self.institution = InstitutionFactory() - self.institution.save() - self.url = '/{0}institutions/auth/'.format(API_BASE) - - def tearDown(self): - super(TestInstitutionAuth, self).tearDown() - self.institution.remove() - User.remove() - - def build_payload(self, username, fullname='Fake User', given_name='', family_name=''): - data = { - 'provider': { - 'id': self.institution._id, - 'user': { - 'middleNames': '', - 'familyName': family_name, - 'givenName': given_name, - 'fullname': fullname, - 'suffix': '', - 'username': username +@pytest.mark.django_db +class TestInstitutionAuth: + + @pytest.fixture() + def institution(self): + institution = InstitutionFactory() + institution.save() + return institution + + @pytest.fixture() + def url_auth_institution(self): + return '/{0}institutions/auth/'.format(API_BASE) + + @pytest.fixture() + def make_user(self): + def user(username, fullname): + return UserFactory(username=username, fullname=fullname) + return user + + @pytest.fixture() + def make_payload(self, institution): + def payload(username, fullname='Fake User', given_name='', family_name=''): + data = { + 'provider': { + 'id': institution._id, + 'user': { + 'middleNames': '', + 'familyName': family_name, + 'givenName': given_name, + 'fullname': fullname, + 'suffix': '', + 'username': username + } } } - } - return jwe.encrypt(jwt.encode({ - 'sub': username, - 'data': json.dumps(data) - }, settings.JWT_SECRET, algorithm='HS256'), settings.JWE_SECRET) + return jwe.encrypt(jwt.encode({ + 'sub': username, + 'data': json.dumps(data) + }, settings.JWT_SECRET, algorithm='HS256'), settings.JWE_SECRET) + + return payload + - def test_creates_user(self): + def test_creates_user(self, app, url_auth_institution, institution, make_payload): username = 'hmoco@circle.edu' - assert_equal(User.find(Q('username', 'eq', username)).count(), 0) + assert User.find(Q('username', 'eq', username)).count() == 0 with capture_signals() as mock_signals: - res = self.app.post(self.url, self.build_payload(username)) + res = app.post(url_auth_institution, make_payload(username)) - assert_equal(res.status_code, 204) - assert_equal(mock_signals.signals_sent(), set([signals.user_confirmed])) + assert res.status_code == 204 + assert mock_signals.signals_sent() == set([signals.user_confirmed]) user = User.find_one(Q('username', 'eq', username)) - assert_true(user) - assert_in(self.institution, user.affiliated_institutions.all()) + assert user + assert institution in user.affiliated_institutions.all() - def test_adds_institution(self): + def test_adds_institution(self, app, make_user, make_payload, institution, url_auth_institution): username = 'hmoco@circle.edu' - user = UserFactory(username=username, fullname='Mr Moco') + user = make_user(username,'Mr Moco') user.save() with capture_signals() as mock_signals: - res = self.app.post(self.url, self.build_payload(username)) + res = app.post(url_auth_institution, make_payload(username)) - assert_equal(res.status_code, 204) - assert_equal(mock_signals.signals_sent(), set()) + assert res.status_code == 204 + assert mock_signals.signals_sent() == set() user.reload() - assert_in(self.institution, user.affiliated_institutions.all()) + assert institution in user.affiliated_institutions.all() - def test_finds_user(self): + def test_finds_user(self, app, make_user, make_payload, institution, url_auth_institution): username = 'hmoco@circle.edu' - user = UserFactory(username=username, fullname='Mr Moco') - user.affiliated_institutions.add(self.institution) + user = make_user(username, 'Mr Moco') + user.affiliated_institutions.add(institution) user.save() - res = self.app.post(self.url, self.build_payload(username)) - assert_equal(res.status_code, 204) + res = app.post(url_auth_institution, make_payload(username)) + assert res.status_code == 204 user.reload() - assert_equal(user.affiliated_institutions.count(), 1) + assert user.affiliated_institutions.count() == 1 - def test_bad_token(self): - res = self.app.post(self.url, 'al;kjasdfljadf', expect_errors=True) - assert_equal(res.status_code, 403) + def test_bad_token(self, app, url_auth_institution): + res = app.post(url_auth_institution, 'al;kjasdfljadf', expect_errors=True) + assert res.status_code == 403 - def test_user_names_guessed_if_not_provided(self): + def test_user_names_guessed_if_not_provided(self, app, make_payload, url_auth_institution): # Regression for https://openscience.atlassian.net/browse/OSF-7212 username = 'fake@user.edu' - res = self.app.post(self.url, self.build_payload(username)) + res = app.post(url_auth_institution, make_payload(username)) - assert_equal(res.status_code, 204) + assert res.status_code == 204 user = User.find_one(Q('username', 'eq', username)) - assert_true(user) - assert_equal(user.fullname, 'Fake User') - assert_equal(user.given_name, 'Fake') - assert_equal(user.family_name, 'User') + assert user + assert user.fullname == 'Fake User' + assert user.given_name == 'Fake' + assert user.family_name == 'User' - def test_user_names_used_when_provided(self): + def test_user_names_used_when_provided(self, app, url_auth_institution, make_payload): # Regression for https://openscience.atlassian.net/browse/OSF-7212 username = 'fake@user.edu' - res = self.app.post(self.url, self.build_payload(username, family_name='West', given_name='Kanye')) + res = app.post(url_auth_institution, make_payload(username, family_name='West', given_name='Kanye')) - assert_equal(res.status_code, 204) + assert res.status_code == 204 user = User.find_one(Q('username', 'eq', username)) - assert_true(user) - assert_equal(user.fullname, 'Fake User') - assert_equal(user.given_name, 'Kanye') - assert_equal(user.family_name, 'West') + assert user + assert user.fullname == 'Fake User' + assert user.given_name == 'Kanye' + assert user.family_name == 'West' From cfbb2e479577cdc3bce8f5f61dcc5ff5042fab48 Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Thu, 6 Jul 2017 09:55:46 -0400 Subject: [PATCH 13/62] Convert institutions detail to pytest --- .../views/test_institution_detail.py | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/api_tests/institutions/views/test_institution_detail.py b/api_tests/institutions/views/test_institution_detail.py index b68a31da469..cab7b62049b 100644 --- a/api_tests/institutions/views/test_institution_detail.py +++ b/api_tests/institutions/views/test_institution_detail.py @@ -1,23 +1,29 @@ -from nose.tools import * # flake8: noqa +import pytest -from tests.base import ApiTestCase +from api.base.settings.defaults import API_BASE from osf_tests.factories import InstitutionFactory -from api.base.settings.defaults import API_BASE +@pytest.mark.django_db +class TestInstitutionDetail: + + @pytest.fixture() + def institution(self): + return InstitutionFactory() -class TestInstitutionDetail(ApiTestCase): - def setUp(self): - super(TestInstitutionDetail, self).setUp() - self.institution = InstitutionFactory() - self.institution_url = '/' + API_BASE + 'institutions/{id}/' + @pytest.fixture() + def url_institution(self): + def url(id): + return '/{}institutions/{}/'.format(API_BASE, id) + return url - def test_return_wrong_id(self): - res = self.app.get(self.institution_url.format(id='1PO'), expect_errors=True) - assert_equal(res.status_code, 404) + def test_detail_response(self, app, institution, url_institution): + #return_wrong_id + res = app.get(url_institution(id='1PO'), expect_errors=True) + assert res.status_code == 404 - def test_return_with_id(self): - res = self.app.get(self.institution_url.format(id=self.institution._id)) + #test_return_with_id + res = app.get(url_institution(id=institution._id)) - assert_equal(res.status_code, 200) - assert_equal(res.json['data']['attributes']['name'], self.institution.name) + assert res.status_code == 200 + assert res.json['data']['attributes']['name'] == institution.name From 190f2778b7b9f0e76136fb590943c725daa177fd Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Thu, 6 Jul 2017 09:56:16 -0400 Subject: [PATCH 14/62] Convert institutions list to pytest --- .../views/test_institution_list.py | 66 +++++++++++-------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/api_tests/institutions/views/test_institution_list.py b/api_tests/institutions/views/test_institution_list.py index 542b0f17124..b9fe0e02f7a 100644 --- a/api_tests/institutions/views/test_institution_list.py +++ b/api_tests/institutions/views/test_institution_list.py @@ -1,38 +1,52 @@ -from nose.tools import * # flake8: noqa +import pytest -from tests.base import ApiTestCase -from osf_tests.factories import InstitutionFactory +from api.base.settings.defaults import API_BASE +from osf_tests.factories import InstitutionFactory from osf.models import AbstractNode as Node -from api.base.settings.defaults import API_BASE -class TestInstitutionList(ApiTestCase): - def setUp(self): - super(TestInstitutionList, self).setUp() - self.institution = InstitutionFactory() - self.institution2 = InstitutionFactory() - self.institution_url = '/{}institutions/'.format(API_BASE) +@pytest.mark.django_db +class TestInstitutionList: - def test_return_all_institutions(self): - res = self.app.get(self.institution_url) + @pytest.fixture() + def institution_one(self): + return InstitutionFactory() - assert_equal(res.status_code, 200) + @pytest.fixture() + def institution_two(self): + return InstitutionFactory() - ids = [each['id'] for each in res.json['data']] - assert_equal(len(res.json['data']), 2) - assert_equal(res.json['links']['meta']['per_page'], 1000) - assert_in(self.institution._id, ids) - assert_in(self.institution2._id, ids) + @pytest.fixture() + def url_institution(self): + return '/{}institutions/'.format(API_BASE) + + @pytest.fixture() + def res_institutions(self, app, url_institution): + return app.get(url_institution) + + @pytest.fixture() + def data_institutions(self, res_institutions): + return res_institutions.json['data'] + + + def test_return_all_institutions(self, institution_one, institution_two, url_institution, res_institutions, data_institutions): + assert res_institutions.status_code == 200 + + ids = [each['id'] for each in data_institutions] + assert len(data_institutions) == 2 + assert res_institutions.json['links']['meta']['per_page'] == 1000 - def test_does_not_return_deleted_institution(self): - self.institution.is_deleted = True - self.institution.save() + assert institution_one._id in ids + assert institution_two._id in ids - res = self.app.get(self.institution_url) + def test_does_not_return_deleted_institution(self, app, institution_one, institution_two, url_institution): + institution_one.is_deleted = True + institution_one.save() - assert_equal(res.status_code, 200) + res = app.get(url_institution) + assert res.status_code == 200 ids = [each['id'] for each in res.json['data']] - assert_equal(len(res.json['data']), 1) - assert_not_in(self.institution._id, ids) - assert_in(self.institution2._id, ids) + assert len(res.json['data']) == 1 + assert institution_one._id not in ids + assert institution_two._id in ids From 266cbe178dae87bee6e080c5213968716f03146a Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Thu, 6 Jul 2017 09:56:52 -0400 Subject: [PATCH 15/62] Convert institutions node relationships to pytest --- .../test_institution_relationship_nodes.py | 437 ++++++++++-------- 1 file changed, 232 insertions(+), 205 deletions(-) diff --git a/api_tests/institutions/views/test_institution_relationship_nodes.py b/api_tests/institutions/views/test_institution_relationship_nodes.py index e7051efd224..c02bc842347 100644 --- a/api_tests/institutions/views/test_institution_relationship_nodes.py +++ b/api_tests/institutions/views/test_institution_relationship_nodes.py @@ -1,303 +1,330 @@ -from nose.tools import * # flake8: noqa +import pytest +from api.base.settings.defaults import API_BASE from framework.auth import Auth +from osf_tests.factories import ( + InstitutionFactory, + AuthUserFactory, + NodeFactory, +) +from website.util import permissions -from tests.base import ApiTestCase -from osf_tests.factories import InstitutionFactory, AuthUserFactory, NodeFactory +@pytest.mark.django_db +class TestInstitutionRelationshipNodes: -from api.base.settings.defaults import API_BASE + @pytest.fixture() + def institution(self): + return InstitutionFactory() -from website.util import permissions + @pytest.fixture() + def user(self, institution): + user = AuthUserFactory() + user.affiliated_institutions.add(institution) + user.save() + return user + + @pytest.fixture() + def node(self, user, institution): + node = NodeFactory(creator=user) + node.affiliated_institutions.add(institution) + node.save() + return node + + @pytest.fixture() + def node_public(self, user, institution): + node_public = NodeFactory(is_public=True) + node_public.affiliated_institutions.add(institution) + node_public.save() + return node_public + + @pytest.fixture() + def node_private(self, user, institution): + node_private = NodeFactory() + node_private.affiliated_institutions.add(institution) + node_private.save() + return node_private + + @pytest.fixture() + def url_institution_nodes(self, institution): + return '/{}institutions/{}/relationships/nodes/'.format(API_BASE, institution._id) + + + @pytest.fixture() + def make_payload(self): + def payload(*node_ids): + data = [ + {'type': 'nodes', 'id': id_} for id_ in node_ids + ] + return {'data': data} + return payload + + def test_auth_get_nodes(self, institution, user, node, node_public, node_private, app, url_institution_nodes): + #test_get_nodes_no_auth + res = app.get(url_institution_nodes) + + assert res.status_code == 200 + node_ids = [node_['id'] for node_ in res.json['data']] + assert node._id not in node_ids + assert node_public._id in node_ids + assert node_private._id not in node_ids -class TestInstitutionRelationshipNodes(ApiTestCase): - def setUp(self): - super(TestInstitutionRelationshipNodes, self).setUp() - self.user = AuthUserFactory() - self.institution = InstitutionFactory() - self.user.affiliated_institutions.add(self.institution) - self.user.save() - self.node1 = NodeFactory(creator=self.user) - self.node2 = NodeFactory(is_public=True) - self.node3 = NodeFactory() - self.node1.affiliated_institutions.add(self.institution) - self.node2.affiliated_institutions.add(self.institution) - self.node3.affiliated_institutions.add(self.institution) - self.node1.save() - self.node2.save() - self.node3.save() - self.institution_nodes_url = '/{}institutions/{}/relationships/nodes/'.format(API_BASE, self.institution._id) - - def create_payload(self, *node_ids): - data = [ - {'type': 'nodes', 'id': id_} for id_ in node_ids - ] - return {'data': data} - - def test_get_nodes_no_auth(self): - res = self.app.get(self.institution_nodes_url) - - assert_equal(res.status_code, 200) - node_ids = [node['id'] for node in res.json['data']] - assert_in(self.node2._id, node_ids) - assert_not_in(self.node1._id, node_ids) - assert_not_in(self.node3._id, node_ids) - - def test_get_nodes_with_auth(self): - res = self.app.get(self.institution_nodes_url, auth=self.user.auth) - - assert_equal(res.status_code, 200) - node_ids = [node['id'] for node in res.json['data']] - assert_in(self.node1._id, node_ids) - assert_in(self.node2._id, node_ids) - assert_not_in(self.node3._id, node_ids) - - def test_node_does_not_exist(self): - res = self.app.post_json_api( - self.institution_nodes_url, - self.create_payload('notIdatAll'), + #test_get_nodes_with_auth + res = app.get(url_institution_nodes, auth=user.auth) + + assert res.status_code == 200 + node_ids = [node_['id'] for node_ in res.json['data']] + assert node._id in node_ids + assert node_public._id in node_ids + assert node_private._id not in node_ids + + def test_node_or_type_does_not_exist(self, app, user, url_institution_nodes, make_payload): + #test_node_does_not_exist + res = app.post_json_api( + url_institution_nodes, + make_payload('notIdatAll'), expect_errors=True, - auth=self.user.auth + auth=user.auth ) - assert_equal(res.status_code, 404) + assert res.status_code == 404 - def test_wrong_type(self): - node = NodeFactory(creator=self.user) - res = self.app.post_json_api( - self.institution_nodes_url, + #test_node_type_does_not_exist + node = NodeFactory(creator=user) + res = app.post_json_api( + url_institution_nodes, {'data': [{'type': 'dugtrio', 'id': node._id}]}, expect_errors=True, - auth=self.user.auth + auth=user.auth ) - assert_equal(res.status_code, 409) + assert res.status_code == 409 - def test_user_with_nodes_and_permissions(self): - node = NodeFactory(creator=self.user) - res = self.app.post_json_api( - self.institution_nodes_url, - self.create_payload(node._id), - auth=self.user.auth + def test_user_with_nodes_and_permissions(self, user, app, url_institution_nodes, make_payload, institution): + node = NodeFactory(creator=user) + res = app.post_json_api( + url_institution_nodes, + make_payload(node._id), + auth=user.auth ) - assert_equal(res.status_code, 201) + assert res.status_code == 201 node_ids = [node_['id'] for node_ in res.json['data']] - assert_in(node._id, node_ids) + assert node._id in node_ids node.reload() - assert_in(self.institution, node.affiliated_institutions.all()) + assert institution in node.affiliated_institutions.all() - def test_user_does_not_have_node(self): + def test_user_does_not_have_node(self, app, url_institution_nodes, make_payload, user, institution): node = NodeFactory() - res = self.app.post_json_api( - self.institution_nodes_url, - self.create_payload(node._id), + res = app.post_json_api( + url_institution_nodes, + make_payload(node._id), expect_errors=True, - auth=self.user.auth + auth=user.auth ) - assert_equal(res.status_code, 403) + assert res.status_code == 403 node.reload() - assert_not_in(self.institution, node.affiliated_institutions.all()) - - def test_user_is_admin(self): - node = NodeFactory(creator=self.user) - res = self.app.post_json_api( - self.institution_nodes_url, - self.create_payload(node._id), - auth=self.user.auth + assert institution not in node.affiliated_institutions.all() + + def test_user_is_admin(self, app, url_institution_nodes, make_payload, user, institution): + node = NodeFactory(creator=user) + res = app.post_json_api( + url_institution_nodes, + make_payload(node._id), + auth=user.auth ) - assert_equal(res.status_code, 201) + assert res.status_code == 201 node.reload() - assert_in(self.institution, node.affiliated_institutions.all()) + assert institution in node.affiliated_institutions.all() - def test_user_is_read_write(self): + def test_user_is_read_write(self, app, url_institution_nodes, make_payload, institution): user = AuthUserFactory() - user.affiliated_institutions.add(self.institution) + user.affiliated_institutions.add(institution) node = NodeFactory() node.add_contributor(user) node.save() - res = self.app.post_json_api( - self.institution_nodes_url, - self.create_payload(node._id), + res = app.post_json_api( + url_institution_nodes, + make_payload(node._id), auth=user.auth ) - assert_equal(res.status_code, 201) + assert res.status_code == 201 node.reload() - assert_in(self.institution, node.affiliated_institutions.all()) + assert institution in node.affiliated_institutions.all() - def test_user_is_read_only(self): + def test_user_is_read_only(self, app, url_institution_nodes, make_payload, institution): user = AuthUserFactory() - user.affiliated_institutions.add(self.institution) + user.affiliated_institutions.add(institution) node = NodeFactory() node.add_contributor(user, permissions=[permissions.READ]) node.save() - res = self.app.post_json_api( - self.institution_nodes_url, - self.create_payload(node._id), + res = app.post_json_api( + url_institution_nodes, + make_payload(node._id), auth=user.auth, expect_errors=True ) - assert_equal(res.status_code, 403) + assert res.status_code == 403 node.reload() - assert_not_in(self.institution, node.affiliated_institutions.all()) + assert institution not in node.affiliated_institutions.all() - def test_user_is_admin_but_not_affiliated(self): + def test_user_is_admin_but_not_affiliated(self, app, url_institution_nodes, make_payload, institution): user = AuthUserFactory() node = NodeFactory(creator=user) - res = self.app.post_json_api( - self.institution_nodes_url, - self.create_payload(node._id), + res = app.post_json_api( + url_institution_nodes, + make_payload(node._id), expect_errors=True, auth=user.auth ) - assert_equal(res.status_code, 403) + assert res.status_code == 403 node.reload() - assert_not_in(self.institution, node.affiliated_institutions.all()) - - def test_add_some_with_permissions_others_without(self): - node1 = NodeFactory(creator=self.user) - node2 = NodeFactory() - res = self.app.post_json_api( - self.institution_nodes_url, - self.create_payload(node1._id, node2._id), + assert institution not in node.affiliated_institutions.all() + + def test_add_some_with_permissions_others_without(self, user, app, url_institution_nodes, make_payload, institution): + node_one = NodeFactory(creator=user) + node_two = NodeFactory() + res = app.post_json_api( + url_institution_nodes, + make_payload(node_one._id, node_two._id), expect_errors=True, - auth=self.user.auth + auth=user.auth ) - assert_equal(res.status_code, 403) - node1.reload() - node2.reload() - assert_not_in(self.institution, node1.affiliated_institutions.all()) - assert_not_in(self.institution, node2.affiliated_institutions.all()) + assert res.status_code == 403 + node_one.reload() + node_two.reload() + assert institution not in node_one.affiliated_institutions.all() + assert institution not in node_two.affiliated_institutions.all() - def test_add_some_existant_others_not(self): - assert_in(self.institution, self.node1.affiliated_institutions.all()) + def test_add_some_existant_others_not(self, institution, node, app, url_institution_nodes, make_payload, user): + assert institution in node.affiliated_institutions.all() - node = NodeFactory(creator=self.user) - res = self.app.post_json_api( - self.institution_nodes_url, - self.create_payload(node._id, self.node1._id), - auth=self.user.auth + node_one= NodeFactory(creator=user) + res = app.post_json_api( + url_institution_nodes, + make_payload(node_one._id, node._id), + auth=user.auth ) - assert_equal(res.status_code, 201) + assert res.status_code == 201 node.reload() - self.node1.reload() - assert_in(self.institution, self.node1.affiliated_institutions.all()) - assert_in(self.institution, node.affiliated_institutions.all()) + node_one.reload() + assert institution in node.affiliated_institutions.all() + assert institution in node_one.affiliated_institutions.all() - def test_only_add_existent_with_mixed_permissions(self): - assert_in(self.institution, self.node1.affiliated_institutions.all()) - assert_in(self.institution, self.node2.affiliated_institutions.all()) + def test_only_add_existent_with_mixed_permissions(self, institution, node, node_public, app, url_institution_nodes, make_payload, user): + assert institution in node.affiliated_institutions.all() + assert institution in node_public.affiliated_institutions.all() - res = self.app.post_json_api( - self.institution_nodes_url, - self.create_payload(self.node2._id, self.node1._id), + res = app.post_json_api( + url_institution_nodes, + make_payload(node_public._id, node._id), expect_errors=True, - auth=self.user.auth + auth=user.auth ) - assert_equal(res.status_code, 403) - self.node1.reload() - self.node2.reload() - assert_in(self.institution, self.node1.affiliated_institutions.all()) - assert_in(self.institution, self.node2.affiliated_institutions.all()) + assert res.status_code == 403 + node.reload() + node_public.reload() + assert institution in node.affiliated_institutions.all() + assert institution in node_public.affiliated_institutions.all() + + def test_only_add_existent_with_permissions(self, user, node, institution, app, url_institution_nodes, make_payload): + node_one = NodeFactory(creator=user) + node_one.affiliated_institutions.add(institution) + node_one.save() + assert institution in node.affiliated_institutions.all() + assert institution in node_one.affiliated_institutions.all() + + res = app.post_json_api( + url_institution_nodes, + make_payload(node_one._id, node._id), + auth=user.auth + ) - def test_only_add_existent_with_permissions(self): - node = NodeFactory(creator=self.user) - node.affiliated_institutions.add(self.institution) - node.save() - assert_in(self.institution, self.node1.affiliated_institutions.all()) - assert_in(self.institution, node.affiliated_institutions.all()) + assert res.status_code == 204 - res = self.app.post_json_api( - self.institution_nodes_url, - self.create_payload(node._id, self.node1._id), - auth=self.user.auth + def test_delete_user_is_admin(self, app, url_institution_nodes, make_payload, node, user, institution): + res = app.delete_json_api( + url_institution_nodes, + make_payload(node._id), + auth=user.auth ) + node.reload() + assert res.status_code == 204 + assert institution not in node.affiliated_institutions.all() - assert_equal(res.status_code, 204) + def test_delete_user_is_read_write(self, node_private, user, app, url_institution_nodes, make_payload, institution): + node_private.add_contributor(user) + node_private.save() - def test_delete_user_is_admin(self): - res = self.app.delete_json_api( - self.institution_nodes_url, - self.create_payload(self.node1._id), - auth=self.user.auth - ) - self.node1.reload() - assert_equal(res.status_code, 204) - assert_not_in(self.institution, self.node1.affiliated_institutions.all()) - - def test_delete_user_is_read_write(self): - self.node3.add_contributor(self.user) - self.node3.save() - - res = self.app.delete_json_api( - self.institution_nodes_url, - self.create_payload(self.node3._id), - auth=self.user.auth + res = app.delete_json_api( + url_institution_nodes, + make_payload(node_private._id), + auth=user.auth ) - self.node3.reload() + node_private.reload() - assert_equal(res.status_code, 204) - assert_not_in(self.institution, self.node3.affiliated_institutions.all()) + assert res.status_code == 204 + assert institution not in node_private.affiliated_institutions.all() - def test_delete_user_is_read_only(self): - self.node3.add_contributor(self.user, permissions='read') - self.node3.save() + def test_delete_user_is_read_only(self, node_private, user, app, url_institution_nodes, make_payload, institution): + node_private.add_contributor(user, permissions='read') + node_private.save() - res = self.app.delete_json_api( - self.institution_nodes_url, - self.create_payload(self.node3._id), - auth=self.user.auth, + res = app.delete_json_api( + url_institution_nodes, + make_payload(node_private._id), + auth=user.auth, expect_errors=True ) - self.node3.reload() + node_private.reload() - assert_equal(res.status_code, 403) - assert_in(self.institution, self.node3.affiliated_institutions.all()) + assert res.status_code == 403 + assert institution in node_private.affiliated_institutions.all() - def test_delete_user_is_admin_and_affiliated_with_inst(self): - assert_in(self.institution, self.node1.affiliated_institutions.all()) + def test_delete_user_is_admin_and_affiliated_with_inst(self, institution, node, app, url_institution_nodes, make_payload, user): + assert institution in node.affiliated_institutions.all() - res = self.app.delete_json_api( - self.institution_nodes_url, - self.create_payload(self.node1._id), - auth=self.user.auth + res = app.delete_json_api( + url_institution_nodes, + make_payload(node._id), + auth=user.auth ) - assert_equal(res.status_code, 204) - self.node1.reload() - assert_not_in(self.institution, self.node1.affiliated_institutions.all()) + assert res.status_code == 204 + node.reload() + assert institution not in node.affiliated_institutions.all() - def test_delete_user_is_admin_but_not_affiliated_with_inst(self): + def test_delete_user_is_admin_but_not_affiliated_with_inst(self, institution, app, url_institution_nodes, make_payload): user = AuthUserFactory() node = NodeFactory(creator=user) - node.affiliated_institutions.add(self.institution) + node.affiliated_institutions.add(institution) node.save() - assert_in(self.institution, node.affiliated_institutions.all()) + assert institution in node.affiliated_institutions.all() - res = self.app.delete_json_api( - self.institution_nodes_url, - self.create_payload(node._id), + res = app.delete_json_api( + url_institution_nodes, + make_payload(node._id), auth=user.auth ) - assert_equal(res.status_code, 204) + assert res.status_code == 204 node.reload() - assert_not_in(self.institution, node.affiliated_institutions.all()) + assert institution not in node.affiliated_institutions.all() - def test_delete_user_is_affiliated_with_inst_and_mixed_permissions_on_nodes(self): - res = self.app.delete_json_api( - self.institution_nodes_url, - self.create_payload(self.node1._id, self.node2._id), + def test_delete_user_is_affiliated_with_inst_and_mixed_permissions_on_nodes(self, app, url_institution_nodes, make_payload, node, node_public, user): + res = app.delete_json_api( + url_institution_nodes, + make_payload(node._id, node_public._id), expect_errors=True, - auth=self.user.auth + auth=user.auth ) - assert_equal(res.status_code, 403) + assert res.status_code == 403 From 1e5a956eb289b8333ecf3c3cc00f51295f37870a Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Thu, 6 Jul 2017 09:57:24 -0400 Subject: [PATCH 16/62] Convert institutions users to pytest --- .../views/test_institution_users_list.py | 55 ++++++++++++------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/api_tests/institutions/views/test_institution_users_list.py b/api_tests/institutions/views/test_institution_users_list.py index 3c13839e7f0..9464beed897 100644 --- a/api_tests/institutions/views/test_institution_users_list.py +++ b/api_tests/institutions/views/test_institution_users_list.py @@ -1,29 +1,42 @@ -from nose.tools import * # flake8: noqa - -from tests.base import ApiTestCase -from osf_tests.factories import InstitutionFactory, UserFactory +import pytest from api.base.settings.defaults import API_BASE +from osf_tests.factories import ( + InstitutionFactory, + UserFactory, +) + +@pytest.mark.django_db +class TestInstitutionUsersList: + + @pytest.fixture() + def institution(self): + return InstitutionFactory() + + @pytest.fixture() + def user_one(self, institution): + user_one = UserFactory() + user_one.affiliated_institutions.add(institution) + user_one.save() + return user_one -class TestInstitutionUsersList(ApiTestCase): - def setUp(self): - super(TestInstitutionUsersList, self).setUp() - self.institution = InstitutionFactory() - self.user1 = UserFactory() - self.user1.affiliated_institutions.add(self.institution) - self.user1.save() - self.user2 = UserFactory() - self.user2.affiliated_institutions.add(self.institution) - self.user2.save() + @pytest.fixture() + def user_two(self, institution): + user_two = UserFactory() + user_two.affiliated_institutions.add(institution) + user_two.save() + return user_two - self.institution_user_url = '/{0}institutions/{1}/users/'.format(API_BASE, self.institution._id) + @pytest.fixture() + def url_institution_user(self, institution): + return '/{0}institutions/{1}/users/'.format(API_BASE, institution._id) - def test_return_all_users(self): - res = self.app.get(self.institution_user_url) + def test_return_all_users(self, app, institution, user_one, user_two, url_institution_user): + res = app.get(url_institution_user) - assert_equal(res.status_code, 200) + assert res.status_code == 200 ids = [each['id'] for each in res.json['data']] - assert_equal(len(res.json['data']), 2) - assert_in(self.user1._id, ids) - assert_in(self.user2._id, ids) + assert len(res.json['data']) == 2 + assert user_one._id in ids + assert user_two._id in ids From eea9655d6b92c9bfd0276b1173010dad9fa54fa5 Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Thu, 6 Jul 2017 10:56:19 -0400 Subject: [PATCH 17/62] Convert license detail to pytest --- .../licenses/views/test_license_detail.py | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/api_tests/licenses/views/test_license_detail.py b/api_tests/licenses/views/test_license_detail.py index 547d08bc975..4d81c574261 100644 --- a/api_tests/licenses/views/test_license_detail.py +++ b/api_tests/licenses/views/test_license_detail.py @@ -1,29 +1,39 @@ -from nose.tools import * # flake8: noqa +import pytest import functools -from tests.base import ApiTestCase -from osf.models.licenses import NodeLicense from api.base.settings.defaults import API_BASE +from osf.models.licenses import NodeLicense + +@pytest.mark.django_db +class TestLicenseDetail: + @pytest.fixture() + def license(self): + return NodeLicense.find()[0] + + @pytest.fixture() + def url_license(self, license): + return '/{}licenses/{}/'.format(API_BASE, license._id) + + @pytest.fixture() + def res_license(self, app, url_license): + return app.get(url_license) + @pytest.fixture() + def data_license(self, res_license): + return res_license.json['data'] -class TestLicenseDetail(ApiTestCase): - def setUp(self): - super(TestLicenseDetail, self).setUp() - self.license = NodeLicense.find()[0] - self.url = '/{}licenses/{}/'.format(API_BASE, self.license._id) - self.res = self.app.get(self.url) - self.data = self.res.json['data'] + def test_license_detail(self, license, res_license, data_license): - def test_license_detail_success(self): - assert_equal(self.res.status_code, 200) - assert_equal(self.res.content_type, 'application/vnd.api+json') + #test_license_detail_success(self, res_license): + assert res_license.status_code == 200 + assert res_license.content_type == 'application/vnd.api+json' - def test_license_top_level(self): - assert_equal(self.data['type'], 'licenses') - assert_equal(self.data['id'], self.license._id) + #test_license_top_level(self, license, data_license): + assert data_license['type'] == 'licenses' + assert data_license['id'] == license._id - def test_license_name(self): - assert_equal(self.data['attributes']['name'], self.license.name) + #test_license_name(self, data_license, license): + assert data_license['attributes']['name'] == license.name - def test_license_text(self): - assert_equal(self.data['attributes']['text'], self.license.text) + #test_license_text(self, data_license, license): + assert data_license['attributes']['text'] == license.text From bd0a1285c99cbc34970430d4b70e65d43d247cde Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Thu, 6 Jul 2017 10:56:45 -0400 Subject: [PATCH 18/62] Convert license list to pytest --- api_tests/licenses/views/test_license_list.py | 73 ++++++++++--------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/api_tests/licenses/views/test_license_list.py b/api_tests/licenses/views/test_license_list.py index 1446b28037c..0ceaaa54624 100644 --- a/api_tests/licenses/views/test_license_list.py +++ b/api_tests/licenses/views/test_license_list.py @@ -1,41 +1,44 @@ -from nose.tools import * # flake8: noqa +import pytest -from tests.base import ApiTestCase -from osf.models.licenses import NodeLicense from api.base.settings.defaults import API_BASE +from osf.models.licenses import NodeLicense + +@pytest.mark.django_db +class TestLicenseList: + + @pytest.fixture() + def licenses(self): + return NodeLicense.find() + + @pytest.fixture() + def url_licenses(self): + return '/{}licenses/'.format(API_BASE) + @pytest.fixture() + def res_licenses(self, app, url_licenses): + return app.get(url_licenses) -class TestLicenseList(ApiTestCase): - def setUp(self): - super(TestLicenseList, self).setUp() - self.licenses = NodeLicense.find() - - def test_license_list_success(self): - url = '/{}licenses/'.format(API_BASE) - res = self.app.get(url) - assert_equal(res.status_code, 200) - assert_equal(res.content_type, 'application/vnd.api+json') - - def test_license_list_count_correct(self): - url = '/{}licenses/'.format(API_BASE) - res = self.app.get(url) - total = res.json['links']['meta']['total'] - assert_equal(total, self.licenses.count()) - - def test_license_list_name_filter(self): - license = self.licenses[0] - name = license.name - url = '/{}licenses/?filter[name]={}'.format(API_BASE, name) - res = self.app.get(url) + + def test_license_list(self, licenses, app, url_licenses, res_licenses): + #test_license_list_success + assert res_licenses.status_code == 200 + assert res_licenses.content_type == 'application/vnd.api+json' + + #test_license_list_count_correct + total = res_licenses.json['links']['meta']['total'] + assert total == licenses.count() + + #test_license_list_name_filter + license = licenses[0] + url = '/{}licenses/?filter[name]={}'.format(API_BASE, license.name) + res = app.get(url) data = res.json['data'][0] - assert_equal(data['attributes']['name'], name) - assert_equal(data['id'], license._id) - - def test_license_list_id_filter(self): - license = self.licenses[0] - id = license._id - url = '/{}licenses/?filter[id]={}'.format(API_BASE, id) - res = self.app.get(url) + assert data['attributes']['name'] == license.name + assert data['id'] == license._id + + #test_license_list_id_filter(self, licenses): + url = '/{}licenses/?filter[id]={}'.format(API_BASE, license._id) + res = app.get(url) data = res.json['data'][0] - assert_equal(data['attributes']['name'], license.name) - assert_equal(data['id'], id) + assert data['attributes']['name'] == license.name + assert data['id'] == license._id From 98c0d2c33e9ce566af9f46c81dfac0dc766161fa Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Thu, 6 Jul 2017 21:36:27 -0400 Subject: [PATCH 19/62] Convert logs detail to pytest --- api_tests/logs/views/test_log_detail.py | 260 +++++++++++++++--------- 1 file changed, 159 insertions(+), 101 deletions(-) diff --git a/api_tests/logs/views/test_log_detail.py b/api_tests/logs/views/test_log_detail.py index c28ac35b3cb..2eb5cddd985 100644 --- a/api_tests/logs/views/test_log_detail.py +++ b/api_tests/logs/views/test_log_detail.py @@ -1,142 +1,200 @@ -# -*- coding: utf-8 -*- +import pytest -from nose.tools import * # noqa - -from tests.base import ApiTestCase +from api.base.settings.defaults import API_BASE +from api_tests import utils as api_utils +from framework.auth.core import Auth +from osf.models import NodeLog from osf_tests.factories import ( ProjectFactory, AuthUserFactory, NodeFactory, ) - -from framework.auth.core import Auth - -from osf.models import NodeLog from website.util import permissions as osf_permissions -from api.base.settings.defaults import API_BASE -from api_tests import utils as api_utils - - -class LogsTestCase(ApiTestCase): - def setUp(self): - super(LogsTestCase, self).setUp() +@pytest.mark.django_db +class LogsTestCase: - self.user = AuthUserFactory() - self.user_two = AuthUserFactory() + @pytest.fixture() + def user_one(self): + return AuthUserFactory() - self.action_set = NodeLog.actions - self.node = ProjectFactory(is_public=False) + @pytest.fixture() + def user_two(self): + return AuthUserFactory() - self.node.add_contributor(self.user, permissions=[osf_permissions.READ], auth=Auth(self.node.creator), log=True, save=True) + @pytest.fixture() + def action_set(self): + return NodeLog.actions - logs = list(self.node.logs.order_by('date')) - self.log = logs[0] - self.log_add_contributor = logs[1] + @pytest.fixture() + def node_private(self, user_one): + node_private = ProjectFactory(is_public=False) + node_private.add_contributor(user_one, permissions=[osf_permissions.READ], auth=Auth(node_private.creator), log=True, save=True) + return node_private - self.public_node = ProjectFactory(is_public=True) - self.public_node.add_contributor(self.user, permissions=[osf_permissions.READ], auth=Auth(self.public_node.creator), log=True, save=True) + @pytest.fixture() + def node_public(self, user_one): + node_public = ProjectFactory(is_public=True) + node_public.add_contributor(user_one, permissions=[osf_permissions.READ], auth=Auth(node_public.creator), log=True, save=True) + return node_public - public_logs = list(self.public_node.logs.order_by('date')) - self.public_log = public_logs[0] - self.public_log_add_contributor = public_logs[1] + @pytest.fixture() + def logs_public(self, node_public): + return list(node_public.logs.order_by('date')) - self.node_log_url = '/{}nodes/{}/logs/'.format(API_BASE, self.node._id) - self.url = '/{}logs/'.format(API_BASE) - self.log_nodes_url = self.url + '{}/nodes/'.format(self.log._id) - self.private_log_detail = self.url + '{}/'.format(self.log._id) - self.log_public_nodes_url = self.url + '{}/nodes/'.format(self.public_log._id) - self.public_log_detail = self.url + '{}/'.format(self.public_log._id) + @pytest.fixture() + def log_public(self, logs_public): + return logs_public[0] + @pytest.fixture() + def contributor_log_public(self, logs_public): + return logs_public[1] -class TestLogDetail(LogsTestCase): - - def test_log_detail_returns_data(self): - res = self.app.get(self.private_log_detail, auth=self.user.auth) - assert_equal(res.status_code, 200) - json_data = res.json['data'] - assert_equal(json_data['id'], self.log._id) - - def test_log_detail_private_not_logged_in_cannot_access_logs(self): - res = self.app.get(self.private_log_detail, expect_errors=True) - assert_equal(res.status_code, 401) + @pytest.fixture() + def logs_private(self, node_private): + return list(node_private.logs.order_by('date')) - def test_log_detail_private_non_contributor_cannot_access_logs(self): - res = self.app.get(self.private_log_detail, auth=self.user_two.auth, expect_errors=True) - assert_equal(res.status_code, 403) + @pytest.fixture() + def log_private(self, logs_private): + return logs_private[0] - def test_log_detail_public_not_logged_in_can_access_logs(self): - res = self.app.get(self.public_log_detail, expect_errors=True) - assert_equal(res.status_code, 200) - json_data = res.json['data'] - assert_equal(json_data['id'], self.public_log._id) - - def test_log_detail_public_non_contributor_can_access_logs(self): - res = self.app.get(self.public_log_detail, auth=self.user_two.auth, expect_errors=True) - assert_equal(res.status_code, 200) - json_data = res.json['data'] - assert_equal(json_data['id'], self.public_log._id) + @pytest.fixture() + def contributor_log_private(self, logs_private): + return logs_private[1] - def test_log_detail_data_format_api(self): - res = self.app.get(self.public_log_detail + '?format=api', auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_in(self.public_log._id, unicode(res.body, 'utf-8')) + @pytest.fixture() + def url_node_private_log(self, node_private): + return '/{}nodes/{}/logs/'.format(API_BASE, node_private._id) + @pytest.fixture() + def url_logs(self): + return '/{}logs/'.format(API_BASE) -class TestNodeFileLogDetail(ApiTestCase): + @pytest.fixture() + def url_log_private_nodes(self, log_private, url_logs): + return url_logs + '{}/nodes/'.format(log_private._id) - def setUp(self): - super(TestNodeFileLogDetail, self).setUp() + @pytest.fixture() + def url_log_public_nodes(self, log_public, url_logs): + return url_logs + '{}/nodes/'.format(log_public._id) - self.user_one = AuthUserFactory() - self.user_two = AuthUserFactory() + @pytest.fixture() + def url_log_detail_private(self, log_private, url_logs): + return url_logs + '{}/'.format(log_private._id) - self.node = ProjectFactory(creator=self.user_one) - self.node.add_contributor(self.user_two) + @pytest.fixture() + def url_log_detail_public(self, log_public, url_logs): + return url_logs + '{}/'.format(log_public._id) - self.component = NodeFactory(parent=self.node, creator=self.user_one) +@pytest.mark.django_db +class TestLogDetail(LogsTestCase): - self.file = api_utils.create_test_file(node=self.component, user=self.user_one) - self.node.add_log( + def test_log_detail_private(self, app, url_log_detail_private, user_one, user_two, log_private): + #test_log_detail_returns_data + res = app.get(url_log_detail_private, auth=user_one.auth) + assert res.status_code == 200 + json_data = res.json['data'] + assert json_data['id'] == log_private._id + + #test_log_detail_private_not_logged_in_cannot_access_logs + res = app.get(url_log_detail_private, expect_errors=True) + assert res.status_code == 401 + + #test_log_detail_private_non_contributor_cannot_access_logs + res = app.get(url_log_detail_private, auth=user_two.auth, expect_errors=True) + assert res.status_code == 403 + + def test_log_detail_public(self, app, url_log_detail_public, log_public, user_two, user_one): + #test_log_detail_public_not_logged_in_can_access_logs + res = app.get(url_log_detail_public, expect_errors=True) + assert res.status_code == 200 + data = res.json['data'] + assert data['id'] == log_public._id + + #test_log_detail_public_non_contributor_can_access_logs + res = app.get(url_log_detail_public, auth=user_two.auth, expect_errors=True) + assert res.status_code == 200 + data = res.json['data'] + assert data['id'] == log_public._id + + #test_log_detail_data_format_api + res = app.get(url_log_detail_public + '?format=api', auth=user_one.auth) + assert res.status_code == 200 + assert log_public._id in unicode(res.body, 'utf-8') + +@pytest.mark.django_db +class TestNodeFileLogDetail: + + @pytest.fixture() + def user_one(self): + return AuthUserFactory() + + @pytest.fixture() + def user_two(self): + return AuthUserFactory() + + @pytest.fixture() + def node(self, user_one, user_two): + node = ProjectFactory(creator=user_one) + node.add_contributor(user_two) + return node + + @pytest.fixture() + def component(self, user_one, node): + return NodeFactory(parent=node, creator=user_one) + + @pytest.fixture() + def file(self, user_one, component): + return api_utils.create_test_file(node=component, user=user_one) + + @pytest.fixture() + def url_node_logs(self, node): + return '/{}nodes/{}/logs/'.format(API_BASE, node._id) + + @pytest.fixture() + def url_component_logs(self, component): + return '/{}nodes/{}/logs/'.format(API_BASE, component._id) + + @pytest.fixture() + def node_with_log(self, node, user_one, file, component): + node.add_log( 'osf_storage_file_moved', - auth=Auth(self.user_one), + auth=Auth(user_one), params={ - 'node': self.node._id, - 'project': self.node.parent_id, - 'path': self.file.materialized_path, + 'node': node._id, + 'project': node.parent_id, + 'path': file.materialized_path, 'source': { - 'materialized': self.file.materialized_path, + 'materialized': file.materialized_path, 'addon': 'osfstorage', 'node': { - '_id': self.component._id, - 'url': self.component.url, - 'title': self.component.title, + '_id': component._id, + 'url': component.url, + 'title': component.title, } }, 'destination': { - 'materialized': self.file.materialized_path, + 'materialized': file.materialized_path, 'addon': 'osfstorage', 'node': { - '_id': self.node._id, - 'url': self.node.url, - 'title': self.node.title, + '_id': node._id, + 'url': node.url, + 'title': node.title, } } }, ) - - self.node.save() - - self.node_logs_url = '/{}nodes/{}/logs/'.format(API_BASE, self.node._id) - self.component_logs_url = '/{}nodes/{}/logs/'.format(API_BASE, self.component._id) - - def test_title_not_hidden_from_contributor_in_file_move(self): - res = self.app.get(self.node_logs_url, auth=self.user_two.auth) - assert_equal(res.status_code, 200) - assert_equal(res.json['data'][0]['attributes']['params']['destination']['node_title'], self.node.title) - - def test_title_hidden_from_non_contributor_in_file_move(self): - res = self.app.get(self.node_logs_url, auth=self.user_two.auth) - assert_equal(res.status_code, 200) - assert_not_in(self.component.title, res.json['data']) - assert_equal(res.json['data'][0]['attributes']['params']['source']['node_title'], 'Private Component') + node.save() + return node + + def test_title_visibility_in_file_move(self, app, url_node_logs, user_two, component, node_with_log): + #test_title_not_hidden_from_contributor_in_file_move + res = app.get(url_node_logs, auth=user_two.auth) + assert res.status_code == 200 + assert res.json['data'][0]['attributes']['params']['destination']['node_title'] == node_with_log.title + + #test_title_hidden_from_non_contributor_in_file_move + res = app.get(url_node_logs, auth=user_two.auth) + assert res.status_code == 200 + assert component.title not in res.json['data'] + assert res.json['data'][0]['attributes']['params']['source']['node_title'] == 'Private Component' From 0c7e09884e17f0be8ad5a77690f5151bbd41cb92 Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Thu, 6 Jul 2017 21:36:47 -0400 Subject: [PATCH 20/62] Convert logs params to pytest --- api_tests/logs/views/test_log_params.py | 69 ++++++++++++------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/api_tests/logs/views/test_log_params.py b/api_tests/logs/views/test_log_params.py index af8c0a9027b..66147a49a23 100644 --- a/api_tests/logs/views/test_log_params.py +++ b/api_tests/logs/views/test_log_params.py @@ -1,70 +1,67 @@ -# -*- coding: utf-8 -*- +import pytest +from api.base.settings.defaults import API_BASE from framework.auth.core import Auth - -from nose.tools import * # noqa -from test_log_detail import LogsTestCase from osf_tests.factories import ( ProjectFactory, PrivateLinkFactory ) - -from api.base.settings.defaults import API_BASE +from test_log_detail import LogsTestCase # TODO add tests for other log params - +@pytest.mark.django_db class TestLogContributors(LogsTestCase): - def test_contributor_added_log_has_contributor_info_in_params(self): - url = self.url + '{}/'.format(self.log_add_contributor._id) - res = self.app.get(url, auth=self.user.auth) - assert_equal(res.status_code, 200) + def test_contributor_added_log_has_contributor_info_in_params(self, app, node_private, contributor_log_private, url_logs, user_one): + url = url_logs + '{}/'.format(contributor_log_private._id) + res = app.get(url, auth=user_one.auth) + assert res.status_code == 200 params = res.json['data']['attributes']['params'] params_node = params['params_node'] contributors = params['contributors'][0] - assert_equal(params_node['id'], self.node._id) - assert_equal(params_node['title'], self.node.title) + assert params_node['id'] == node_private._id + assert params_node['title'] == node_private.title - assert_equal(contributors['family_name'], self.user.family_name) - assert_equal(contributors['full_name'], self.user.fullname) - assert_equal(contributors['given_name'], self.user.given_name) - assert_equal(contributors['unregistered_name'], None) + assert contributors['family_name'] == user_one.family_name + assert contributors['full_name'] == user_one.fullname + assert contributors['given_name'] == user_one.given_name + assert contributors['unregistered_name'] == None - def test_unregistered_contributor_added_has_contributor_info_in_params(self): - project = ProjectFactory(creator=self.user) - project.add_unregistered_contributor('Robert Jackson', 'robert@gmail.com', auth=Auth(self.user), save=True) + def test_unregistered_contributor_added_has_contributor_info_in_params(self, app, user_one): + project = ProjectFactory(creator=user_one) + project.add_unregistered_contributor('Robert Jackson', 'robert@gmail.com', auth=Auth(user_one), save=True) relevant_log = project.logs.latest() url = '/{}logs/{}/'.format(API_BASE, relevant_log._id) - res = self.app.get(url, auth=self.user.auth) + res = app.get(url, auth=user_one.auth) - assert_equal(res.status_code, 200) + assert res.status_code == 200 params = res.json['data']['attributes']['params'] params_node = params['params_node'] contributors = params['contributors'][0] - assert_equal(params_node['id'], project._id) - assert_equal(params_node['title'], project.title) + assert params_node['id'] == project._id + assert params_node['title'] == project.title - assert_equal(contributors['family_name'], 'Jackson') - assert_equal(contributors['full_name'], 'Robert Jackson') - assert_equal(contributors['given_name'], 'Robert') - assert_equal(contributors['unregistered_name'], 'Robert Jackson') + assert contributors['family_name'] == 'Jackson' + assert contributors['full_name'] == 'Robert Jackson' + assert contributors['given_name'] == 'Robert' + assert contributors['unregistered_name'] == 'Robert Jackson' - def test_params_do_not_appear_on_private_project_with_anonymous_view_only_link(self): + def test_params_do_not_appear_on_private_project_with_anonymous_view_only_link(self, app, url_logs, node_private, contributor_log_private, user_one): private_link = PrivateLinkFactory(anonymous=True) - private_link.nodes.add(self.node) + private_link.nodes.add(node_private) private_link.save() - url = self.url + '{}/'.format(self.log_add_contributor._id) + url = url_logs + '{}/'.format(contributor_log_private._id) - res = self.app.get(url, {'view_only': private_link.key}, expect_errors=True) - assert_equal(res.status_code, 200) + res = app.get(url, {'view_only': private_link.key}, expect_errors=True) + assert res.status_code == 200 data = res.json['data'] - assert_in('attributes', data) - assert_not_in('params', data['attributes']) + assert 'attributes' in data + assert 'params' not in data['attributes'] body = res.body - assert_not_in(self.user._id, body) + assert user_one._id not in body From 7ebd859a2d484e5bfd26fb1d7e6884aaf4ce90ff Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Thu, 6 Jul 2017 21:37:06 -0400 Subject: [PATCH 21/62] Convert logs embeds to pytest --- api_tests/logs/views/test_log_embeds.py | 78 +++++++++++++++---------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/api_tests/logs/views/test_log_embeds.py b/api_tests/logs/views/test_log_embeds.py index 474632194b5..c40c8205073 100644 --- a/api_tests/logs/views/test_log_embeds.py +++ b/api_tests/logs/views/test_log_embeds.py @@ -1,56 +1,70 @@ -from nose.tools import * # flake8: noqa +import pytest from api.base.settings.defaults import API_BASE -from tests.base import ApiTestCase from osf_tests.factories import ( ProjectFactory, AuthUserFactory, RegistrationFactory ) +@pytest.mark.django_db +class TestLogEmbeds: -class TestLogEmbeds(ApiTestCase): + @pytest.fixture() + def user(self): + return AuthUserFactory() + @pytest.fixture() + def project(self, user): + return ProjectFactory(is_public=True, creator=user) - def setUp(self): - super(TestLogEmbeds, self).setUp() + @pytest.fixture() + def registration(self, user, project): + return RegistrationFactory(project=project, creator=user, is_public=True) - self.user = AuthUserFactory() - self.project = ProjectFactory(is_public=True, creator=self.user) - self.registration = RegistrationFactory(project=self.project, creator=self.user, is_public=True) + @pytest.fixture() + def registration_log(self, registration): + return registration.logs.order_by('date').first() - self.first_reg_log = self.registration.logs.order_by('date').first() + @pytest.fixture() + def make_url_registration_log(self, registration_log): + def url_registration_log(type_embed): + return '/{}logs/{}/?embed={}'.format(API_BASE, registration_log._id, type_embed) + return url_registration_log - def test_embed_original_node(self): - registration_log_url = '/{}logs/{}/?embed=original_node'.format(API_BASE, self.first_reg_log._id) - res = self.app.get(registration_log_url, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal(res.json['data']['attributes']['action'], 'project_created') + def test_log_embed_types(self, app, registration_log, make_url_registration_log, user, project, registration): + + #test_embed_original_node + url_registration_log = make_url_registration_log(type_embed='original_node') + + res = app.get(url_registration_log, auth=user.auth) + assert res.status_code == 200 + assert res.json['data']['attributes']['action'] == 'project_created' embeds = res.json['data']['embeds']['original_node'] - assert_equal(embeds['data']['id'], self.project._id) + assert embeds['data']['id'] == project._id - def test_embed_node(self): - registration_log_url = '/{}logs/{}/?embed=node'.format(API_BASE, self.first_reg_log._id) + #test_embed_node + url_registration_log = make_url_registration_log(type_embed='node') - res = self.app.get(registration_log_url, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal(res.json['data']['attributes']['action'], 'project_created') + res = app.get(url_registration_log, auth=user.auth) + assert res.status_code == 200 + assert res.json['data']['attributes']['action'] == 'project_created' embeds = res.json['data']['embeds']['node'] - assert_equal(embeds['data']['id'], self.registration._id) + assert embeds['data']['id'] == registration._id - def test_embed_user(self): - registration_log_url = '/{}logs/{}/?embed=user'.format(API_BASE, self.first_reg_log._id) + #test_embed_user + url_registration_log = make_url_registration_log(type_embed='user') - res = self.app.get(registration_log_url, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal(res.json['data']['attributes']['action'], 'project_created') + res = app.get(url_registration_log, auth=user.auth) + assert res.status_code == 200 + assert res.json['data']['attributes']['action'] == 'project_created' embeds = res.json['data']['embeds']['user'] - assert_equal(embeds['data']['id'], self.user._id) + assert embeds['data']['id'] == user._id - def test_embed_attributes_not_relationships(self): - url = '/{}logs/{}/?embed=action'.format(API_BASE, self.first_reg_log._id) + #test_embed_attributes_not_relationships + url_registration_log = make_url_registration_log(type_embed='action') - res = self.app.get(url, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], "The following fields are not embeddable: action") + res = app.get(url_registration_log, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == "The following fields are not embeddable: action" From af0a2f061bf0201e783fd97471c7e4d59674bb0e Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Thu, 6 Jul 2017 22:30:48 -0400 Subject: [PATCH 22/62] Convert metaschemas detail to pytest --- .../views/test_metaschemas_detail.py | 86 ++++++++++--------- 1 file changed, 47 insertions(+), 39 deletions(-) diff --git a/api_tests/metaschemas/views/test_metaschemas_detail.py b/api_tests/metaschemas/views/test_metaschemas_detail.py index a8f7c05fb9a..36d7c1cf24e 100644 --- a/api_tests/metaschemas/views/test_metaschemas_detail.py +++ b/api_tests/metaschemas/views/test_metaschemas_detail.py @@ -1,52 +1,60 @@ -from nose.tools import * # flake8: noqa - -from website.project.metadata.schemas import LATEST_SCHEMA_VERSION -from website.project.model import Q -from osf.models import MetaSchema +import pytest from api.base.settings.defaults import API_BASE - -from tests.base import ApiTestCase +from osf.models import MetaSchema from osf_tests.factories import ( AuthUserFactory ) -class TestMetaSchemaDetail(ApiTestCase): - def setUp(self): - super(TestMetaSchemaDetail, self).setUp() - self.user = AuthUserFactory() - self.schema = MetaSchema.find_one(Q('name', 'eq', 'Prereg Challenge') & Q('schema_version', 'eq', LATEST_SCHEMA_VERSION)) - self.url = '/{}metaschemas/{}/'.format(API_BASE, self.schema._id) - - def test_pass_authenticated_user_can_retrieve_schema(self): - res = self.app.get(self.url, auth=self.user.auth) - assert_equal(res.status_code, 200) +from website.project.metadata.schemas import LATEST_SCHEMA_VERSION +from website.project.model import Q + +@pytest.mark.django_db +class TestMetaSchemaDetail: + + @pytest.fixture() + def user(self): + return AuthUserFactory() + + @pytest.fixture() + def schema(self): + return MetaSchema.find_one(Q('name', 'eq', 'Prereg Challenge') & Q('schema_version', 'eq', LATEST_SCHEMA_VERSION)) + + @pytest.fixture() + def url_metaschemas_detail(self, schema): + return '/{}metaschemas/{}/'.format(API_BASE, schema._id) + + def test_metaschemas_detail_visibility(self, app, schema, url_metaschemas_detail, user): + + #test_pass_authenticated_user_can_retrieve_schema + res = app.get(url_metaschemas_detail, auth=user.auth) + assert res.status_code == 200 data = res.json['data']['attributes'] - assert_equal(data['name'], 'Prereg Challenge') - assert_equal(data['schema_version'], 2) - assert_true(data['active']) - assert_equal(res.json['data']['id'], self.schema._id) + assert data['name'] == 'Prereg Challenge' + assert data['schema_version'] == 2 + assert data['active'] + assert res.json['data']['id'] == schema._id - def test_pass_unauthenticated_user_can_view_schemas(self): - res = self.app.get(self.url) - assert_equal(res.status_code, 200) + #test_pass_unauthenticated_user_can_view_schemas + res = app.get(url_metaschemas_detail) + assert res.status_code == 200 - def test_inactive_metaschema_returned(self): + #test_inactive_metaschema_returned inactive_schema = MetaSchema.objects.get(name='Election Research Preacceptance Competition', active=False) url = '/{}metaschemas/{}/'.format(API_BASE, inactive_schema._id) - res = self.app.get(url) - assert_equal(res.status_code, 200) - assert_equal(res.json['data']['attributes']['name'], 'Election Research Preacceptance Competition') - assert_equal(res.json['data']['attributes']['active'], False) + res = app.get(url) + assert res.status_code == 200 + assert res.json['data']['attributes']['name'] == 'Election Research Preacceptance Competition' + assert res.json['data']['attributes']['active'] == False - def test_non_latest_version_metaschema_returned(self): + #test_non_latest_version_metaschema_returned old_schema = MetaSchema.objects.get(name='OSF-Standard Pre-Data Collection Registration', schema_version=1) url = '/{}metaschemas/{}/'.format(API_BASE, old_schema._id) - res = self.app.get(url) - assert_equal(res.status_code, 200) - assert_equal(res.json['data']['attributes']['name'], 'OSF-Standard Pre-Data Collection Registration') - assert_equal(res.json['data']['attributes']['schema_version'], 1) - - def test_invalid_metaschema_not_found(self): - self.url = '/{}metaschemas/garbage/'.format(API_BASE) - res = self.app.get(self.url, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 404) + res = app.get(url) + assert res.status_code == 200 + assert res.json['data']['attributes']['name'] == 'OSF-Standard Pre-Data Collection Registration' + assert res.json['data']['attributes']['schema_version'] == 1 + + #test_invalid_metaschema_not_found + url = '/{}metaschemas/garbage/'.format(API_BASE) + res = app.get(url, auth=user.auth, expect_errors=True) + assert res.status_code == 404 From 8adbfed49e9bd046a5eb5616ccf90e1512f3850b Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Thu, 6 Jul 2017 22:30:59 -0400 Subject: [PATCH 23/62] Convert metaschemas list to pytest --- .../views/test_metaschemas_list.py | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/api_tests/metaschemas/views/test_metaschemas_list.py b/api_tests/metaschemas/views/test_metaschemas_list.py index a99ed3c98b1..6b2b3ba3d94 100644 --- a/api_tests/metaschemas/views/test_metaschemas_list.py +++ b/api_tests/metaschemas/views/test_metaschemas_list.py @@ -1,38 +1,39 @@ -from nose.tools import * # flake8: noqa - -from osf.models.metaschema import MetaSchema -from website.project.metadata.schemas import LATEST_SCHEMA_VERSION +import pytest from api.base.settings.defaults import API_BASE - -from tests.base import ApiTestCase +from osf.models.metaschema import MetaSchema from osf_tests.factories import ( AuthUserFactory ) +from website.project.metadata.schemas import LATEST_SCHEMA_VERSION + +@pytest.mark.django_db +class TestMetaSchemaList: + @pytest.fixture() + def user(self): + return AuthUserFactory() -class TestMetaSchemaList(ApiTestCase): - def setUp(self): - super(TestMetaSchemaList, self).setUp() - self.user = AuthUserFactory() - self.url = '/{}metaschemas/'.format(API_BASE) + @pytest.fixture() + def url_metaschemas_list(self): + return '/{}metaschemas/'.format(API_BASE) - def test_pass_authenticated_user_can_view_schemas(self): - res = self.app.get(self.url, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal( - len(res.json['data']), - MetaSchema.objects.filter(active=True, schema_version=LATEST_SCHEMA_VERSION).count() - ) + def test_metaschemas_list_visibility_create_update(self, app, url_metaschemas_list, user): + #test_pass_authenticated_user_can_view_schemas + res = app.get(url_metaschemas_list, auth=user.auth) + assert res.status_code == 200 + assert ( + len(res.json['data']) == + MetaSchema.objects.filter(active=True, schema_version=LATEST_SCHEMA_VERSION).count()) - def test_cannot_update_metaschemas(self): - res = self.app.put_json_api(self.url, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 405) + #test_cannot_update_metaschemas + res = app.put_json_api(url_metaschemas_list, auth=user.auth, expect_errors=True) + assert res.status_code == 405 - def test_cannot_post_metaschemas(self): - res = self.app.post_json_api(self.url, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 405) + #test_cannot_post_metaschemas + res = app.post_json_api(url_metaschemas_list, auth=user.auth, expect_errors=True) + assert res.status_code == 405 - def test_pass_unauthenticated_user_can_view_schemas(self): - res = self.app.get(self.url) - assert_equal(res.status_code, 200) + #test_pass_unauthenticated_user_can_view_schemas + res = app.get(url_metaschemas_list) + assert res.status_code == 200 From d930f8d4ca5a01b4e0ee6eb38c3b486875252c4c Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Fri, 7 Jul 2017 00:35:57 -0400 Subject: [PATCH 24/62] Convert guid detail to pytest --- api_tests/guids/views/test_guid_detail.py | 173 ++++++++++++---------- 1 file changed, 93 insertions(+), 80 deletions(-) diff --git a/api_tests/guids/views/test_guid_detail.py b/api_tests/guids/views/test_guid_detail.py index 4d9679006f2..f5f490b6017 100644 --- a/api_tests/guids/views/test_guid_detail.py +++ b/api_tests/guids/views/test_guid_detail.py @@ -1,53 +1,70 @@ -from nose.tools import * # flake8: noqa -from api.base.settings.defaults import API_BASE import pytest from addons.osfstorage.models import OsfStorageFile -from website.settings import API_DOMAIN - -from tests.base import ApiTestCase -from osf_tests.factories import (AuthUserFactory, ProjectFactory, RegistrationFactory, - CommentFactory, CollectionFactory, PrivateLinkFactory) from addons.wiki.tests.factories import NodeWikiFactory +from api.base.settings.defaults import API_BASE +from osf_tests.factories import ( + AuthUserFactory, + ProjectFactory, + RegistrationFactory, + CommentFactory, + CollectionFactory, + PrivateLinkFactory, +) +from website.settings import API_DOMAIN -class TestGuidDetail(ApiTestCase): - - def setUp(self): - super(TestGuidDetail, self).setUp() - self.user = AuthUserFactory() - - def _add_private_link(self, project, anonymous=False): - view_only_link = PrivateLinkFactory(anonymous=anonymous) - view_only_link.nodes.add(project) - view_only_link.save() - return view_only_link - - def test_redirect_to_node_view(self): - project = ProjectFactory() - url = '/{}guids/{}/'.format(API_BASE, project._id) - res = self.app.get(url, auth=self.user.auth) +@pytest.mark.django_db +class TestGuidDetail: + + @pytest.fixture() + def user(self): + return AuthUserFactory() + + @pytest.fixture() + def project(self): + return ProjectFactory() + + @pytest.fixture() + def _add_private_link(self, project): + def private_link(anonymous=False): + view_only_link = PrivateLinkFactory(anonymous=anonymous) + view_only_link.nodes.add(project) + view_only_link.save() + return view_only_link + return private_link + + @pytest.fixture() + def url_guids_detail(self): + def url(id): + return '/{}guids/{}/'.format(API_BASE, id) + return url + + def test_redirects(self, app, project, url_guids_detail, user): + #test_redirect_to_node_view + url = url_guids_detail(project._id) + res = app.get(url, auth=user.auth) redirect_url = '{}{}nodes/{}/'.format(API_DOMAIN, API_BASE, project._id) - assert_equal(res.status_code, 302) - assert_equal(res.location, redirect_url) + assert res.status_code == 302 + assert res.location == redirect_url - def test_redirect_to_registration_view(self): + #test_redirect_to_registration_view registration = RegistrationFactory() - url = '/{}guids/{}/'.format(API_BASE, registration._id) - res = self.app.get(url, auth=self.user.auth) + url = url_guids_detail(registration._id) + res = app.get(url, auth=user.auth) redirect_url = '{}{}registrations/{}/'.format(API_DOMAIN, API_BASE, registration._id) - assert_equal(res.status_code, 302) - assert_equal(res.location, redirect_url) + assert res.status_code == 302 + assert res.location == redirect_url - def test_redirect_to_collections_view(self): + #test_redirect_to_collections_view collection = CollectionFactory() - url = '/{}guids/{}/'.format(API_BASE, collection._id) - res = self.app.get(url, auth=self.user.auth) + url = url_guids_detail(collection._id) + res = app.get(url, auth=user.auth) redirect_url = '{}{}collections/{}/'.format(API_DOMAIN, API_BASE, collection._id) - assert_equal(res.status_code, 302) - assert_equal(res.location, redirect_url) + assert res.status_code == 302 + assert res.location == redirect_url - def test_redirect_to_file_view(self): + #test_redirect_to_file_view test_file = OsfStorageFile.create( node=ProjectFactory(), path='/test', @@ -56,36 +73,36 @@ def test_redirect_to_file_view(self): ) test_file.save() guid = test_file.get_guid(create=True) - url = '/{}guids/{}/'.format(API_BASE, guid._id) - res = self.app.get(url, auth=self.user.auth) + url = url_guids_detail(guid._id) + res = app.get(url, auth=user.auth) redirect_url = '{}{}files/{}/'.format(API_DOMAIN, API_BASE, test_file._id) - assert_equal(res.status_code, 302) - assert_equal(res.location, redirect_url) + assert res.status_code == 302 + assert res.location == redirect_url - def test_redirect_to_comment_view(self): + #test_redirect_to_comment_view comment = CommentFactory() - url = '/{}guids/{}/'.format(API_BASE, comment._id) - res = self.app.get(url, auth=self.user.auth) + url = url_guids_detail(comment._id) + res = app.get(url, auth=user.auth) redirect_url = '{}{}comments/{}/'.format(API_DOMAIN, API_BASE, comment._id) - assert_equal(res.status_code, 302) - assert_equal(res.location, redirect_url) + assert res.status_code == 302 + assert res.location == redirect_url - def test_redirect_throws_404_for_invalid_guids(self): - url = '/{}guids/{}/'.format(API_BASE, 'fakeguid') - res = self.app.get(url, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 404) + #test_redirect_throws_404_for_invalid_guids + url = url_guids_detail('fakeguid') + res = app.get(url, auth=user.auth, expect_errors=True) + assert res.status_code == 404 - def test_redirect_when_viewing_private_project_through_view_only_link(self): - project = ProjectFactory() - view_only_link = self._add_private_link(project) + def test_redirects_through_view_only_link(self, app, project, _add_private_link, user): + + #test_redirect_when_viewing_private_project_through_view_only_link + view_only_link = _add_private_link() url = '/{}guids/{}/?view_only={}'.format(API_BASE, project._id, view_only_link.key) - res = self.app.get(url, auth=AuthUserFactory().auth) + res = app.get(url, auth=user.auth) redirect_url = '{}{}nodes/{}/?view_only={}'.format(API_DOMAIN, API_BASE, project._id, view_only_link.key) - assert_equal(res.status_code, 302) - assert_equal(res.location, redirect_url) + assert res.status_code == 302 + assert res.location == redirect_url - def test_redirect_when_viewing_private_project_file_through_view_only_link(self): - project = ProjectFactory() + #test_redirect_when_viewing_private_project_file_through_view_only_link test_file = OsfStorageFile.create( node=project, path='/test', @@ -94,41 +111,37 @@ def test_redirect_when_viewing_private_project_file_through_view_only_link(self) ) test_file.save() guid = test_file.get_guid(create=True) - view_only_link = self._add_private_link(project) - url = '/{}guids/{}/?view_only={}'.format(API_BASE, guid._id, view_only_link.key) - res = self.app.get(url, auth=AuthUserFactory().auth) + res = app.get(url, auth=user.auth) redirect_url = '{}{}files/{}/?view_only={}'.format(API_DOMAIN, API_BASE, test_file._id, view_only_link.key) - assert_equal(res.status_code, 302) - assert_equal(res.location, redirect_url) + assert res.status_code == 302 + assert res.location == redirect_url - def test_redirect_when_viewing_private_project_comment_through_view_only_link(self): - project = ProjectFactory() - view_only_link = self._add_private_link(project) + #test_redirect_when_viewing_private_project_comment_through_view_only_link comment = CommentFactory(node=project) url = '/{}guids/{}/?view_only={}'.format(API_BASE, comment._id, view_only_link.key) - res = self.app.get(url, auth=AuthUserFactory().auth) + res = app.get(url, auth=AuthUserFactory().auth) redirect_url = '{}{}comments/{}/?view_only={}'.format(API_DOMAIN, API_BASE, comment._id, view_only_link.key) - assert_equal(res.status_code, 302) - assert_equal(res.location, redirect_url) + assert res.status_code == 302 + assert res.location == redirect_url - def test_resolve_query_param(self): - project = ProjectFactory() + def test_resolves(self, app, project, user): + #test_resolve_query_param url = '{}{}guids/{}/?resolve=false'.format(API_DOMAIN, API_BASE, project._id) - res = self.app.get(url, auth=self.user.auth) + res = app.get(url, auth=user.auth) related_url = '{}{}nodes/{}/'.format(API_DOMAIN, API_BASE, project._id) related = res.json['data']['relationships']['referent']['links']['related'] - assert_equal(related['href'], related_url) - assert_equal(related['meta']['type'], 'nodes') + assert related['href'] == related_url + assert related['meta']['type'] == 'nodes' - def test_referent_is_embeddable(self): - project = ProjectFactory(creator=self.user) + #test_referent_is_embeddable + project = ProjectFactory(creator=user) url = '{}{}guids/{}/?resolve=false&embed=referent'.format(API_DOMAIN, API_BASE, project._id) - res = self.app.get(url, auth=self.user.auth) + res = app.get(url, auth=user.auth) related_url = '{}{}nodes/{}/'.format(API_DOMAIN, API_BASE, project._id) related = res.json['data']['relationships']['referent']['links']['related'] - assert_equal(related['href'], related_url) - assert_equal(related['meta']['type'], 'nodes') + assert related['href'] == related_url + assert related['meta']['type'] == 'nodes' referent = res.json['data']['embeds']['referent']['data'] - assert_equal(referent['id'], project._id) - assert_equal(referent['type'], 'nodes') + assert referent['id'] == project._id + assert referent['type'] == 'nodes' From e8bbae7135b47defca807499ca6e1f518b377265 Mon Sep 17 00:00:00 2001 From: Rheisen Dennis Date: Fri, 7 Jul 2017 14:34:11 -0400 Subject: [PATCH 25/62] pytest conversion of test node comments list --- .../nodes/views/test_node_comments_list.py | 1603 +++++++++-------- 1 file changed, 836 insertions(+), 767 deletions(-) diff --git a/api_tests/nodes/views/test_node_comments_list.py b/api_tests/nodes/views/test_node_comments_list.py index 056ccb63ab7..59c59a3447d 100644 --- a/api_tests/nodes/views/test_node_comments_list.py +++ b/api_tests/nodes/views/test_node_comments_list.py @@ -1,442 +1,474 @@ # -*- coding: utf-8 -*- import pytest import mock -from nose.tools import * # flake8: noqa -from framework.auth import core -from osf.models import Guid - -from api.base.settings.defaults import API_BASE +from addons.wiki.tests.factories import NodeWikiFactory from api.base.settings import osf_settings +from api.base.settings.defaults import API_BASE from api_tests import utils as test_utils -from tests.base import ApiTestCase +from framework.auth import core +from osf.models import Guid from osf_tests.factories import ( ProjectFactory, RegistrationFactory, AuthUserFactory, CommentFactory, ) -from addons.wiki.tests.factories import NodeWikiFactory +from rest_framework import exceptions + +@pytest.fixture() +def user(): + return AuthUserFactory() +@pytest.mark.django_db class NodeCommentsListMixin(object): - def setUp(self): - super(NodeCommentsListMixin, self).setUp() - self.user = AuthUserFactory() - self.non_contributor = AuthUserFactory() + @pytest.fixture() + def user_non_contrib(self): + return AuthUserFactory() - def _set_up_private_project_with_comment(self): + @pytest.fixture() + def project_private(self): raise NotImplementedError - def _set_up_public_project_with_comment(self): + @pytest.fixture() + def project_public(self): raise NotImplementedError - def _set_up_registration_with_comment(self): + @pytest.fixture() + def registration(self): raise NotImplementedError - def test_return_public_node_comments_logged_out_user(self): - self._set_up_public_project_with_comment() - res = self.app.get(self.public_url) - assert_equal(res.status_code, 200) + def test_return_comments(self, app, user, user_non_contrib, project_public, project_private, registration): + + # test_return_public_node_comments_logged_out_user + res = app.get(project_public['url']) + assert res.status_code == 200 comment_json = res.json['data'] comment_ids = [comment['id'] for comment in comment_json] - assert_equal(len(comment_json), 1) - assert_in(self.public_comment._id, comment_ids) + assert len(comment_json) == 1 + assert project_public['comment']._id in comment_ids - def test_return_public_node_comments_logged_in_user(self): - self._set_up_public_project_with_comment() - res = self.app.get(self.public_url, auth=self.non_contributor) - assert_equal(res.status_code, 200) + # test_return_public_node_comments_logged_in_user + res = app.get(project_public['url'], auth=user_non_contrib) + assert res.status_code == 200 comment_json = res.json['data'] comment_ids = [comment['id'] for comment in comment_json] - assert_equal(len(comment_json), 1) - assert_in(self.public_comment._id, comment_ids) - - def test_return_private_node_comments_logged_out_user(self): - self._set_up_private_project_with_comment() - res = self.app.get(self.private_url, expect_errors=True) - assert_equal(res.status_code, 401) - assert_equal(res.json['errors'][0]['detail'], 'Authentication credentials were not provided.') - - def test_return_private_node_comments_logged_in_non_contributor(self): - self._set_up_private_project_with_comment() - res = self.app.get(self.private_url, auth=self.non_contributor, expect_errors=True) - assert_equal(res.status_code, 401) - assert_equal(res.json['errors'][0]['detail'], 'Authentication credentials were not provided.') - - def test_return_private_node_comments_logged_in_contributor(self): - self._set_up_private_project_with_comment() - res = self.app.get(self.private_url, auth=self.user.auth) - assert_equal(res.status_code, 200) + assert len(comment_json) == 1 + assert project_public['comment']._id in comment_ids + + # test_return_private_node_comments_logged_out_user + res = app.get(project_private['url'], expect_errors=True) + assert res.status_code == 401 + assert res.json['errors'][0]['detail'] == exceptions.NotAuthenticated.default_detail + + # test_return_private_node_comments_logged_in_non_contributor + res = app.get(project_private['url'], auth=user_non_contrib, expect_errors=True) + assert res.status_code == 401 + assert res.json['errors'][0]['detail'] == exceptions.NotAuthenticated.default_detail + + # test_return_private_node_comments_logged_in_contributor + res = app.get(project_private['url'], auth=user.auth) + assert res.status_code == 200 comment_json = res.json['data'] comment_ids = [comment['id'] for comment in comment_json] - assert_equal(len(comment_json), 1) - assert_in(self.comment._id, comment_ids) + assert len(comment_json) == 1 + assert project_private['comment']._id in comment_ids - def test_return_registration_comments_logged_in_contributor(self): - self._set_up_registration_with_comment() - res = self.app.get(self.registration_url, auth=self.user.auth) - assert_equal(res.status_code, 200) + # test_return_registration_comments_logged_in_contributor + res = app.get(registration['url'], auth=user.auth) + assert res.status_code == 200 comment_json = res.json['data'] comment_ids = [comment['id'] for comment in comment_json] - assert_equal(len(comment_json), 1) - assert_in(self.registration_comment._id, comment_ids) - - def test_return_both_deleted_and_undeleted_comments(self, mock_update_search=None): - self._set_up_private_project_with_comment() - deleted_comment = CommentFactory(node=self.private_project, user=self.user, target=self.comment.target, is_deleted=True) - res = self.app.get(self.private_url, auth=self.user.auth) - assert_equal(res.status_code, 200) + assert len(comment_json) == 1 + assert registration['comment']._id in comment_ids + + def test_return_both_deleted_and_undeleted_comments(self, app, user, project_private, mock_update_search=None): + deleted_comment = CommentFactory(node=project_private['project'], user=user, target=project_private['comment'].target, is_deleted=True) + res = app.get(project_private['url'], auth=user.auth) + assert res.status_code == 200 comment_json = res.json['data'] comment_ids = [comment['id'] for comment in comment_json] - assert_in(self.comment._id, comment_ids) - assert_in(deleted_comment._id, comment_ids) - - def test_node_comments_list_pagination(self): - self._set_up_public_project_with_comment() - url = '{}?filter[target]={}&related_counts=False'.format(self.public_url, self.public_project._id) - res = self.app.get(url, user=self.user, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal(res.json['links']['meta']['unread'], 0) - - def test_node_comments_list_updated_pagination(self): - self._set_up_public_project_with_comment() - url = '{}?filter[target]={}&related_counts=False&version=2.1'.format(self.public_url, self.public_project._id) - res = self.app.get(url, user=self.user, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal(res.json['meta']['unread'], 0) - - -class TestNodeCommentsList(NodeCommentsListMixin, ApiTestCase): - - def _set_up_private_project_with_comment(self): - self.private_project = ProjectFactory(is_public=False, creator=self.user) - self.comment = CommentFactory(node=self.private_project, user=self.user) - self.private_url = '/{}nodes/{}/comments/'.format(API_BASE, self.private_project._id) - - def _set_up_public_project_with_comment(self): - self.public_project = ProjectFactory(is_public=True, creator=self.user) - self.public_comment = CommentFactory(node=self.public_project, user=self.user) - self.public_url = '/{}nodes/{}/comments/'.format(API_BASE, self.public_project._id) - - def _set_up_registration_with_comment(self): - self.registration = RegistrationFactory(creator=self.user) - self.registration_comment = CommentFactory(node=self.registration, user=self.user) - self.registration_url = '/{}registrations/{}/comments/'.format(API_BASE, self.registration._id) - - -class TestNodeCommentsListFiles(NodeCommentsListMixin, ApiTestCase): - - def _set_up_private_project_with_comment(self): - self.private_project = ProjectFactory(is_public=False, creator=self.user) - self.file = test_utils.create_test_file(self.private_project, self.user) - self.comment = CommentFactory(node=self.private_project, user=self.user, target=self.file.get_guid(), page='files') - self.private_url = '/{}nodes/{}/comments/'.format(API_BASE, self.private_project._id) - - def _set_up_public_project_with_comment(self): - self.public_project = ProjectFactory(is_public=True, creator=self.user) - self.public_file = test_utils.create_test_file(self.public_project, self.user) - self.public_comment = CommentFactory(node=self.public_project, user=self.user, target=self.public_file.get_guid(), page='files') - self.public_url = '/{}nodes/{}/comments/'.format(API_BASE, self.public_project._id) - - def _set_up_registration_with_comment(self): - self.registration = RegistrationFactory(creator=self.user) - self.registration_file = test_utils.create_test_file(self.registration, self.user) - self.registration_comment = CommentFactory(node=self.registration, user=self.user, target=self.registration_file.get_guid(), page='files') - self.registration_url = '/{}registrations/{}/comments/'.format(API_BASE, self.registration._id) - - def test_comments_on_deleted_files_are_not_returned(self): - self._set_up_private_project_with_comment() + assert project_private['comment']._id in comment_ids + assert deleted_comment._id in comment_ids + + def test_node_comments_pagination(self, app, user, project_public): + + # test_node_comments_list_pagination + url = '{}?filter[target]={}&related_counts=False'.format(project_public['url'], project_public['project']._id) + res = app.get(url, user=user, auth=user.auth) + assert res.status_code == 200 + assert res.json['links']['meta']['unread'] == 0 + + # test_node_comments_list_updated_pagination + url = '{}?filter[target]={}&related_counts=False&version=2.1'.format(project_public['url'], project_public['project']._id) + res = app.get(url, user=user, auth=user.auth) + assert res.status_code == 200 + assert res.json['meta']['unread'] == 0 + + +@pytest.mark.django_db +class TestNodeCommentsList(NodeCommentsListMixin): + + @pytest.fixture() + def project_private(self, user): + project_private = ProjectFactory(is_public=False, creator=user) + comment_private = CommentFactory(node=project_private, user=user) + url_private = '/{}nodes/{}/comments/'.format(API_BASE, project_private._id) + return {'project': project_private, 'comment': comment_private, 'url': url_private} + + @pytest.fixture() + def project_public(self, user): + project_public = ProjectFactory(is_public=True, creator=user) + comment_public = CommentFactory(node=project_public, user=user) + url_public = '/{}nodes/{}/comments/'.format(API_BASE, project_public._id) + return {'project': project_public, 'comment': comment_public, 'url': url_public} + + @pytest.fixture() + def registration(self, user): + registration = RegistrationFactory(creator=user) + comment_registration = CommentFactory(node=registration, user=user) + url_registration = '/{}registrations/{}/comments/'.format(API_BASE, registration._id) + return {'registration': registration, 'comment': comment_registration, 'url': url_registration} + + +@pytest.mark.django_db +class TestNodeCommentsListFiles(NodeCommentsListMixin): + + @pytest.fixture() + def project_private(self, user): + project_private = ProjectFactory(is_public=False, creator=user) + file = test_utils.create_test_file(project_private, user) + comment_private = CommentFactory(node=project_private, user=user, target=file.get_guid(), page='files') + url_private = '/{}nodes/{}/comments/'.format(API_BASE, project_private._id) + return {'project': project_private, 'file': file, 'comment': comment_private, 'url': url_private} + + @pytest.fixture() + def project_public(self, user): + project_public = ProjectFactory(is_public=True, creator=user) + file_public = test_utils.create_test_file(project_public, user) + comment_public = CommentFactory(node=project_public, user=user, target=file_public.get_guid(), page='files') + url_public = '/{}nodes/{}/comments/'.format(API_BASE, project_public._id) + return {'project': project_public, 'file': file_public, 'comment': comment_public, 'url': url_public} + + @pytest.fixture() + def registration(self, user): + registration = RegistrationFactory(creator=user) + file_registration = test_utils.create_test_file(registration, user) + comment_registration = CommentFactory(node=registration, user=user, target=file_registration.get_guid(), page='files') + url_registration = '/{}registrations/{}/comments/'.format(API_BASE, registration._id) + return {'registration': registration, 'file': file_registration, 'comment': comment_registration, 'url': url_registration} + + def test_comments_on_deleted_files_are_not_returned(self, app, user, project_private): # Delete commented file - osfstorage = self.private_project.get_addon('osfstorage') + osfstorage = project_private['project'].get_addon('osfstorage') root_node = osfstorage.get_root() - # root_node.delete(self.file) - self.file.delete(user=self.user) - res = self.app.get(self.private_url, auth=self.user.auth) - assert_equal(res.status_code, 200) + # root_node.delete(project_private['file']) + project_private['file'].delete(user=user) + res = app.get(project_private['url'], auth=user.auth) + assert res.status_code == 200 comment_json = res.json['data'] comment_ids = [comment['id'] for comment in comment_json] - assert_not_in(self.comment._id, comment_ids) - - -class TestNodeCommentsListWiki(NodeCommentsListMixin, ApiTestCase): - - def _set_up_private_project_with_comment(self): - self.private_project = ProjectFactory(is_public=False, creator=self.user) - self.wiki = NodeWikiFactory(node=self.private_project, user=self.user) - self.comment = CommentFactory(node=self.private_project, user=self.user, target=Guid.load(self.wiki._id), page='wiki') - self.private_url = '/{}nodes/{}/comments/'.format(API_BASE, self.private_project._id) - - def _set_up_public_project_with_comment(self): - self.public_project = ProjectFactory(is_public=True, creator=self.user) - self.public_wiki = NodeWikiFactory(node=self.public_project, user=self.user) - self.public_comment = CommentFactory(node=self.public_project, user=self.user, target=Guid.load(self.public_wiki._id), page='wiki') - self.public_url = '/{}nodes/{}/comments/'.format(API_BASE, self.public_project._id) - - def _set_up_registration_with_comment(self): - self.registration = RegistrationFactory(creator=self.user) - self.registration_wiki = NodeWikiFactory(node=self.registration, user=self.user) - self.registration_comment = CommentFactory(node=self.registration, user=self.user, target=Guid.load(self.registration_wiki._id), page='wiki') - self.registration_url = '/{}registrations/{}/comments/'.format(API_BASE, self.registration._id) - - def test_comments_on_deleted_wikis_are_not_returned(self, mock_update_search=None): - self._set_up_private_project_with_comment() + assert project_private['comment']._id not in comment_ids + + +@pytest.mark.django_db +class TestNodeCommentsListWiki(NodeCommentsListMixin): + + @pytest.fixture() + def project_private(self, user): + project_private = ProjectFactory(is_public=False, creator=user) + wiki_private = NodeWikiFactory(node=project_private, user=user) + comment_private = CommentFactory(node=project_private, user=user, target=Guid.load(wiki_private._id), page='wiki') + url_private = '/{}nodes/{}/comments/'.format(API_BASE, project_private._id) + return {'project': project_private, 'wiki': wiki_private, 'comment': comment_private, 'url': url_private} + + @pytest.fixture() + def project_public(self, user): + project_public = ProjectFactory(is_public=True, creator=user) + wiki_public = NodeWikiFactory(node=project_public, user=user) + comment_public = CommentFactory(node=project_public, user=user, target=Guid.load(wiki_public._id), page='wiki') + url_public = '/{}nodes/{}/comments/'.format(API_BASE, project_public._id) + return {'project': project_public, 'wiki': wiki_public, 'comment': comment_public, 'url': url_public} + + @pytest.fixture() + def registration(self, user): + registration = RegistrationFactory(creator=user) + wiki_registration = NodeWikiFactory(node=registration, user=user) + comment_registration = CommentFactory(node=registration, user=user, target=Guid.load(wiki_registration._id), page='wiki') + url_registration = '/{}registrations/{}/comments/'.format(API_BASE, registration._id) + return {'registration': registration, 'wiki': wiki_registration, 'comment': comment_registration, 'url': url_registration} + + def test_comments_on_deleted_wikis_are_not_returned(self, app, user, project_private, mock_update_search=None): # Delete wiki - self.private_project.delete_node_wiki(self.wiki.page_name, core.Auth(self.user)) - res = self.app.get(self.private_url, auth=self.user.auth) - assert_equal(res.status_code, 200) + project_private['project'].delete_node_wiki(project_private['wiki'].page_name, core.Auth(user)) + res = app.get(project_private['url'], auth=user.auth) + assert res.status_code == 200 comment_json = res.json['data'] comment_ids = [comment['id'] for comment in comment_json] - assert_not_in(self.comment._id, comment_ids) - + assert project_private['comment']._id not in comment_ids +@pytest.mark.django_db class NodeCommentsCreateMixin(object): - def setUp(self): - super(NodeCommentsCreateMixin, self).setUp() - self.user = AuthUserFactory() - self.read_only_contributor = AuthUserFactory() - self.non_contributor = AuthUserFactory() + @pytest.fixture() + def user_read_contrib(self): + return AuthUserFactory() - def _set_up_payload(self, target_id): + @pytest.fixture() + def user_non_contrib(self): + return AuthUserFactory() + + @pytest.fixture() + def payload(self): raise NotImplementedError - def _set_up_private_project_with_private_comment_level(self): + @pytest.fixture() + def project_private_comment_private(self): raise NotImplementedError - def _set_up_public_project_with_private_comment_level(self): + @pytest.fixture() + def project_public_comment_private(self): raise NotImplementedError - def _set_up_public_project_with_public_comment_level(self): + @pytest.fixture() + def project_public_comment_public(self): raise NotImplementedError - def _set_up_private_project_with_public_comment_level(self): + @pytest.fixture() + def project_private_comment_public(self): raise NotImplementedError - def test_private_node_private_comment_level_logged_in_admin_can_comment(self): - self._set_up_private_project_with_private_comment_level() - res = self.app.post_json_api(self.private_url, self.private_payload, auth=self.user.auth) - assert_equal(res.status_code, 201) - assert_equal(res.json['data']['attributes']['content'], self.private_payload['data']['attributes']['content']) - - def test_private_node_private_comment_level_logged_in_read_contributor_can_comment(self): - self._set_up_private_project_with_private_comment_level() - res = self.app.post_json_api(self.private_url, self.private_payload, auth=self.read_only_contributor.auth) - assert_equal(res.status_code, 201) - assert_equal(res.json['data']['attributes']['content'], self.private_payload['data']['attributes']['content']) - - def test_private_node_private_comment_level_non_contributor_cannot_comment(self): - self._set_up_private_project_with_private_comment_level() - res = self.app.post_json_api(self.private_url, self.private_payload, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - assert_equal(res.json['errors'][0]['detail'], 'You do not have permission to perform this action.') - - def test_private_node_private_comment_level_logged_out_user_cannot_comment(self): - self._set_up_private_project_with_private_comment_level() - res = self.app.post_json_api(self.private_url, self.private_payload, expect_errors=True) - assert_equal(res.status_code, 401) - assert_equal(res.json['errors'][0]['detail'], 'Authentication credentials were not provided.') - - def test_private_node_with_public_comment_level_admin_can_comment(self): + def test_node_comments(self, app, user, user_read_contrib, user_non_contrib, project_private_comment_private, project_private_comment_public, project_public_comment_public, project_public_comment_private): + + # test_private_node_private_comment_level_logged_in_admin_can_comment + project_dict = project_private_comment_private + res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user.auth) + assert res.status_code == 201 + assert res.json['data']['attributes']['content'] == project_dict['payload']['data']['attributes']['content'] + + # test_private_node_private_comment_level_logged_in_read_contributor_can_comment + project_dict = project_private_comment_private + res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user_read_contrib.auth) + assert res.status_code == 201 + assert res.json['data']['attributes']['content'] == project_dict['payload']['data']['attributes']['content'] + + # test_private_node_private_comment_level_non_contributor_cannot_comment + project_dict = project_private_comment_private + res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user_non_contrib.auth, expect_errors=True) + assert res.status_code == 403 + assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail + + # test_private_node_private_comment_level_logged_out_user_cannot_comment + project_dict = project_private_comment_private + res = app.post_json_api(project_dict['url'], project_dict['payload'], expect_errors=True) + assert res.status_code == 401 + assert res.json['errors'][0]['detail'] == exceptions.NotAuthenticated.default_detail + + # test_private_node_with_public_comment_level_admin_can_comment """ Test admin contributors can still comment on a private project with comment_level == 'public' """ - self._set_up_private_project_with_public_comment_level() - res = self.app.post_json_api(self.private_project_public_comments_url, - self.private_project_public_comments_payload, - auth=self.user.auth) - assert_equal(res.status_code, 201) - assert_equal(res.json['data']['attributes']['content'], - self.private_project_public_comments_payload['data']['attributes']['content']) - - def test_private_node_with_public_comment_level_read_only_contributor_can_comment(self): + project_dict = project_private_comment_public + res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user.auth) + assert res.status_code == 201 + assert res.json['data']['attributes']['content'] == project_dict['payload']['data']['attributes']['content'] + + # test_private_node_with_public_comment_level_read_only_contributor_can_comment """ Test read-only contributors can still comment on a private project with comment_level == 'public' """ - self._set_up_private_project_with_public_comment_level() - res = self.app.post_json_api(self.private_project_public_comments_url, - self.private_project_public_comments_payload, - auth=self.read_only_contributor.auth) - assert_equal(res.status_code, 201) - assert_equal(res.json['data']['attributes']['content'], - self.private_project_public_comments_payload['data']['attributes']['content']) - - def test_private_node_with_public_comment_level_non_contributor_cannot_comment(self): + project_dict = project_private_comment_public + res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user_read_contrib.auth) + assert res.status_code == 201 + assert res.json['data']['attributes']['content'] == project_dict['payload']['data']['attributes']['content'] + + # test_private_node_with_public_comment_level_non_contributor_cannot_comment """ Test non-contributors cannot comment on a private project with comment_level == 'public' """ - self._set_up_private_project_with_public_comment_level() - res = self.app.post_json_api(self.private_project_public_comments_url, - self.private_project_public_comments_payload, - auth=self.non_contributor.auth, - expect_errors=True) - assert_equal(res.status_code, 403) - - def test_private_node_with_public_comment_level_logged_out_user_cannot_comment(self): + project_dict = project_private_comment_public + res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user_non_contrib.auth, expect_errors=True) + assert res.status_code == 403 + + # test_private_node_with_public_comment_level_logged_out_user_cannot_comment """ Test logged out users cannot comment on a private project with comment_level == 'public' """ - self._set_up_private_project_with_public_comment_level() - res = self.app.post_json_api(self.private_project_public_comments_url, - self.private_project_public_comments_payload, expect_errors=True) - assert_equal(res.status_code, 401) - assert_equal(res.json['errors'][0]['detail'], 'Authentication credentials were not provided.') + project_dict = project_private_comment_public + res = app.post_json_api(project_dict['url'], project_dict['payload'], expect_errors=True) + assert res.status_code == 401 + assert res.json['errors'][0]['detail'] == exceptions.NotAuthenticated.default_detail - def test_public_project_with_public_comment_level_admin_can_comment(self): + # test_public_project_with_public_comment_level_admin_can_comment """ Test admin contributor can still comment on a public project when it is configured so any logged-in user can comment (comment_level == 'public') """ - self._set_up_public_project_with_public_comment_level() - res = self.app.post_json_api(self.public_comments_url, self.public_comment_level_payload, auth=self.user.auth) - assert_equal(res.status_code, 201) - assert_equal(res.json['data']['attributes']['content'], self.public_comment_level_payload['data']['attributes']['content']) + project_dict = project_public_comment_public + res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user.auth) + assert res.status_code == 201 + assert res.json['data']['attributes']['content'] == project_dict['payload']['data']['attributes']['content'] - def test_public_project_with_public_comment_level_read_only_contributor_can_comment(self): + # test_public_project_with_public_comment_level_read_only_contributor_can_comment """ Test read-only contributor can still comment on a public project when it is configured so any logged-in user can comment (comment_level == 'public') """ - self._set_up_public_project_with_public_comment_level() - res = self.app.post_json_api(self.public_comments_url, self.public_comment_level_payload, auth=self.read_only_contributor.auth) - assert_equal(res.status_code, 201) - assert_equal(res.json['data']['attributes']['content'], self.public_comment_level_payload['data']['attributes']['content']) + project_dict = project_public_comment_public + res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user_read_contrib.auth) + assert res.status_code == 201 + assert res.json['data']['attributes']['content'] == project_dict['payload']['data']['attributes']['content'] - def test_public_project_with_public_comment_level_non_contributor_can_comment(self): + # test_public_project_with_public_comment_level_non_contributor_can_comment """ Test non-contributors can comment on a public project when it is configured so any logged-in user can comment (comment_level == 'public') """ - self._set_up_public_project_with_public_comment_level() - res = self.app.post_json_api(self.public_comments_url, self.public_comment_level_payload, auth=self.non_contributor.auth) - assert_equal(res.status_code, 201) - assert_equal(res.json['data']['attributes']['content'], self.public_comment_level_payload['data']['attributes']['content']) + project_dict = project_public_comment_public + res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user_non_contrib.auth) + assert res.status_code == 201 + assert res.json['data']['attributes']['content'] == project_dict['payload']['data']['attributes']['content'] - def test_public_project_with_public_comment_level_logged_out_user_cannot_comment(self): + # test_public_project_with_public_comment_level_logged_out_user_cannot_comment """ Test logged out users cannot comment on a public project when it is configured so any logged-in user can comment (comment_level == 'public') """ - self._set_up_public_project_with_public_comment_level() - res = self.app.post_json_api(self.public_comments_url, self.public_comment_level_payload, expect_errors=True) - assert_equal(res.status_code, 401) - assert_equal(res.json['errors'][0]['detail'], 'Authentication credentials were not provided.') + project_dict = project_public_comment_public + res = app.post_json_api(project_dict['url'], project_dict['payload'], expect_errors=True) + assert res.status_code == 401 + assert res.json['errors'][0]['detail'] == exceptions.NotAuthenticated.default_detail - def test_public_node_private_comment_level_admin_can_comment(self): + # test_public_node_private_comment_level_admin_can_comment """ Test only contributors can comment on a public project when it is configured so only contributors can comment (comment_level == 'private') """ - self._set_up_public_project_with_private_comment_level() - res = self.app.post_json_api(self.public_url, self.public_payload, auth=self.user.auth) - assert_equal(res.status_code, 201) - assert_equal(res.json['data']['attributes']['content'], self.public_payload['data']['attributes']['content']) - - def test_public_node_private_comment_level_read_only_contributor_can_comment(self): - self._set_up_public_project_with_private_comment_level() - res = self.app.post_json_api(self.public_url, self.public_payload, auth=self.read_only_contributor.auth) - assert_equal(res.status_code, 201) - assert_equal(res.json['data']['attributes']['content'], self.public_payload['data']['attributes']['content']) - - def test_public_node_private_comment_level_non_contributor_cannot_comment(self): - self._set_up_public_project_with_private_comment_level() - res = self.app.post_json_api(self.public_url, self.public_payload, auth=self.non_contributor.auth, expect_errors=True) - assert_equal(res.status_code, 403) - assert_equal(res.json['errors'][0]['detail'], 'You do not have permission to perform this action.') - - def test_public_node_private_comment_level_logged_out_user_cannot_comment(self): - self._set_up_public_project_with_private_comment_level() - res = self.app.post_json_api(self.public_url, self.public_payload, expect_errors=True) - assert_equal(res.status_code, 401) - assert_equal(res.json['errors'][0]['detail'], 'Authentication credentials were not provided.') - - -class TestNodeCommentCreate(NodeCommentsCreateMixin, ApiTestCase): - - def _set_up_payload(self, target_id): - return { - 'data': { - 'type': 'comments', - 'attributes': { - 'content': 'This is a comment' - }, - 'relationships': { - 'target': { - 'data': { - 'type': 'nodes', - 'id': target_id + project_dict = project_public_comment_private + res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user.auth) + assert res.status_code == 201 + assert res.json['data']['attributes']['content'] == project_dict['payload']['data']['attributes']['content'] + + # test_public_node_private_comment_level_read_only_contributor_can_comment + project_dict = project_public_comment_private + res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user_read_contrib.auth) + assert res.status_code == 201 + assert res.json['data']['attributes']['content'] == project_dict['payload']['data']['attributes']['content'] + + # test_public_node_private_comment_level_non_contributor_cannot_comment + project_dict = project_public_comment_private + res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user_non_contrib.auth, expect_errors=True) + assert res.status_code == 403 + assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail + + # test_public_node_private_comment_level_logged_out_user_cannot_comment + project_dict = project_public_comment_private + res = app.post_json_api(project_dict['url'], project_dict['payload'], expect_errors=True) + assert res.status_code == 401 + assert res.json['errors'][0]['detail'] == exceptions.NotAuthenticated.default_detail + + +@pytest.mark.django_db +class TestNodeCommentCreate(NodeCommentsCreateMixin): + + @pytest.fixture() + def payload(self): + def make_payload(target_id): + return { + 'data': { + 'type': 'comments', + 'attributes': { + 'content': 'This is a comment' + }, + 'relationships': { + 'target': { + 'data': { + 'type': 'nodes', + 'id': target_id + } } } } } - } - - def _set_up_private_project_with_private_comment_level(self): - self.private_project = ProjectFactory(is_public=False, creator=self.user, comment_level='private') - self.private_project.add_contributor(self.read_only_contributor, permissions=['read']) - self.private_project.save() - self.private_url = '/{}nodes/{}/comments/'.format(API_BASE, self.private_project._id) - self.private_payload = self._set_up_payload(self.private_project._id) - - def _set_up_public_project_with_private_comment_level(self): - self.public_project = ProjectFactory(is_public=True, creator=self.user, comment_level='private') - self.public_project.add_contributor(self.read_only_contributor, permissions=['read']) - self.public_project.save() - self.public_url = '/{}nodes/{}/comments/'.format(API_BASE, self.public_project._id) - self.public_payload = self._set_up_payload(self.public_project._id) - - def _set_up_public_project_with_public_comment_level(self): + return make_payload + + @pytest.fixture() + def project_private_comment_private(self, user, user_read_contrib, payload): + project_private = ProjectFactory(is_public=False, creator=user, comment_level='private') + project_private.add_contributor(user_read_contrib, permissions=['read']) + project_private.save() + url_private = '/{}nodes/{}/comments/'.format(API_BASE, project_private._id) + payload_private = payload(project_private._id) + return {'project': project_private, 'url': url_private, 'payload': payload_private} + + @pytest.fixture() + def project_public_comment_private(self, user, user_read_contrib, payload): + project_public = ProjectFactory(is_public=True, creator=user, comment_level='private') + project_public.add_contributor(user_read_contrib, permissions=['read']) + project_public.save() + url_public = '/{}nodes/{}/comments/'.format(API_BASE, project_public._id) + payload_public = payload(project_public._id) + return {'project': project_public, 'url': url_public, 'payload': payload_public} + + @pytest.fixture() + def project_public_comment_public(self, user, user_read_contrib, payload): """ Public project configured so that any logged-in user can comment.""" - self.project_with_public_comment_level = ProjectFactory(is_public=True, creator=self.user) - self.project_with_public_comment_level.add_contributor(self.read_only_contributor, permissions=['read']) - self.project_with_public_comment_level.save() - self.public_comments_url = '/{}nodes/{}/comments/'.format(API_BASE, self.project_with_public_comment_level._id) - self.public_comment_level_payload = self._set_up_payload(self.project_with_public_comment_level._id) - - def _set_up_private_project_with_public_comment_level(self): - self.private_project_with_public_comment_level = ProjectFactory(is_public=False, creator=self.user) - self.private_project_with_public_comment_level.add_contributor(self.read_only_contributor, permissions=['read']) - self.private_project_with_public_comment_level.save() - self.private_project_public_comments_url = '/{}nodes/{}/comments/'.format(API_BASE, self.private_project_with_public_comment_level._id) - self.private_project_public_comments_payload = self._set_up_payload(self.private_project_with_public_comment_level._id) - - def test_create_comment_invalid_data(self): - self._set_up_private_project_with_private_comment_level() - res = self.app.post_json_api(self.private_url, "Incorrect data", auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - - def test_create_comment_no_relationships(self): - self._set_up_private_project_with_private_comment_level() - payload = { + project_public = ProjectFactory(is_public=True, creator=user) + project_public.add_contributor(user_read_contrib, permissions=['read']) + project_public.save() + url_public = '/{}nodes/{}/comments/'.format(API_BASE, project_public._id) + payload_public = payload(project_public._id) + return {'project': project_public, 'url': url_public, 'payload': payload_public} + + @pytest.fixture() + def project_private_comment_public(self, user, user_read_contrib, payload): + project_private = ProjectFactory(is_public=False, creator=user) + project_private.add_contributor(user_read_contrib, permissions=['read']) + project_private.save() + url_private = '/{}nodes/{}/comments/'.format(API_BASE, project_private._id) + payload_private = payload(project_private._id) + return {'project': project_private, 'url': url_private, 'payload': payload_private} + + def test_create_comment_errors(self, app, user, payload, project_private_comment_private): + + # test_create_comment_invalid_data + project_dict = project_private_comment_private + res = app.post_json_api(project_dict['url'], 'Incorrect data', auth=user.auth, expect_errors=True) + assert res.status_code == 400 + + # test_create_comment_no_relationships + project_dict = project_private_comment_private + payload_req = { 'data': { 'type': 'comments', 'attributes': { - 'content': 'This is a comment' + 'content': '4:44' } } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], 'Request must include /data/relationships.') - assert_equal(res.json['errors'][0]['source']['pointer'], '/data/relationships') - - def test_create_comment_empty_relationships(self): - self._set_up_private_project_with_private_comment_level() - payload = { + res = app.post_json_api(project_dict['url'], payload_req, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'Request must include /data/relationships.' + assert res.json['errors'][0]['source']['pointer'] == '/data/relationships' + + # test_create_comment_empty_relationships + project_dict = project_private_comment_private + payload_req = { 'data': { 'type': 'comments', 'attributes': { - 'content': 'This is a comment' + 'content': 'Center for Closed Logic' }, 'relationships': {} } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], 'Request must include /data/relationships.') - assert_equal(res.json['errors'][0]['source']['pointer'], '/data/relationships') - - def test_create_comment_relationship_is_a_list(self): - self._set_up_private_project_with_private_comment_level() - payload = { + res = app.post_json_api(project_dict['url'], payload_req, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'Request must include /data/relationships.' + assert res.json['errors'][0]['source']['pointer'] == '/data/relationships' + + # test_create_comment_relationship_is_a_list + project_dict = project_private_comment_private + payload_req = { 'data': { 'type': 'comments', 'attributes': { 'content': 'This is a comment' }, - 'relationships': [{'id': self.private_project._id}] + 'relationships': [{'id': project_dict['project']._id}] } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], "Malformed request.") + res = app.post_json_api(project_dict['url'], payload_req, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == exceptions.ParseError.default_detail - def test_create_comment_target_no_data_in_relationships(self): - self._set_up_private_project_with_private_comment_level() - payload = { + # test_create_comment_target_no_data_in_relationships + project_dict = project_private_comment_private + payload_req = { 'data': { 'type': 'comments', 'attributes': { @@ -447,14 +479,14 @@ def test_create_comment_target_no_data_in_relationships(self): } } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], 'Request must include /data.') - assert_equal(res.json['errors'][0]['source']['pointer'], 'data/relationships/target/data') - - def test_create_comment_no_target_key_in_relationships(self): - self._set_up_private_project_with_private_comment_level() - payload = { + res = app.post_json_api(project_dict['url'], payload_req, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'Request must include /data.' + assert res.json['errors'][0]['source']['pointer'] == 'data/relationships/target/data' + + # test_create_comment_no_target_key_in_relationships + project_dict = project_private_comment_private + payload_req = { 'data': { 'type': 'comments', 'attributes': { @@ -463,18 +495,18 @@ def test_create_comment_no_target_key_in_relationships(self): 'relationships': { 'data': { 'type': 'nodes', - 'id': self.private_project._id + 'id': project_dict['project']._id } } } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], 'Malformed request.') + res = app.post_json_api(project_dict['url'], payload_req, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == exceptions.ParseError.default_detail - def test_create_comment_blank_target_id(self): - self._set_up_private_project_with_private_comment_level() - payload = { + # test_create_comment_blank_target_id + project_dict = project_private_comment_private + payload_req = { 'data': { 'type': 'comments', 'attributes': { @@ -490,21 +522,21 @@ def test_create_comment_blank_target_id(self): } } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], "Invalid comment target ''.") + res = app.post_json_api(project_dict['url'], payload_req, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'Invalid comment target \'\'.' - def test_create_comment_invalid_target_id(self): - self._set_up_private_project_with_private_comment_level() + # test_create_comment_invalid_target_id + project_dict = project_private_comment_private project_id = ProjectFactory()._id - payload = self._set_up_payload(project_id) - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], "Invalid comment target \'" + str(project_id) + "\'.") - - def test_create_comment_invalid_target_type(self): - self._set_up_private_project_with_private_comment_level() - payload = { + payload_project = payload(project_id) + res = app.post_json_api(project_dict['url'], payload_project, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'Invalid comment target \'' + str(project_id) + '\'.' + + # test_create_comment_invalid_target_type + project_dict = project_private_comment_private + payload_req = { 'data': { 'type': 'comments', 'attributes': { @@ -514,19 +546,19 @@ def test_create_comment_invalid_target_type(self): 'target': { 'data': { 'type': 'Invalid', - 'id': self.private_project._id + 'id': project_dict['project']._id } } } } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 409) - assert_equal(res.json['errors'][0]['detail'], 'The target resource has a type of "nodes", but you set the json body\'s type field to "Invalid". You probably need to change the type field to match the target resource\'s type.') + res = app.post_json_api(project_dict['url'], payload_req, auth=user.auth, expect_errors=True) + assert res.status_code == 409 + assert res.json['errors'][0]['detail'] == 'The target resource has a type of "nodes", but you set the json body\'s type field to "Invalid". You probably need to change the type field to match the target resource\'s type.' - def test_create_comment_no_target_type_in_relationships(self): - self._set_up_private_project_with_private_comment_level() - payload = { + # test_create_comment_no_target_type_in_relationships + project_dict = project_private_comment_private + payload_req = { 'data': { 'type': 'comments', 'attributes': { @@ -535,19 +567,19 @@ def test_create_comment_no_target_type_in_relationships(self): 'relationships': { 'target': { 'data': { - 'id': self.private_project._id + 'id': project_dict['project']._id } } } } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], 'Request must include /type.') + res = app.post_json_api(project_dict['url'], payload_req, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'Request must include /type.' - def test_create_comment_no_type(self): - self._set_up_private_project_with_private_comment_level() - payload = { + # test_create_comment_no_type + project_dict = project_private_comment_private + payload_req = { 'data': { 'type': '', 'attributes': { @@ -557,42 +589,20 @@ def test_create_comment_no_type(self): 'target': { 'data': { 'type': 'nodes', - 'id': self.private_project._id - } - } - } - } - } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], 'This field may not be blank.') - assert_equal(res.json['errors'][0]['source']['pointer'], '/data/type') - - def test_create_comment_incorrect_type(self): - self._set_up_private_project_with_private_comment_level() - payload = { - 'data': { - 'type': 'cookies', - 'attributes': { - 'content': 'This is a comment' - }, - 'relationships': { - 'target': { - 'data': { - 'type': 'nodes', - 'id': self.private_project._id + 'id': project_dict['project']._id } } } } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 409) - assert_equal(res.json['errors'][0]['detail'], 'This resource has a type of "comments", but you set the json body\'s type field to "cookies". You probably need to change the type field to match the resource\'s type.') - - def test_create_comment_no_content(self): - self._set_up_private_project_with_private_comment_level() - payload = { + res = app.post_json_api(project_dict['url'], payload_req, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'This field may not be blank.' + assert res.json['errors'][0]['source']['pointer'] == '/data/type' + + # test_create_comment_no_content + project_dict = project_private_comment_private + payload_req = { 'data': { 'type': 'comments', 'attributes': { @@ -602,20 +612,20 @@ def test_create_comment_no_content(self): 'target': { 'data': { 'type': 'nodes', - 'id': self.private_project._id + 'id': project_dict['project']._id } } } } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], 'This field may not be blank.') - assert_equal(res.json['errors'][0]['source']['pointer'], '/data/attributes/content') - - def test_create_comment_trims_whitespace(self): - self._set_up_private_project_with_private_comment_level() - payload = { + res = app.post_json_api(project_dict['url'], payload_req, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'This field may not be blank.' + assert res.json['errors'][0]['source']['pointer'] == '/data/attributes/content' + + # test_create_comment_trims_whitespace + project_dict = project_private_comment_private + payload_req = { 'data': { 'type': 'comments', 'attributes': { @@ -625,133 +635,146 @@ def test_create_comment_trims_whitespace(self): 'target': { 'data': { 'type': 'nodes', - 'id': self.private_project._id + 'id': project_dict['project']._id } } } } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], 'This field may not be blank.') + res = app.post_json_api(project_dict['url'], payload_req, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'This field may not be blank.' - def test_create_comment_with_allowed_tags(self): - self._set_up_private_project_with_private_comment_level() - payload = { + # test_create_comment_exceeds_max_length + project_dict = project_private_comment_private + payload_req = { 'data': { 'type': 'comments', 'attributes': { - 'content': 'Cool Comment' + 'content': ('c' * (osf_settings.COMMENT_MAXLENGTH + 3)) }, 'relationships': { 'target': { 'data': { 'type': 'nodes', - 'id': self.private_project._id + 'id': project_dict['project']._id } } } } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth) - assert_equal(res.status_code, 201) - assert_equal(res.json['data']['attributes']['content'], payload['data']['attributes']['content']) - - def test_create_comment_exceeds_max_length(self): - self._set_up_private_project_with_private_comment_level() + res = app.post_json_api(project_dict['url'], payload_req, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'Ensure this field has no more than {} characters.'.format(str(osf_settings.COMMENT_MAXLENGTH)) + + # test_create_comment_invalid_target_node + url_fake = '/{}nodes/{}/comments/'.format(API_BASE, 'abcde') + payload_fake = payload('abcde') + res = app.post_json_api(url_fake, payload_fake, auth=user.auth, expect_errors=True) + assert res.status_code == 404 + assert res.json['errors'][0]['detail'] == exceptions.NotFound.default_detail + + def test_create_comment_with_allowed_tags(self, app, user, project_private_comment_private): + project_dict = project_private_comment_private payload = { 'data': { 'type': 'comments', 'attributes': { - 'content': ('c' * (osf_settings.COMMENT_MAXLENGTH + 3)) + 'content': 'Logic Reason' }, 'relationships': { 'target': { 'data': { 'type': 'nodes', - 'id': self.private_project._id + 'id': project_dict['project']._id } } } } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], - 'Ensure this field has no more than {} characters.'.format(str(osf_settings.COMMENT_MAXLENGTH))) - - def test_create_comment_invalid_target_node(self): - url = '/{}nodes/{}/comments/'.format(API_BASE, 'abcde') - payload = self._set_up_payload('abcde') - res = self.app.post_json_api(url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 404) - assert_equal(res.json['errors'][0]['detail'], 'Not found.') - - -class TestFileCommentCreate(NodeCommentsCreateMixin, ApiTestCase): - - def _set_up_payload(self, target_id): - return { - 'data': { - 'type': 'comments', - 'attributes': { - 'content': 'This is a comment' - }, - 'relationships': { - 'target': { - 'data': { - 'type': 'files', - 'id': target_id + res = app.post_json_api(project_dict['url'], payload, auth=user.auth) + assert res.status_code == 201 + assert res.json['data']['attributes']['content'] == payload['data']['attributes']['content'] + + +@pytest.mark.django_db +class TestFileCommentCreate(NodeCommentsCreateMixin): + + @pytest.fixture() + def payload(self): + def make_payload(target_id): + return { + 'data': { + 'type': 'comments', + 'attributes': { + 'content': 'This is a comment' + }, + 'relationships': { + 'target': { + 'data': { + 'type': 'files', + 'id': target_id + } } } } } - } - - def _set_up_private_project_with_private_comment_level(self): - self.private_project = ProjectFactory(is_public=False, creator=self.user, comment_level='private') - self.private_project.add_contributor(self.read_only_contributor, permissions=['read']) - self.private_project.save() - self.private_url = '/{}nodes/{}/comments/'.format(API_BASE, self.private_project._id) - self.test_file = test_utils.create_test_file(self.private_project, self.user) - self.private_payload = self._set_up_payload(self.test_file.get_guid()._id) - - def _set_up_public_project_with_private_comment_level(self): - self.public_project = ProjectFactory(is_public=True, creator=self.user, comment_level='private') - self.public_project.add_contributor(self.read_only_contributor, permissions=['read']) - self.public_project.save() - self.public_url = '/{}nodes/{}/comments/'.format(API_BASE, self.public_project._id) - self.test_file = test_utils.create_test_file(self.public_project, self.user) - self.public_payload = self._set_up_payload(self.test_file.get_guid()._id) - - def _set_up_public_project_with_public_comment_level(self): + return make_payload + + @pytest.fixture() + def project_private_comment_private(self, user, user_read_contrib, payload): + project_private = ProjectFactory(is_public=False, creator=user, comment_level='private') + project_private.add_contributor(user_read_contrib, permissions=['read']) + project_private.save() + url_private = '/{}nodes/{}/comments/'.format(API_BASE, project_private._id) + file_private = test_utils.create_test_file(project_private, user) + payload_private = payload(file_private.get_guid()._id) + return {'project': project_private, 'url': url_private, 'file': file_private, 'payload': payload_private} + + @pytest.fixture() + def project_public_comment_private(self, user, user_read_contrib, payload): + project_public = ProjectFactory(is_public=True, creator=user, comment_level='private') + project_public.add_contributor(user_read_contrib, permissions=['read']) + project_public.save() + url_public = '/{}nodes/{}/comments/'.format(API_BASE, project_public._id) + file_public = test_utils.create_test_file(project_public, user) + payload_public = payload(file_public.get_guid()._id) + return {'project': project_public, 'url': url_public, 'file': file_public, 'payload': payload_public} + + @pytest.fixture() + def project_public_comment_public(self, user, user_read_contrib, payload): """ Public project configured so that any logged-in user can comment.""" - self.project_with_public_comment_level = ProjectFactory(is_public=True, creator=self.user) - self.project_with_public_comment_level.add_contributor(self.read_only_contributor, permissions=['read']) - self.project_with_public_comment_level.save() - self.public_comments_url = '/{}nodes/{}/comments/'.format(API_BASE, self.project_with_public_comment_level._id) - self.test_file = test_utils.create_test_file(self.project_with_public_comment_level, self.user) - self.public_comment_level_payload = self._set_up_payload(self.test_file.get_guid()._id) - - def _set_up_private_project_with_public_comment_level(self): - self.private_project_with_public_comment_level = ProjectFactory(is_public=False, creator=self.user) - self.private_project_with_public_comment_level.add_contributor(self.read_only_contributor, permissions=['read']) - self.private_project_with_public_comment_level.save() - self.private_project_public_comments_url = '/{}nodes/{}/comments/'.format(API_BASE, self.private_project_with_public_comment_level._id) - self.test_file = test_utils.create_test_file(self.private_project_with_public_comment_level, self.user) - self.private_project_public_comments_payload = self._set_up_payload(self.test_file.get_guid()._id) - - def test_create_file_comment_invalid_target_id(self): - self._set_up_private_project_with_private_comment_level() - file = test_utils.create_test_file(ProjectFactory(), self.user) - payload = self._set_up_payload(file._id) - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], "Invalid comment target \'" + str(file._id) + "\'.") - - def test_create_file_comment_invalid_target_type(self): - self._set_up_private_project_with_private_comment_level() - payload = { + project_public = ProjectFactory(is_public=True, creator=user) + project_public.add_contributor(user_read_contrib, permissions=['read']) + project_public.save() + url_public = '/{}nodes/{}/comments/'.format(API_BASE, project_public._id) + file_public = test_utils.create_test_file(project_public, user) + payload_public = payload(file_public.get_guid()._id) + return {'project': project_public, 'url': url_public, 'file': file_public, 'payload': payload_public} + + @pytest.fixture() + def project_private_comment_public(self, user, user_read_contrib, payload): + project_private = ProjectFactory(is_public=False, creator=user) + project_private.add_contributor(user_read_contrib, permissions=['read']) + project_private.save() + url_private = '/{}nodes/{}/comments/'.format(API_BASE, project_private._id) + file_private = test_utils.create_test_file(project_private, user) + payload_private = payload(file_private.get_guid()._id) + return {'project': project_private, 'url': url_private, 'file': file_private, 'payload': payload_private} + + def test_create_file_comment_errors(self, app, user, payload, project_private_comment_private): + + # test_create_file_comment_invalid_target_id + project_dict = project_private_comment_private + file = test_utils.create_test_file(ProjectFactory(), user) + payload_req = payload(file._id) + res = app.post_json_api(project_dict['url'], payload_req, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'Invalid comment target \'' + str(file._id) + '\'.' + + # test_create_file_comment_invalid_target_type + project_dict = project_private_comment_private + payload_req = { 'data': { 'type': 'comments', 'attributes': { @@ -761,81 +784,95 @@ def test_create_file_comment_invalid_target_type(self): 'target': { 'data': { 'type': 'Invalid', - 'id': self.test_file.get_guid()._id + 'id': project_dict['file'].get_guid()._id } } } } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 409) - assert_equal(res.json['errors'][0]['detail'], 'The target resource has a type of "files", but you set the json body\'s type field to "Invalid". You probably need to change the type field to match the target resource\'s type.') - - -class TestWikiCommentCreate(NodeCommentsCreateMixin, ApiTestCase): - - def _set_up_payload(self, target_id): - return { - 'data': { - 'type': 'comments', - 'attributes': { - 'content': 'This is a comment' - }, - 'relationships': { - 'target': { - 'data': { - 'type': 'wiki', - 'id': target_id + res = app.post_json_api(project_dict['url'], payload_req, auth=user.auth, expect_errors=True) + assert res.status_code == 409 + assert res.json['errors'][0]['detail'] == 'The target resource has a type of "files", but you set the json body\'s type field to "Invalid". You probably need to change the type field to match the target resource\'s type.' + + +@pytest.mark.django_db +class TestWikiCommentCreate(NodeCommentsCreateMixin): + + @pytest.fixture() + def payload(self): + def make_payload(target_id): + return { + 'data': { + 'type': 'comments', + 'attributes': { + 'content': 'This is a comment' + }, + 'relationships': { + 'target': { + 'data': { + 'type': 'wiki', + 'id': target_id + } } } } } - } - - def _set_up_private_project_with_private_comment_level(self): - self.private_project = ProjectFactory(is_public=False, creator=self.user, comment_level='private') - self.private_project.add_contributor(self.read_only_contributor, permissions=['read']) - self.private_project.save() - self.private_url = '/{}nodes/{}/comments/'.format(API_BASE, self.private_project._id) - self.wiki = NodeWikiFactory(node=self.private_project, user=self.user) - self.private_payload = self._set_up_payload(self.wiki._id) - - def _set_up_public_project_with_private_comment_level(self): - self.public_project = ProjectFactory(is_public=True, creator=self.user, comment_level='private') - self.public_project.add_contributor(self.read_only_contributor, permissions=['read']) - self.public_project.save() - self.public_url = '/{}nodes/{}/comments/'.format(API_BASE, self.public_project._id) - self.wiki = NodeWikiFactory(node=self.public_project, user=self.user) - self.public_payload = self._set_up_payload(self.wiki._id) - - def _set_up_public_project_with_public_comment_level(self): + return make_payload + + @pytest.fixture() + def project_private_comment_private(self, user, user_read_contrib, payload): + project_private = ProjectFactory(is_public=False, creator=user, comment_level='private') + project_private.add_contributor(user_read_contrib, permissions=['read']) + project_private.save() + url_private = '/{}nodes/{}/comments/'.format(API_BASE, project_private._id) + wiki = NodeWikiFactory(node=project_private, user=user) + payload_private = payload(wiki._id) + return {'project': project_private, 'url': url_private, 'wiki': wiki, 'payload': payload_private} + + @pytest.fixture() + def project_public_comment_private(self, user, user_read_contrib, payload): + project_public = ProjectFactory(is_public=True, creator=user, comment_level='private') + project_public.add_contributor(user_read_contrib, permissions=['read']) + project_public.save() + url_public = '/{}nodes/{}/comments/'.format(API_BASE, project_public._id) + wiki = NodeWikiFactory(node=project_public, user=user) + payload_public = payload(wiki._id) + return {'project': project_public, 'url': url_public, 'wiki': wiki, 'payload': payload_public} + + @pytest.fixture() + def project_public_comment_public(self, user, user_read_contrib, payload): """ Public project configured so that any logged-in user can comment.""" - self.project_with_public_comment_level = ProjectFactory(is_public=True, creator=self.user) - self.project_with_public_comment_level.add_contributor(self.read_only_contributor, permissions=['read']) - self.project_with_public_comment_level.save() - self.public_comments_url = '/{}nodes/{}/comments/'.format(API_BASE, self.project_with_public_comment_level._id) - self.wiki = NodeWikiFactory(node=self.project_with_public_comment_level, user=self.user) - self.public_comment_level_payload = self._set_up_payload(self.wiki._id) - - def _set_up_private_project_with_public_comment_level(self): - self.private_project_with_public_comment_level = ProjectFactory(is_public=False, creator=self.user) - self.private_project_with_public_comment_level.add_contributor(self.read_only_contributor, permissions=['read']) - self.private_project_with_public_comment_level.save() - self.private_project_public_comments_url = '/{}nodes/{}/comments/'.format(API_BASE, self.private_project_with_public_comment_level._id) - self.wiki = NodeWikiFactory(node=self.private_project_with_public_comment_level, user=self.user) - self.private_project_public_comments_payload = self._set_up_payload(self.wiki._id) - - def test_create_wiki_comment_invalid_target_id(self, mock_update_search=None): - self._set_up_private_project_with_private_comment_level() - wiki = NodeWikiFactory(node=ProjectFactory(), user=self.user) - payload = self._set_up_payload(wiki._id) - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], "Invalid comment target \'" + str(wiki._id) + "\'.") - - def test_create_wiki_comment_invalid_target_type(self, mock_update_search=None): - self._set_up_private_project_with_private_comment_level() - payload = { + project_public = ProjectFactory(is_public=True, creator=user) + project_public.add_contributor(user_read_contrib, permissions=['read']) + project_public.save() + url_public = '/{}nodes/{}/comments/'.format(API_BASE, project_public._id) + wiki = NodeWikiFactory(node=project_public, user=user) + payload_public = payload(wiki._id) + return {'project': project_public, 'url': url_public, 'wiki': wiki, 'payload': payload_public} + + @pytest.fixture() + def project_private_comment_public(self, user, user_read_contrib, payload): + project_private = ProjectFactory(is_public=False, creator=user) + project_private.add_contributor(user_read_contrib, permissions=['read']) + project_private.save() + url_private = '/{}nodes/{}/comments/'.format(API_BASE, project_private._id) + wiki = NodeWikiFactory(node=project_private, user=user) + payload_private = payload(wiki._id) + return {'project': project_private, 'url': url_private, 'wiki': wiki, 'payload': payload_private} + + def test_create_wiki_comment_errors(self, app, user, payload, project_private_comment_private, mock_update_search=None): + + # test_create_wiki_comment_invalid_target_id + project_dict = project_private_comment_private + wiki = NodeWikiFactory(node=ProjectFactory(), user=user) + payload_req = payload(wiki._id) + res = app.post_json_api(project_dict['url'], payload_req, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'Invalid comment target \'' + str(wiki._id) + '\'.' + + # test_create_wiki_comment_invalid_target_type + project_dict = project_private_comment_private + payload_req = { 'data': { 'type': 'comments', 'attributes': { @@ -845,206 +882,238 @@ def test_create_wiki_comment_invalid_target_type(self, mock_update_search=None): 'target': { 'data': { 'type': 'Invalid', - 'id': self.wiki._id + 'id': project_dict['wiki']._id } } } } } - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 409) - assert_equal(res.json['errors'][0]['detail'], 'The target resource has a type of "wiki", but you set the json body\'s type field to "Invalid". You probably need to change the type field to match the target resource\'s type.') - - -class TestCommentRepliesCreate(NodeCommentsCreateMixin, ApiTestCase): - - def _set_up_payload(self, comment_id): - return { - 'data': { - 'type': 'comments', - 'attributes': { - 'content': 'This is a comment' - }, - 'relationships': { - 'target': { - 'data': { - 'type': 'comments', - 'id': comment_id + res = app.post_json_api(project_dict['url'], payload_req, auth=user.auth, expect_errors=True) + assert res.status_code == 409 + assert res.json['errors'][0]['detail'] == 'The target resource has a type of "wiki", but you set the json body\'s type field to "Invalid". You probably need to change the type field to match the target resource\'s type.' + + +@pytest.mark.django_db +class TestCommentRepliesCreate(NodeCommentsCreateMixin): + + @pytest.fixture() + def payload(self): + def make_payload(comment_id): + return { + 'data': { + 'type': 'comments', + 'attributes': { + 'content': 'This is a comment' + }, + 'relationships': { + 'target': { + 'data': { + 'type': 'comments', + 'id': comment_id + } } } } } - } - - def _set_up_private_project_with_private_comment_level(self): - self.private_project = ProjectFactory.create(is_public=False, creator=self.user, comment_level='private') - self.private_project.add_contributor(self.read_only_contributor, permissions=['read'], save=True) - self.comment = CommentFactory(node=self.private_project, user=self.user) - self.private_url = '/{}nodes/{}/comments/'.format(API_BASE, self.private_project._id) - self.private_payload = self._set_up_payload(self.comment._id) - - def _set_up_public_project_with_private_comment_level(self): - self.public_project = ProjectFactory.create(is_public=True, creator=self.user, comment_level='private') - self.public_project.add_contributor(self.read_only_contributor, permissions=['read'], save=True) - self.public_comment = CommentFactory(node=self.public_project, user=self.user) - self.public_url = '/{}nodes/{}/comments/'.format(API_BASE, self.public_project._id) - self.public_payload = self._set_up_payload(self.public_comment._id) - - def _set_up_private_project_with_public_comment_level(self): - self.private_project_with_public_comment_level = ProjectFactory(is_public=False, creator=self.user) - self.private_project_with_public_comment_level.add_contributor(self.read_only_contributor, permissions=['read'], save=True) - comment = CommentFactory(node=self.private_project_with_public_comment_level, user=self.user) - reply = CommentFactory(node=self.private_project_with_public_comment_level, target=Guid.load(comment._id), user=self.user) - self.private_project_public_comments_url = '/{}nodes/{}/comments/'.format(API_BASE, self.private_project_with_public_comment_level._id) - self.private_project_public_comments_payload = self._set_up_payload(reply._id) - - def _set_up_public_project_with_public_comment_level(self): - self.public_project_with_public_comment_level = ProjectFactory(is_public=True, creator=self.user) - self.public_project_with_public_comment_level.add_contributor(self.read_only_contributor, permissions=['read'], save=True) - comment = CommentFactory(node=self.public_project_with_public_comment_level, user=self.user) - reply = CommentFactory(node=self.public_project_with_public_comment_level, target=Guid.load(comment._id), user=self.user) - self.public_comments_url = '/{}nodes/{}/comments/'.format(API_BASE, self.public_project_with_public_comment_level._id) - self.public_comment_level_payload = self._set_up_payload(reply._id) - - def test_create_comment_reply_invalid_target_id(self): - self._set_up_private_project_with_private_comment_level() - target_comment = CommentFactory(node=ProjectFactory(), user=self.user) - payload = self._set_up_payload(target_comment._id) - res = self.app.post_json_api(self.private_url, payload, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], "Invalid comment target \'" + str(target_comment._id) + "\'.") - - -class TestCommentFiltering(ApiTestCase): - - def setUp(self): - super(TestCommentFiltering, self).setUp() - self.user = AuthUserFactory() - self.project = ProjectFactory(creator=self.user) - self.comment = CommentFactory(node=self.project, user=self.user, page='node') - self.deleted_comment = CommentFactory(node=self.project, user=self.user, is_deleted=True, page='node') - self.base_url = '/{}nodes/{}/comments/'.format(API_BASE, self.project._id) - - self.formatted_date_created = self.comment.date_created.strftime('%Y-%m-%dT%H:%M:%S.%f') - self.comment.edit('Edited comment', auth=core.Auth(self.user), save=True) - self.formatted_date_modified = self.comment.date_modified.strftime('%Y-%m-%dT%H:%M:%S.%f') - - def test_node_comments_with_no_filter_returns_all_comments(self): - res = self.app.get(self.base_url, auth=self.user.auth) - assert_equal(len(res.json['data']), 2) - - def test_filtering_for_deleted_comments(self): - url = self.base_url + '?filter[deleted]=True' - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 1) - assert_true(res.json['data'][0]['attributes']['deleted']) - - def test_filtering_for_non_deleted_comments(self): - url = self.base_url + '?filter[deleted]=False' - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 1) - assert_false(res.json['data'][0]['attributes']['deleted']) - - def test_filtering_comments_created_before_date(self): - url = self.base_url + '?filter[date_created][lt]={}'.format(self.formatted_date_created) - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 0) - - def test_filtering_comments_created_on_date(self): - url = self.base_url + '?filter[date_created][eq]={}'.format(self.formatted_date_created) - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 1) - - def test_filtering_comments_created_on_or_before_date(self): - url = self.base_url + '?filter[date_created][lte]={}'.format(self.formatted_date_created) - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 1) - - def test_filtering_comments_created_after_date(self): - url = self.base_url + '?filter[date_created][gt]={}'.format(self.formatted_date_created) - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 1) - - def test_filtering_comments_created_on_or_after_date(self): - url = self.base_url + '?filter[date_created][gte]={}'.format(self.formatted_date_created) - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 2) - - def test_filtering_comments_modified_before_date(self): - url = self.base_url + '?filter[date_modified][lt]={}'.format(self.formatted_date_modified) - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 1) - - def test_filtering_comments_modified_on_date(self): - url = self.base_url + '?filter[date_modified][eq]={}'.format(self.formatted_date_modified) - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 1) - - def test_filtering_comments_modified_after_date(self): - url = self.base_url + '?filter[date_modified][gt]={}'.format(self.formatted_date_modified) - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 0) - - def test_filtering_by_target_node(self): - url = self.base_url + '?filter[target]=' + str(self.project._id) - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 2) - assert_in(self.project._id, res.json['data'][0]['relationships']['target']['links']['related']['href']) - assert_in(self.project._id, res.json['data'][1]['relationships']['target']['links']['related']['href']) - - def test_filtering_by_target_no_results(self): - url = self.base_url + '?filter[target]=' + 'fakeid' - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 0) - - def test_filtering_by_target_no_results_with_related_counts(self): - url = '{}?filter[target]=fakeid&related_counts=True'.format(self.base_url) - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 0) - - def test_filtering_for_comment_replies(self): - reply = CommentFactory(node=self.project, user=self.user, target=Guid.load(self.comment._id)) - url = self.base_url + '?filter[target]=' + str(self.comment._id) - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 1) - assert_in(self.comment._id, res.json['data'][0]['relationships']['target']['links']['related']['href']) - - def test_filtering_by_target_file(self): - test_file = test_utils.create_test_file(self.project, self.user) + return make_payload + + @pytest.fixture() + def project_private_comment_private(self, user, user_read_contrib, payload): + project_private = ProjectFactory.create(is_public=False, creator=user, comment_level='private') + project_private.add_contributor(user_read_contrib, permissions=['read'], save=True) + comment_private = CommentFactory(node=project_private, user=user) + url_private = '/{}nodes/{}/comments/'.format(API_BASE, project_private._id) + payload_private = payload(comment_private._id) + return {'project': project_private, 'comment': comment_private, 'url': url_private, 'payload': payload_private} + + @pytest.fixture() + def project_public_comment_private(self, user, user_read_contrib, payload): + project_public = ProjectFactory.create(is_public=True, creator=user, comment_level='private') + project_public.add_contributor(user_read_contrib, permissions=['read'], save=True) + comment_public = CommentFactory(node=project_public, user=user) + url_public = '/{}nodes/{}/comments/'.format(API_BASE, project_public._id) + payload_public = payload(comment_public._id) + return {'project': project_public, 'comment': comment_public, 'url': url_public, 'payload': payload_public} + + @pytest.fixture() + def project_private_comment_public(self, user, user_read_contrib, payload): + project_private = ProjectFactory(is_public=False, creator=user) + project_private.add_contributor(user_read_contrib, permissions=['read'], save=True) + comment_private = CommentFactory(node=project_private, user=user) + comment_reply = CommentFactory(node=project_private, target=Guid.load(comment_private._id), user=user) + url_private = '/{}nodes/{}/comments/'.format(API_BASE, project_private._id) + payload_private = payload(comment_reply._id) + return {'project': project_private, 'comment': comment_private, 'reply': comment_reply, 'url': url_private, 'payload': payload_private} + + @pytest.fixture() + def project_public_comment_public(self, user, user_read_contrib, payload): + project_public = ProjectFactory(is_public=True, creator=user) + project_public.add_contributor(user_read_contrib, permissions=['read'], save=True) + comment_public = CommentFactory(node=project_public, user=user) + comment_reply = CommentFactory(node=project_public, target=Guid.load(comment_public._id), user=user) + url_public = '/{}nodes/{}/comments/'.format(API_BASE, project_public._id) + payload_public = payload(comment_reply._id) + return {'project': project_public, 'comment': comment_public, 'reply': comment_reply, 'url': url_public, 'payload': payload_public} + + def test_create_comment_reply_invalid_target_id(self, app, user, payload, project_private_comment_private): + project_dict = project_private_comment_private + target_comment = CommentFactory(node=ProjectFactory(), user=user) + payload_req = payload(target_comment._id) + res = app.post_json_api(project_dict['url'], payload_req, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == 'Invalid comment target \'' + str(target_comment._id) + '\'.' + + +@pytest.mark.django_db +class TestCommentFiltering: + + @pytest.fixture() + def project(self, user): + return ProjectFactory(creator=user) + + @pytest.fixture() + def comment(self, user, project): + return CommentFactory(node=project, user=user, page='node') + + @pytest.fixture() + def comment_deleted(self, user, project): + return CommentFactory(node=project, user=user, is_deleted=True, page='node') + + @pytest.fixture() + def url_base(self, project): + return '/{}nodes/{}/comments/'.format(API_BASE, project._id) + + @pytest.fixture() + def date_created_formatted(self, comment): + return comment.date_created.strftime('%Y-%m-%dT%H:%M:%S.%f') + + @pytest.fixture() + def date_modified_formatted(self, user, comment): + comment.edit('Edited comment', auth=core.Auth(user), save=True) + return comment.date_modified.strftime('%Y-%m-%dT%H:%M:%S.%f') + + def test_filtering(self, app, user, project, comment, comment_deleted, date_created_formatted, date_modified_formatted, url_base): + + # test_node_comments_with_no_filter_returns_all_comments + res = app.get(url_base, auth=user.auth) + assert len(res.json['data']) == 2 + + # test_filtering_for_deleted_comments + assert comment + assert comment_deleted + url = url_base + '?filter[deleted]=True' + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 1 + assert res.json['data'][0]['attributes']['deleted'] + + # test_filtering_for_non_deleted_comments + assert comment + assert comment_deleted + url = url_base + '?filter[deleted]=False' + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 1 + assert not res.json['data'][0]['attributes']['deleted'] + + # test_filtering_comments_created_before_date + url = url_base + '?filter[date_created][lt]={}'.format(date_created_formatted) + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 0 + + # test_filtering_comments_created_on_date + url = url_base + '?filter[date_created][eq]={}'.format(date_created_formatted) + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 1 + + # test_filtering_comments_created_on_or_before_date + url = url_base + '?filter[date_created][lte]={}'.format(date_created_formatted) + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 1 + + # test_filtering_comments_created_after_date + url = url_base + '?filter[date_created][gt]={}'.format(date_created_formatted) + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 1 + + # test_filtering_comments_created_on_or_after_date + url = url_base + '?filter[date_created][gte]={}'.format(date_created_formatted) + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 2 + + # test_filtering_comments_modified_before_date + url = url_base + '?filter[date_modified][lt]={}'.format(date_modified_formatted) + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 1 + + # test_filtering_comments_modified_on_date + url = url_base + '?filter[date_modified][eq]={}'.format(date_modified_formatted) + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 1 + + # test_filtering_comments_modified_after_date + url = url_base + '?filter[date_modified][gt]={}'.format(date_modified_formatted) + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 0 + + # test_filtering_by_target_node + url = url_base + '?filter[target]=' + str(project._id) + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 2 + assert project._id in res.json['data'][0]['relationships']['target']['links']['related']['href'] + assert project._id in res.json['data'][1]['relationships']['target']['links']['related']['href'] + + # test_filtering_by_target_no_results + url = url_base + '?filter[target]=' + 'fakeid' + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 0 + + # test_filtering_by_target_no_results_with_related_counts + url = '{}?filter[target]=fakeid&related_counts=True'.format(url_base) + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 0 + + # test_filtering_by_page_node + url = url_base + '?filter[page]=node' + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 2 + assert 'node' == res.json['data'][0]['attributes']['page'] + assert 'node' == res.json['data'][1]['attributes']['page'] + + def test_filtering_for_comment_replies(self, app, user, project, comment, comment_deleted, url_base): + reply = CommentFactory(node=project, user=user, target=Guid.load(comment._id)) + url = url_base + '?filter[target]=' + str(comment._id) + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 1 + assert comment._id in res.json['data'][0]['relationships']['target']['links']['related']['href'] + + def test_filtering_by_target_file(self, app, user, project, comment, comment_deleted, url_base): + test_file = test_utils.create_test_file(project, user) target = test_file.get_guid() - file_comment = CommentFactory(node=self.project, user=self.user, target=target) - url = self.base_url + '?filter[target]=' + str(target._id) - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 1) - assert_in(test_file._id, res.json['data'][0]['relationships']['target']['links']['related']['href']) - - def test_filtering_by_target_wiki(self): - test_wiki = NodeWikiFactory(node=self.project, user=self.user) - wiki_comment = CommentFactory(node=self.project, user=self.user, target=Guid.load(test_wiki._id), page='wiki') - url = self.base_url + '?filter[target]=' + str(test_wiki._id) - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 1) - assert_equal(test_wiki.get_absolute_url(), res.json['data'][0]['relationships']['target']['links']['related']['href']) - - def test_filtering_by_page_node(self): - url = self.base_url + '?filter[page]=node' - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 2) - assert_equal('node', res.json['data'][0]['attributes']['page']) - assert_equal('node', res.json['data'][1]['attributes']['page']) - - def test_filtering_by_page_files(self): - test_file = test_utils.create_test_file(self.project, self.user) - file_comment = CommentFactory(node=self.project, user=self.user, target=test_file.get_guid(), page='files') - url = self.base_url + '?filter[page]=files' - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 1) - assert_equal('files', res.json['data'][0]['attributes']['page']) - - def test_filtering_by_page_wiki(self): - test_wiki = NodeWikiFactory(node=self.project, user=self.user) - wiki_comment = CommentFactory(node=self.project, user=self.user, target=Guid.load(test_wiki._id), page='wiki') - url = self.base_url + '?filter[page]=wiki' - res = self.app.get(url, auth=self.user.auth) - assert_equal(len(res.json['data']), 1) - assert_equal('wiki', res.json['data'][0]['attributes']['page']) + file_comment = CommentFactory(node=project, user=user, target=target) + url = url_base + '?filter[target]=' + str(target._id) + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 1 + assert test_file._id in res.json['data'][0]['relationships']['target']['links']['related']['href'] + + def test_filtering_by_target_wiki(self, app, user, project, comment, comment_deleted, url_base): + test_wiki = NodeWikiFactory(node=project, user=user) + wiki_comment = CommentFactory(node=project, user=user, target=Guid.load(test_wiki._id), page='wiki') + url = url_base + '?filter[target]=' + str(test_wiki._id) + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 1 + assert test_wiki.get_absolute_url() == res.json['data'][0]['relationships']['target']['links']['related']['href'] + + def test_filtering_by_page_files(self, app, user, project, comment, comment_deleted, url_base): + test_file = test_utils.create_test_file(project, user) + file_comment = CommentFactory(node=project, user=user, target=test_file.get_guid(), page='files') + url = url_base + '?filter[page]=files' + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 1 + assert 'files' == res.json['data'][0]['attributes']['page'] + + def test_filtering_by_page_wiki(self, app, user, project, comment, comment_deleted, url_base): + test_wiki = NodeWikiFactory(node=project, user=user) + wiki_comment = CommentFactory(node=project, user=user, target=Guid.load(test_wiki._id), page='wiki') + url = url_base + '?filter[page]=wiki' + res = app.get(url, auth=user.auth) + assert len(res.json['data']) == 1 + assert 'wiki' == res.json['data'][0]['attributes']['page'] From b03c5b251bf71534d62cc17f4b087da7cb0d470e Mon Sep 17 00:00:00 2001 From: Rheisen Dennis Date: Fri, 7 Jul 2017 14:36:04 -0400 Subject: [PATCH 26/62] partial conversion of test_node_contributors_detail (assert_latest_log decorator needed) --- .../views/test_node_contributors_detail.py | 1292 +++++++++-------- 1 file changed, 676 insertions(+), 616 deletions(-) diff --git a/api_tests/nodes/views/test_node_contributors_detail.py b/api_tests/nodes/views/test_node_contributors_detail.py index ec5d6692416..8e9b68eba3a 100644 --- a/api_tests/nodes/views/test_node_contributors_detail.py +++ b/api_tests/nodes/views/test_node_contributors_detail.py @@ -1,202 +1,224 @@ -# -*- coding: utf-8 -*- -from nose.tools import * # flake8: noqa - -from osf.models import NodeLog -from framework.auth.core import Auth -from website.util import permissions +import pytest from api.base.settings.defaults import API_BASE -from website.util import disconnected_from_listeners -from website.project.signals import contributor_removed - -from tests.base import ApiTestCase +from framework.auth.core import Auth +from osf.models import NodeLog from osf_tests.factories import ( ProjectFactory, AuthUserFactory, ) +from rest_framework import exceptions from tests.utils import assert_logs, assert_not_logs +from website.util import permissions, disconnected_from_listeners +from website.project.signals import contributor_removed -class NodeCRUDTestCase(ApiTestCase): +@pytest.fixture() +def user(): + return AuthUserFactory() - def setUp(self): - super(NodeCRUDTestCase, self).setUp() - self.user = AuthUserFactory() - self.user_two = AuthUserFactory() +@pytest.mark.django_db +class TestContributorDetail: - self.title = 'Cool Project' - self.new_title = 'Super Cool Project' - self.description = 'A Properly Cool Project' - self.new_description = 'An even cooler project' - self.category = 'data' - self.new_category = 'project' + @pytest.fixture() + def title(self): + return 'Cool Project' - self.public_project = ProjectFactory(title=self.title, - description=self.description, - category=self.category, - is_public=True, - creator=self.user) + @pytest.fixture() + def description(self): + return 'A Properly Cool Project' - self.public_url = '/{}nodes/{}/'.format(API_BASE, self.public_project._id) + @pytest.fixture() + def category(self): + return 'data' - self.private_project = ProjectFactory(title=self.title, - description=self.description, - category=self.category, - is_public=False, - creator=self.user) - self.private_url = '/{}nodes/{}/'.format(API_BASE, self.private_project._id) + @pytest.fixture() + def project_public(self, user, title, description, category): + return ProjectFactory( + title=title, + description=description, + category=category, + is_public=True, + creator=user + ) - self.fake_url = '/{}nodes/{}/'.format(API_BASE, '12345') + @pytest.fixture() + def project_private(self, user, title, description, category): + return ProjectFactory( + title=title, + description=description, + category=category, + is_public=False, + creator=user + ) + @pytest.fixture() + def url_public(self, user, project_public): + return '/{}nodes/{}/contributors/{}/'.format(API_BASE, project_public._id, user._id) -def make_node_payload(node, attributes): - return { - 'data': { - 'id': node._id, - 'type': 'nodes', - 'attributes': attributes, - } - } + @pytest.fixture() + def url_private_base(self, project_private): + return '/{}nodes/{}/contributors/{}/'.format(API_BASE, project_private._id, '{}') + @pytest.fixture() + def url_private(self, user, url_private_base): + return url_private_base.format(user._id) -class TestContributorDetail(NodeCRUDTestCase): - def setUp(self): - super(TestContributorDetail, self).setUp() + def test_get_contributor_detail_valid_response(self, app, user, project_public, project_private, url_public, url_private): - self.public_url = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.public_project._id, self.user._id) - self.private_url_base = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.private_project._id, '{}') - self.private_url = self.private_url_base.format(self.user._id) + # test_get_public_contributor_detail + res = app.get(url_public) + assert res.status_code == 200 + assert res.json['data']['id'] == '{}-{}'.format(project_public._id, user._id) - def test_get_public_contributor_detail(self): - res = self.app.get(self.public_url) - assert_equal(res.status_code, 200) - assert_equal(res.json['data']['id'], '{}-{}'.format(self.public_project._id, self.user._id)) + # regression test + # test_get_public_contributor_detail_is_viewable_through_browsable_api + res = app.get(url_public + '?format=api') + assert res.status_code == 200 - # regression test - def test_get_public_contributor_detail_is_viewable_through_browsable_api(self): - res = self.app.get(self.public_url + '?format=api') - assert_equal(res.status_code, 200) + # test_get_private_node_contributor_detail_contributor_auth + res = app.get(url_private, auth=user.auth) + assert res.status_code == 200 + assert res.json['data']['id'] == '{}-{}'.format(project_private._id, user._id) - def test_get_private_node_contributor_detail_contributor_auth(self): - res = self.app.get(self.private_url, auth=self.user.auth) - assert_equal(res.status_code, 200) - assert_equal(res.json['data']['id'], '{}-{}'.format(self.private_project._id, self.user._id)) + def test_get_contributor_detail_errors(self, app, user, url_private_base, url_private): + non_contrib = AuthUserFactory() - def test_get_private_node_contributor_detail_non_contributor(self): - res = self.app.get(self.private_url, auth=self.user_two.auth, expect_errors=True) - assert_equal(res.status_code, 403) + # test_get_private_node_contributor_detail_non_contributor + res = app.get(url_private, auth=non_contrib.auth, expect_errors=True) + assert res.status_code == 403 - def test_get_private_node_contributor_detail_not_logged_in(self): - res = self.app.get(self.private_url, expect_errors=True) - assert_equal(res.status_code, 401) + # test_get_private_node_contributor_detail_not_logged_in + res = app.get(url_private, expect_errors=True) + assert res.status_code == 401 - def test_get_private_node_non_contributor_detail_contributor_auth(self): - res = self.app.get(self.private_url_base.format(self.user_two._id), auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 404) + # test_get_private_node_non_contributor_detail_contributor_auth + res = app.get(url_private_base.format(non_contrib._id), auth=user.auth, expect_errors=True) + assert res.status_code == 404 - def test_get_private_node_invalid_user_detail_contributor_auth(self): - res = self.app.get(self.private_url_base.format('invalid'), auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 404) + # test_get_private_node_invalid_user_detail_contributor_auth + res = app.get(url_private_base.format('invalid'), auth=user.auth, expect_errors=True) + assert res.status_code == 404 - def test_unregistered_contributor_detail_show_up_as_name_associated_with_project(self): - project = ProjectFactory(creator=self.user, is_public=True) - project.add_unregistered_contributor('Robert Jackson', 'robert@gmail.com', auth=Auth(self.user), save=True) + def test_unregistered_contributor_detail_show_up_as_name_associated_with_project(self, app, user): + project = ProjectFactory(creator=user, is_public=True) + project.add_unregistered_contributor('Rheisen Dennis', 'reason@gmail.com', auth=Auth(user), save=True) unregistered_contributor = project.contributors[1] url = '/{}nodes/{}/contributors/{}/'.format(API_BASE, project._id, unregistered_contributor._id) - res = self.app.get(url, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 200) - assert_equal(res.json['data']['embeds']['users']['data']['attributes']['full_name'], 'Robert Jackson') - assert_equal(res.json['data']['attributes'].get('unregistered_contributor'), 'Robert Jackson') + res = app.get(url, auth=user.auth, expect_errors=True) + assert res.status_code == 200 + assert res.json['data']['embeds']['users']['data']['attributes']['full_name'] == 'Rheisen Dennis' + assert res.json['data']['attributes'].get('unregistered_contributor') == 'Rheisen Dennis' - project_two = ProjectFactory(creator=self.user, is_public=True) - project_two.add_unregistered_contributor('Bob Jackson', 'robert@gmail.com', auth=Auth(self.user), save=True) + project_two = ProjectFactory(creator=user, is_public=True) + project_two.add_unregistered_contributor('Nesiehr Sinned', 'reason@gmail.com', auth=Auth(user), save=True) url = '/{}nodes/{}/contributors/{}/'.format(API_BASE, project_two._id, unregistered_contributor._id) - res = self.app.get(url, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 200) + res = app.get(url, auth=user.auth, expect_errors=True) + assert res.status_code == 200 - assert_equal(res.json['data']['embeds']['users']['data']['attributes']['full_name'], 'Robert Jackson') - assert_equal(res.json['data']['attributes'].get('unregistered_contributor'), 'Bob Jackson') + assert res.json['data']['embeds']['users']['data']['attributes']['full_name'] == 'Rheisen Dennis' + assert res.json['data']['attributes'].get('unregistered_contributor') == 'Nesiehr Sinned' - def test_detail_includes_index(self): - res = self.app.get(self.public_url) + def test_detail_includes_index(self, app, user, project_public, url_public): + res = app.get(url_public) data = res.json['data'] - assert_in('index', data['attributes'].keys()) - assert_equal(data['attributes']['index'], 0) + assert 'index' in data['attributes'].keys() + assert data['attributes']['index'] == 0 other_contributor = AuthUserFactory() - self.public_project.add_contributor(other_contributor, auth=Auth(self.user), save=True) - - other_contributor_detail = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.public_project._id, other_contributor._id) - res = self.app.get(other_contributor_detail) - assert_equal(res.json['data']['attributes']['index'], 1) - - -class TestNodeContributorOrdering(ApiTestCase): - def setUp(self): - super(TestNodeContributorOrdering, self).setUp() - self.contributors = [AuthUserFactory() for number in range(1, 10)] - self.user_one = AuthUserFactory() - - self.project = ProjectFactory(creator=self.user_one) - for contributor in self.contributors: - self.project.add_contributor( - contributor, - permissions=[permissions.READ, permissions.WRITE], - visible=True, - save=True - ) - - self.contributors.insert(0, self.user_one) - self.base_contributor_url = '/{}nodes/{}/contributors/'.format(API_BASE, self.project._id) - self.url_creator = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, self.user_one._id) - self.contributor_urls = ['/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, contributor._id) - for contributor in self.contributors] - self.last_position = len(self.contributors) - 1 + project_public.add_contributor(other_contributor, auth=Auth(user), save=True) + + other_contributor_detail = '/{}nodes/{}/contributors/{}/'.format(API_BASE, project_public._id, other_contributor._id) + res = app.get(other_contributor_detail) + assert res.json['data']['attributes']['index'] == 1 + + +@pytest.mark.django_db +class TestNodeContributorOrdering: + + @pytest.fixture() + def contribs(self, user): + contribs = [AuthUserFactory() for number in range(1, 10)] + contribs.insert(0, user) + return contribs + + @pytest.fixture() + def project(self, user, contribs): + project = ProjectFactory(creator=user) + for contrib in contribs: + if contrib._id is not user._id: + project.add_contributor( + contrib, + permissions=[permissions.READ, permissions.WRITE], + visible=True, + save=True + ) + return project + + @pytest.fixture() + def url_contrib_base(self, project): + return '/{}nodes/{}/contributors/'.format(API_BASE, project._id) + + @pytest.fixture() + def url_creator(self, user, project): + return '/{}nodes/{}/contributors/{}/'.format(API_BASE, project._id, user._id) + + @pytest.fixture() + def urls_contrib(self, contribs, project): + return ['/{}nodes/{}/contributors/{}/'.format(API_BASE, project._id, contrib._id) + for contrib in contribs] + + @pytest.fixture() + def last_position(self, contribs): + return len(contribs) - 1 @staticmethod - def _get_contributor_user_id(contributor): - return contributor['embeds']['users']['data']['id'] - - def test_initial_order(self): - res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth) - assert_equal(res.status_code, 200) + @pytest.fixture() + def contrib_user_id(): + def get_contrib_user_id(contributor): + return contributor['embeds']['users']['data']['id'] + return get_contrib_user_id + + def test_initial_order(self, app, user, contribs, project, contrib_user_id): + res = app.get('/{}nodes/{}/contributors/'.format(API_BASE, project._id), auth=user.auth) + assert res.status_code == 200 contributor_list = res.json['data'] found_contributors = False - for i in range(0, len(self.contributors)): - assert_equal(self.contributors[i]._id, self._get_contributor_user_id(contributor_list[i])) - assert_equal(i, contributor_list[i]['attributes']['index']) + for i in range(0, len(contribs)): + assert contribs[i]._id == contrib_user_id(contributor_list[i]) + assert i == contributor_list[i]['attributes']['index'] found_contributors = True - assert_true(found_contributors, "Did not compare any contributors.") - - @assert_logs(NodeLog.CONTRIB_REORDERED, 'project') - def test_move_top_contributor_down_one_and_also_log(self): - contributor_to_move = self.contributors[0]._id - contributor_id = '{}-{}'.format(self.project._id, contributor_to_move) - former_second_contributor = self.contributors[1] - url = '{}{}/'.format(self.base_contributor_url, contributor_to_move) - data = { - 'data': { - 'id': contributor_id, - 'type': 'contributors', - 'attributes': { - 'index': 1 - } - } - } - res_patch = self.app.patch_json_api(url, data, auth=self.user_one.auth) - assert_equal(res_patch.status_code, 200) - self.project.reload() - res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth) - assert_equal(res.status_code, 200) - contributor_list = res.json['data'] - assert_equal(self._get_contributor_user_id(contributor_list[1]), contributor_to_move) - assert_equal(self._get_contributor_user_id(contributor_list[0]), former_second_contributor._id) - - def test_move_second_contributor_up_one_to_top(self): - contributor_to_move = self.contributors[1]._id - contributor_id = '{}-{}'.format(self.project._id, contributor_to_move) - former_first_contributor = self.contributors[0] - url = '{}{}/'.format(self.base_contributor_url, contributor_to_move) + assert found_contributors, 'Did not compare any contributors.' + +# @assert_logs(NodeLog.CONTRIB_REORDERED, 'project') +# def test_move_top_contributor_down_one_and_also_log(self): +# contributor_to_move = self.contribs[0]._id +# contributor_id = '{}-{}'.format(self.project._id, contributor_to_move) +# former_second_contributor = self.contribs[1] +# url = '{}{}/'.format(self.base_contributor_url, contributor_to_move) +# data = { +# 'data': { +# 'id': contributor_id, +# 'type': 'contributors', +# 'attributes': { +# 'index': 1 +# } +# } +# } +# res_patch = self.app.patch_json_api(url, data, auth=self.user.auth) +# assert res_patch.status_code == 200 +# self.project.reload() +# res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user.auth) +# assert res.status_code == 200 +# contributor_list = res.json['data'] +# assert self.contrib_user_id(contributor_list[1]) == contributor_to_move +# assert self.contrib_user_id(contributor_list[0]) == former_second_contributor._id + + def test_move_second_contributor_up_one_to_top(self, app, user, contribs, project, contrib_user_id, url_contrib_base): + contributor_to_move = contribs[1]._id + contributor_id = '{}-{}'.format(project._id, contributor_to_move) + former_first_contributor = contribs[0] + url = '{}{}/'.format(url_contrib_base, contributor_to_move) data = { 'data': { 'id': contributor_id, @@ -206,44 +228,44 @@ def test_move_second_contributor_up_one_to_top(self): } } } - res_patch = self.app.patch_json_api(url, data, auth=self.user_one.auth) - assert_equal(res_patch.status_code, 200) - self.project.reload() - res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth) - assert_equal(res.status_code, 200) + res_patch = app.patch_json_api(url, data, auth=user.auth) + assert res_patch.status_code == 200 + project.reload() + res = app.get('/{}nodes/{}/contributors/'.format(API_BASE, project._id), auth=user.auth) + assert res.status_code == 200 contributor_list = res.json['data'] - assert_equal(self._get_contributor_user_id(contributor_list[0]), contributor_to_move) - assert_equal(self._get_contributor_user_id(contributor_list[1]), former_first_contributor._id) - - def test_move_top_contributor_down_to_bottom(self): - contributor_to_move = self.contributors[0]._id - contributor_id = '{}-{}'.format(self.project._id, contributor_to_move) - former_second_contributor = self.contributors[1] - url = '{}{}/'.format(self.base_contributor_url, contributor_to_move) + assert contrib_user_id(contributor_list[0]) == contributor_to_move + assert contrib_user_id(contributor_list[1]) == former_first_contributor._id + + def test_move_top_contributor_down_to_bottom(self, app, user, contribs, project, contrib_user_id, last_position, url_contrib_base): + contributor_to_move = contribs[0]._id + contributor_id = '{}-{}'.format(project._id, contributor_to_move) + former_second_contributor = contribs[1] + url = '{}{}/'.format(url_contrib_base, contributor_to_move) data = { 'data': { 'id': contributor_id, 'type': 'contributors', 'attributes': { - 'index': self.last_position + 'index': last_position } } } - res_patch = self.app.patch_json_api(url, data, auth=self.user_one.auth) - assert_equal(res_patch.status_code, 200) - self.project.reload() - res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth) - assert_equal(res.status_code, 200) + res_patch = app.patch_json_api(url, data, auth=user.auth) + assert res_patch.status_code == 200 + project.reload() + res = app.get('/{}nodes/{}/contributors/'.format(API_BASE, project._id), auth=user.auth) + assert res.status_code == 200 contributor_list = res.json['data'] - assert_equal(self._get_contributor_user_id(contributor_list[self.last_position]), contributor_to_move) - assert_equal(self._get_contributor_user_id(contributor_list[0]), former_second_contributor._id) + assert contrib_user_id(contributor_list[last_position]) == contributor_to_move + assert contrib_user_id(contributor_list[0]) == former_second_contributor._id - def test_move_bottom_contributor_up_to_top(self): - contributor_to_move = self.contributors[self.last_position]._id - contributor_id = '{}-{}'.format(self.project._id, contributor_to_move) - former_second_to_last_contributor = self.contributors[self.last_position - 1] + def test_move_bottom_contributor_up_to_top(self, app, user, contribs, project, contrib_user_id, last_position, url_contrib_base): + contributor_to_move = contribs[last_position]._id + contributor_id = '{}-{}'.format(project._id, contributor_to_move) + former_second_to_last_contributor = contribs[last_position - 1] - url = '{}{}/'.format(self.base_contributor_url, contributor_to_move) + url = '{}{}/'.format(url_contrib_base, contributor_to_move) data = { 'data': { 'id': contributor_id, @@ -253,50 +275,48 @@ def test_move_bottom_contributor_up_to_top(self): } } } - res_patch = self.app.patch_json_api(url, data, auth=self.user_one.auth) - assert_equal(res_patch.status_code, 200) - self.project.reload() - res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth) - assert_equal(res.status_code, 200) + res_patch = app.patch_json_api(url, data, auth=user.auth) + assert res_patch.status_code == 200 + project.reload() + res = app.get('/{}nodes/{}/contributors/'.format(API_BASE, project._id), auth=user.auth) + assert res.status_code == 200 contributor_list = res.json['data'] - assert_equal(self._get_contributor_user_id(contributor_list[0]), contributor_to_move) - assert_equal( - self._get_contributor_user_id(contributor_list[self.last_position]), - former_second_to_last_contributor._id - ) + assert contrib_user_id(contributor_list[0]) == contributor_to_move + assert ( + contrib_user_id(contributor_list[last_position]) == + former_second_to_last_contributor._id) - def test_move_second_to_last_contributor_down_past_bottom(self): - contributor_to_move = self.contributors[self.last_position - 1]._id - contributor_id = '{}-{}'.format(self.project._id, contributor_to_move) - former_last_contributor = self.contributors[self.last_position] + def test_move_second_to_last_contributor_down_past_bottom(self, app, user, contribs, project, contrib_user_id, last_position, url_contrib_base): + contributor_to_move = contribs[last_position - 1]._id + contributor_id = '{}-{}'.format(project._id, contributor_to_move) + former_last_contributor = contribs[last_position] - url = '{}{}/'.format(self.base_contributor_url, contributor_to_move) + url = '{}{}/'.format(url_contrib_base, contributor_to_move) data = { 'data': { 'id': contributor_id, 'type': 'contributors', 'attributes': { - 'index': self.last_position + 10 + 'index': last_position + 10 } } } - res_patch = self.app.patch_json_api(url, data, auth=self.user_one.auth) - assert_equal(res_patch.status_code, 200) - self.project.reload() - res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth) - assert_equal(res.status_code, 200) + res_patch = app.patch_json_api(url, data, auth=user.auth) + assert res_patch.status_code == 200 + project.reload() + res = app.get('/{}nodes/{}/contributors/'.format(API_BASE, project._id), auth=user.auth) + assert res.status_code == 200 contributor_list = res.json['data'] - assert_equal(self._get_contributor_user_id(contributor_list[self.last_position]), contributor_to_move) - assert_equal( - self._get_contributor_user_id(contributor_list[self.last_position - 1]), - former_last_contributor._id - ) - - def test_move_top_contributor_down_to_second_to_last_position_with_negative_numbers(self): - contributor_to_move = self.contributors[0]._id - contributor_id = '{}-{}'.format(self.project._id, contributor_to_move) - former_second_contributor = self.contributors[1] - url = '{}{}/'.format(self.base_contributor_url, contributor_to_move) + assert contrib_user_id(contributor_list[last_position]) == contributor_to_move + assert ( + contrib_user_id(contributor_list[last_position - 1]) == + former_last_contributor._id) + + def test_move_top_contributor_down_to_second_to_last_position_with_negative_numbers(self, app, user, contribs, project, contrib_user_id, last_position, url_contrib_base): + contributor_to_move = contribs[0]._id + contributor_id = '{}-{}'.format(project._id, contributor_to_move) + former_second_contributor = contribs[1] + url = '{}{}/'.format(url_contrib_base, contributor_to_move) data = { 'data': { 'id': contributor_id, @@ -306,20 +326,20 @@ def test_move_top_contributor_down_to_second_to_last_position_with_negative_numb } } } - res_patch = self.app.patch_json_api(url, data, auth=self.user_one.auth) - assert_equal(res_patch.status_code, 200) - self.project.reload() - res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth) - assert_equal(res.status_code, 200) + res_patch = app.patch_json_api(url, data, auth=user.auth) + assert res_patch.status_code == 200 + project.reload() + res = app.get('/{}nodes/{}/contributors/'.format(API_BASE, project._id), auth=user.auth) + assert res.status_code == 200 contributor_list = res.json['data'] - assert_equal(self._get_contributor_user_id(contributor_list[self.last_position - 1]), contributor_to_move) - assert_equal(self._get_contributor_user_id(contributor_list[0]), former_second_contributor._id) - - def test_write_contributor_fails_to_move_top_contributor_down_one(self): - contributor_to_move = self.contributors[0]._id - contributor_id = '{}-{}'.format(self.project._id, contributor_to_move) - former_second_contributor = self.contributors[1] - url = '{}{}/'.format(self.base_contributor_url, contributor_to_move) + assert contrib_user_id(contributor_list[last_position - 1]) == contributor_to_move + assert contrib_user_id(contributor_list[0]) == former_second_contributor._id + + def test_write_contributor_fails_to_move_top_contributor_down_one(self, app, user, contribs, project, contrib_user_id, url_contrib_base): + contributor_to_move = contribs[0]._id + contributor_id = '{}-{}'.format(project._id, contributor_to_move) + former_second_contributor = contribs[1] + url = '{}{}/'.format(url_contrib_base, contributor_to_move) data = { 'data': { 'id': contributor_id, @@ -329,20 +349,20 @@ def test_write_contributor_fails_to_move_top_contributor_down_one(self): } } } - res_patch = self.app.patch_json_api(url, data, auth=former_second_contributor.auth, expect_errors=True) - assert_equal(res_patch.status_code, 403) - self.project.reload() - res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth) - assert_equal(res.status_code, 200) + res_patch = app.patch_json_api(url, data, auth=former_second_contributor.auth, expect_errors=True) + assert res_patch.status_code == 403 + project.reload() + res = app.get('/{}nodes/{}/contributors/'.format(API_BASE, project._id), auth=user.auth) + assert res.status_code == 200 contributor_list = res.json['data'] - assert_equal(self._get_contributor_user_id(contributor_list[0]), contributor_to_move) - assert_equal(self._get_contributor_user_id(contributor_list[1]), former_second_contributor._id) - - def test_non_authenticated_fails_to_move_top_contributor_down_one(self): - contributor_to_move = self.contributors[0]._id - contributor_id = '{}-{}'.format(self.project._id, contributor_to_move) - former_second_contributor = self.contributors[1] - url = '{}{}/'.format(self.base_contributor_url, contributor_to_move) + assert contrib_user_id(contributor_list[0]) == contributor_to_move + assert contrib_user_id(contributor_list[1]) == former_second_contributor._id + + def test_non_authenticated_fails_to_move_top_contributor_down_one(self, app, user, contribs, project, contrib_user_id, url_contrib_base): + contributor_to_move = contribs[0]._id + contributor_id = '{}-{}'.format(project._id, contributor_to_move) + former_second_contributor = contribs[1] + url = '{}{}/'.format(url_contrib_base, contributor_to_move) data = { 'data': { 'id': contributor_id, @@ -352,55 +372,42 @@ def test_non_authenticated_fails_to_move_top_contributor_down_one(self): } } } - res_patch = self.app.patch_json_api(url, data, expect_errors=True) - assert_equal(res_patch.status_code, 401) - self.project.reload() - res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user_one.auth) - assert_equal(res.status_code, 200) + res_patch = app.patch_json_api(url, data, expect_errors=True) + assert res_patch.status_code == 401 + project.reload() + res = app.get('/{}nodes/{}/contributors/'.format(API_BASE, project._id), auth=user.auth) + assert res.status_code == 200 contributor_list = res.json['data'] - assert_equal(self._get_contributor_user_id(contributor_list[0]), contributor_to_move) - assert_equal(self._get_contributor_user_id(contributor_list[1]), former_second_contributor._id) + assert contrib_user_id(contributor_list[0]) == contributor_to_move + assert contrib_user_id(contributor_list[1]) == former_second_contributor._id -class TestNodeContributorUpdate(ApiTestCase): - def setUp(self): - super(TestNodeContributorUpdate, self).setUp() - self.user = AuthUserFactory() - self.user_two = AuthUserFactory() +@pytest.mark.django_db +class TestNodeContributorUpdate: - self.project = ProjectFactory(creator=self.user) - self.project.add_contributor(self.user_two, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True) + @pytest.fixture() + def contrib(self): + return AuthUserFactory() - self.url_creator = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, self.user._id) - self.url_contributor = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, self.user_two._id) + @pytest.fixture() + def project(self, user, contrib): + project = ProjectFactory(creator=user) + project.add_contributor(contrib, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True) + return project - def test_node_update_invalid_data(self): - res = self.app.put_json_api(self.url_creator, "Incorrect data", auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], "Malformed request.") + @pytest.fixture() + def url_creator(self, user, project): + return '/{}nodes/{}/contributors/{}/'.format(API_BASE, project._id, user._id) - res = self.app.put_json_api(self.url_creator, ["Incorrect data"], auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(res.json['errors'][0]['detail'], "Malformed request.") + @pytest.fixture() + def url_contrib(self, project, contrib): + return '/{}nodes/{}/contributors/{}/'.format(API_BASE, project._id, contrib._id) - def test_change_contributor_no_id(self): - data = { - 'data': { - 'type': 'contributors', - 'attributes': { - 'permission': permissions.ADMIN, - 'bibliographic': True - } - } - } - res = self.app.put_json_api(self.url_contributor, data, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) + def test_change_contrib_errors(self, app, user, contrib, project, url_contrib): - def test_change_contributor_correct_id(self): - contrib_id = '{}-{}'.format(self.project._id, self.user_two._id) + # test_change_contributor_no_id data = { 'data': { - 'id': contrib_id, 'type': 'contributors', 'attributes': { 'permission': permissions.ADMIN, @@ -408,10 +415,10 @@ def test_change_contributor_correct_id(self): } } } - res = self.app.put_json_api(self.url_contributor, data, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 200) + res = app.put_json_api(url_contrib, data, auth=user.auth, expect_errors=True) + assert res.status_code == 400 - def test_change_contributor_incorrect_id(self): + # test_change_contributor_incorrect_id data = { 'data': { 'id': '12345', @@ -422,11 +429,11 @@ def test_change_contributor_incorrect_id(self): } } } - res = self.app.put_json_api(self.url_contributor, data, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 409) + res = app.put_json_api(url_contrib, data, auth=user.auth, expect_errors=True) + assert res.status_code == 409 - def test_change_contributor_no_type(self): - contrib_id = '{}-{}'.format(self.project._id, self.user_two._id) + # test_change_contributor_no_type + contrib_id = '{}-{}'.format(project._id, contrib._id) data = { 'data': { 'id': contrib_id, @@ -436,13 +443,13 @@ def test_change_contributor_no_type(self): } } } - res = self.app.put_json_api(self.url_contributor, data, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) + res = app.put_json_api(url_contrib, data, auth=user.auth, expect_errors=True) + assert res.status_code == 400 - def test_change_contributor_incorrect_type(self): + # test_change_contributor_incorrect_type data = { 'data': { - 'id': self.user_two._id, + 'id': contrib._id, 'type': 'Wrong type.', 'attributes': { 'permission': permissions.ADMIN, @@ -450,114 +457,48 @@ def test_change_contributor_incorrect_type(self): } } } - res = self.app.put_json_api(self.url_contributor, data, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 409) - - - @assert_logs(NodeLog.PERMISSIONS_UPDATED, 'project', -3) - @assert_logs(NodeLog.PERMISSIONS_UPDATED, 'project', -2) - @assert_logs(NodeLog.PERMISSIONS_UPDATED, 'project') - def test_change_contributor_permissions(self): - contrib_id = '{}-{}'.format(self.project._id, self.user_two._id) - data = { - 'data': { - 'id': contrib_id, - 'type': 'contributors', - 'attributes': { - 'permission': permissions.ADMIN, - 'bibliographic': True - } - } - } - res = self.app.put_json_api(self.url_contributor, data, auth=self.user.auth) - assert_equal(res.status_code, 200) - attributes = res.json['data']['attributes'] - assert_equal(attributes['permission'], permissions.ADMIN) - - self.project.reload() - assert_equal(self.project.get_permissions(self.user_two), [permissions.READ, permissions.WRITE, permissions.ADMIN]) + res = app.put_json_api(url_contrib, data, auth=user.auth, expect_errors=True) + assert res.status_code == 409 + # test_invalid_change_inputs_contributor + contrib_id = '{}-{}'.format(project._id, contrib._id) data = { 'data': { 'id': contrib_id, 'type': 'contributors', 'attributes': { - 'permission': permissions.WRITE, - 'bibliographic': True + 'permission': 'invalid', + 'bibliographic': 'invalid' } } } - res = self.app.put_json_api(self.url_contributor, data, auth=self.user.auth) - assert_equal(res.status_code, 200) - attributes = res.json['data']['attributes'] - assert_equal(attributes['permission'], permissions.WRITE) - - self.project.reload() - assert_equal(self.project.get_permissions(self.user_two), [permissions.READ, permissions.WRITE]) + res = app.put_json_api(url_contrib, data, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert project.get_permissions(contrib) == [permissions.READ, permissions.WRITE] + assert project.get_visible(contrib) + # test_change_contributor_not_logged_in data = { 'data': { - 'id': contrib_id, + 'id': contrib._id, 'type': 'contributors', 'attributes': { 'permission': permissions.READ, - 'bibliographic': True - } - } - } - res = self.app.put_json_api(self.url_contributor, data, auth=self.user.auth) - assert_equal(res.status_code, 200) - attributes = res.json['data']['attributes'] - assert_equal(attributes['permission'], permissions.READ) - - self.project.reload() - assert_equal(self.project.get_permissions(self.user_two), [permissions.READ]) - - @assert_logs(NodeLog.MADE_CONTRIBUTOR_INVISIBLE, 'project', -2) - @assert_logs(NodeLog.MADE_CONTRIBUTOR_VISIBLE, 'project') - def test_change_contributor_bibliographic(self): - contrib_id = '{}-{}'.format(self.project._id, self.user_two._id) - data = { - 'data': { - 'id': contrib_id, - 'type': 'contributors', - 'attributes': { 'bibliographic': False } } } - res = self.app.put_json_api(self.url_contributor, data, auth=self.user.auth) - assert_equal(res.status_code, 200) - attributes = res.json['data']['attributes'] - assert_equal(attributes['bibliographic'], False) + res = app.put_json_api(url_contrib, data, expect_errors=True) + assert res.status_code == 401 - self.project.reload() - assert_false(self.project.get_visible(self.user_two)) + project.reload() + assert project.get_permissions(contrib) == [permissions.READ, permissions.WRITE] + assert project.get_visible(contrib) + # test_change_contributor_non_admin_auth data = { 'data': { - 'id': contrib_id, - 'type': 'contributors', - 'attributes': { - 'bibliographic': True - } - } - } - res = self.app.put_json_api(self.url_contributor, data, auth=self.user.auth) - assert_equal(res.status_code, 200) - attributes = res.json['data']['attributes'] - assert_equal(attributes['bibliographic'], True) - - self.project.reload() - assert_true(self.project.get_visible(self.user_two)) - - @assert_logs(NodeLog.PERMISSIONS_UPDATED, 'project', -2) - @assert_logs(NodeLog.MADE_CONTRIBUTOR_INVISIBLE, 'project') - def test_change_contributor_permission_and_bibliographic(self): - contrib_id = '{}-{}'.format(self.project._id, self.user_two._id) - data = { - 'data': { - 'id': contrib_id, + 'id': contrib._id, 'type': 'contributors', 'attributes': { 'permission': permissions.READ, @@ -565,80 +506,15 @@ def test_change_contributor_permission_and_bibliographic(self): } } } - res = self.app.put_json_api(self.url_contributor, data, auth=self.user.auth) - assert_equal(res.status_code, 200) - attributes = res.json['data']['attributes'] - assert_equal(attributes['permission'], permissions.READ) - assert_equal(attributes['bibliographic'], False) - - self.project.reload() - assert_equal(self.project.get_permissions(self.user_two), [permissions.READ]) - assert_false(self.project.get_visible(self.user_two)) - - @assert_not_logs(NodeLog.PERMISSIONS_UPDATED, 'project') - def test_not_change_contributor(self): - contrib_id = '{}-{}'.format(self.project._id, self.user_two._id) - data = { - 'data': { - 'id': contrib_id, - 'type': 'contributors', - 'attributes': { - 'permission': None, - 'bibliographic': True - } - } - } - res = self.app.put_json_api(self.url_contributor, data, auth=self.user.auth) - assert_equal(res.status_code, 200) - attributes = res.json['data']['attributes'] - assert_equal(attributes['permission'], permissions.WRITE) - assert_equal(attributes['bibliographic'], True) - - self.project.reload() - assert_equal(self.project.get_permissions(self.user_two), [permissions.READ, permissions.WRITE]) - assert_true(self.project.get_visible(self.user_two)) - - def test_invalid_change_inputs_contributor(self): - contrib_id = '{}-{}'.format(self.project._id, self.user_two._id) - data = { - 'data': { - 'id': contrib_id, - 'type': 'contributors', - 'attributes': { - 'permission': 'invalid', - 'bibliographic': 'invalid' - } - } - } - res = self.app.put_json_api(self.url_contributor, data, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - assert_equal(self.project.get_permissions(self.user_two), [permissions.READ, permissions.WRITE]) - assert_true(self.project.get_visible(self.user_two)) - - @assert_logs(NodeLog.PERMISSIONS_UPDATED, 'project') - def test_change_admin_self_with_other_admin(self): - self.project.add_permission(self.user_two, permissions.ADMIN, save=True) - contrib_id = '{}-{}'.format(self.project._id, self.user._id) - data = { - 'data': { - 'id': contrib_id, - 'type': 'contributors', - 'attributes': { - 'permission': permissions.WRITE, - 'bibliographic': True - } - } - } - res = self.app.put_json_api(self.url_creator, data, auth=self.user.auth) - assert_equal(res.status_code, 200) - attributes = res.json['data']['attributes'] - assert_equal(attributes['permission'], permissions.WRITE) + res = app.put_json_api(url_contrib, data, auth=contrib.auth, expect_errors=True) + assert res.status_code == 403 - self.project.reload() - assert_equal(self.project.get_permissions(self.user), [permissions.READ, permissions.WRITE]) + project.reload() + assert project.get_permissions(contrib) == [permissions.READ, permissions.WRITE] + assert project.get_visible(contrib) - def test_change_admin_self_without_other_admin(self): - contrib_id = '{}-{}'.format(self.project._id, self.user._id) + def test_change_admin_self_without_other_admin(self, app, user, project, url_creator): + contrib_id = '{}-{}'.format(project._id, user._id) data = { 'data': { 'id': contrib_id, @@ -649,81 +525,244 @@ def test_change_admin_self_without_other_admin(self): } } } - res = self.app.put_json_api(self.url_creator, data, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) + res = app.put_json_api(url_creator, data, auth=user.auth, expect_errors=True) + assert res.status_code == 400 - self.project.reload() - assert_equal(self.project.get_permissions(self.user), [permissions.READ, permissions.WRITE, permissions.ADMIN]) + project.reload() + assert project.get_permissions(user) == [permissions.READ, permissions.WRITE, permissions.ADMIN] - def test_remove_all_bibliographic_statuses_contributors(self): - self.project.set_visible(self.user_two, False, save=True) - contrib_id = '{}-{}'.format(self.project._id, self.user._id) - data = { - 'data': { - 'id': contrib_id, - 'type': 'contributors', - 'attributes': { - 'bibliographic': False - } - } - } - res = self.app.put_json_api(self.url_creator, data, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) + def test_node_update_invalid_data(self, app, user, url_creator): + res = app.put_json_api(url_creator, "Incorrect data", auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == exceptions.ParseError.default_detail - self.project.reload() - assert_true(self.project.get_visible(self.user)) + res = app.put_json_api(url_creator, ["Incorrect data"], auth=user.auth, expect_errors=True) + assert res.status_code == 400 + assert res.json['errors'][0]['detail'] == exceptions.ParseError.default_detail - def test_change_contributor_non_admin_auth(self): + def test_change_contributor_correct_id(self, app, user, contrib, project, url_contrib): + contrib_id = '{}-{}'.format(project._id, contrib._id) data = { 'data': { - 'id': self.user_two._id, + 'id': contrib_id, 'type': 'contributors', 'attributes': { - 'permission': permissions.READ, - 'bibliographic': False + 'permission': permissions.ADMIN, + 'bibliographic': True } } } - res = self.app.put_json_api(self.url_contributor, data, auth=self.user_two.auth, expect_errors=True) - assert_equal(res.status_code, 403) + res = app.put_json_api(url_contrib, data, auth=user.auth, expect_errors=True) + assert res.status_code == 200 - self.project.reload() - assert_equal(self.project.get_permissions(self.user_two), [permissions.READ, permissions.WRITE]) - assert_true(self.project.get_visible(self.user_two)) - - def test_change_contributor_not_logged_in(self): + def test_remove_all_bibliographic_statuses_contributors(self, app, user, contrib, project, url_creator): + project.set_visible(contrib, False, save=True) + contrib_id = '{}-{}'.format(project._id, user._id) data = { 'data': { - 'id': self.user_two._id, + 'id': contrib_id, 'type': 'contributors', 'attributes': { - 'permission': permissions.READ, 'bibliographic': False } } } - res = self.app.put_json_api(self.url_contributor, data, expect_errors=True) - assert_equal(res.status_code, 401) - - self.project.reload() - assert_equal(self.project.get_permissions(self.user_two), [permissions.READ, permissions.WRITE]) - assert_true(self.project.get_visible(self.user_two)) - - -class TestNodeContributorPartialUpdate(ApiTestCase): - def setUp(self): - super(TestNodeContributorPartialUpdate, self).setUp() - self.user = AuthUserFactory() - self.user_two = AuthUserFactory() - - self.project = ProjectFactory(creator=self.user) - self.project.add_contributor(self.user_two, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True) - - self.url_creator = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, self.user._id) - self.url_contributor = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, self.user_two._id) - - def test_patch_bibliographic_only(self): - creator_id = '{}-{}'.format(self.project._id, self.user._id) + res = app.put_json_api(url_creator, data, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + + project.reload() + assert project.get_visible(user) + +# @assert_logs(NodeLog.PERMISSIONS_UPDATED, 'project', -3) +# @assert_logs(NodeLog.PERMISSIONS_UPDATED, 'project', -2) +# @assert_logs(NodeLog.PERMISSIONS_UPDATED, 'project') +# def test_change_contributor_permissions(self): +# contrib_id = '{}-{}'.format(self.project._id, self.contrib._id) +# data = { +# 'data': { +# 'id': contrib_id, +# 'type': 'contributors', +# 'attributes': { +# 'permission': permissions.ADMIN, +# 'bibliographic': True +# } +# } +# } +# res = self.app.put_json_api(self.url_contrib, data, auth=self.user.auth) +# assert res.status_code == 200 +# attributes = res.json['data']['attributes'] +# assert attributes['permission'] == permissions.ADMIN + +# self.project.reload() +# assert self.project.get_permissions(self.contrib) == [permissions.READ, permissions.WRITE, permissions.ADMIN] + +# data = { +# 'data': { +# 'id': contrib_id, +# 'type': 'contributors', +# 'attributes': { +# 'permission': permissions.WRITE, +# 'bibliographic': True +# } +# } +# } +# res = self.app.put_json_api(self.url_contrib, data, auth=self.user.auth) +# assert res.status_code == 200 +# attributes = res.json['data']['attributes'] +# assert attributes['permission'] == permissions.WRITE + +# self.project.reload() +# assert self.project.get_permissions(self.contrib) == [permissions.READ, permissions.WRITE] + +# data = { +# 'data': { +# 'id': contrib_id, +# 'type': 'contributors', +# 'attributes': { +# 'permission': permissions.READ, +# 'bibliographic': True +# } +# } +# } +# res = self.app.put_json_api(self.url_contrib, data, auth=self.user.auth) +# assert res.status_code == 200 +# attributes = res.json['data']['attributes'] +# assert attributes['permission'] == permissions.READ + +# self.project.reload() +# assert self.project.get_permissions(self.contrib) == [permissions.READ] + +# @assert_logs(NodeLog.MADE_CONTRIBUTOR_INVISIBLE, 'project', -2) +# @assert_logs(NodeLog.MADE_CONTRIBUTOR_VISIBLE, 'project') +# def test_change_contributor_bibliographic(self): +# contrib_id = '{}-{}'.format(self.project._id, self.contrib._id) +# data = { +# 'data': { +# 'id': contrib_id, +# 'type': 'contributors', +# 'attributes': { +# 'bibliographic': False +# } +# } +# } +# res = self.app.put_json_api(self.url_contrib, data, auth=self.user.auth) +# assert res.status_code == 200 +# attributes = res.json['data']['attributes'] +# assert attributes['bibliographic'] == False + +# self.project.reload() +# assert not self.project.get_visible(self.contrib) + +# data = { +# 'data': { +# 'id': contrib_id, +# 'type': 'contributors', +# 'attributes': { +# 'bibliographic': True +# } +# } +# } +# res = self.app.put_json_api(self.url_contrib, data, auth=self.user.auth) +# assert res.status_code == 200 +# attributes = res.json['data']['attributes'] +# assert attributes['bibliographic'] == True + +# self.project.reload() +# assert self.project.get_visible(self.contrib) + +# @assert_logs(NodeLog.PERMISSIONS_UPDATED, 'project', -2) +# @assert_logs(NodeLog.MADE_CONTRIBUTOR_INVISIBLE, 'project') +# def test_change_contributor_permission_and_bibliographic(self): +# contrib_id = '{}-{}'.format(self.project._id, self.contrib._id) +# data = { +# 'data': { +# 'id': contrib_id, +# 'type': 'contributors', +# 'attributes': { +# 'permission': permissions.READ, +# 'bibliographic': False +# } +# } +# } +# res = self.app.put_json_api(self.url_contrib, data, auth=self.user.auth) +# assert res.status_code == 200 +# attributes = res.json['data']['attributes'] +# assert attributes['permission'] == permissions.READ +# assert attributes['bibliographic'] == False + +# self.project.reload() +# assert self.project.get_permissions(self.contrib) == [permissions.READ] +# assert not self.project.get_visible(self.contrib) + +# @assert_not_logs(NodeLog.PERMISSIONS_UPDATED, 'project') +# def test_not_change_contributor(self): +# contrib_id = '{}-{}'.format(self.project._id, self.contrib._id) +# data = { +# 'data': { +# 'id': contrib_id, +# 'type': 'contributors', +# 'attributes': { +# 'permission': None, +# 'bibliographic': True +# } +# } +# } +# res = self.app.put_json_api(self.url_contrib, data, auth=self.user.auth) +# assert res.status_code == 200 +# attributes = res.json['data']['attributes'] +# assert attributes['permission'] == permissions.WRITE +# assert attributes['bibliographic'] == True + +# self.project.reload() +# assert self.project.get_permissions(self.contrib) == [permissions.READ, permissions.WRITE] +# assert self.project.get_visible(self.contrib) + +# @assert_logs(NodeLog.PERMISSIONS_UPDATED, 'project') +# def test_change_admin_self_with_other_admin(self): +# self.project.add_permission(self.contrib, permissions.ADMIN, save=True) +# contrib_id = '{}-{}'.format(self.project._id, self.user._id) +# data = { +# 'data': { +# 'id': contrib_id, +# 'type': 'contributors', +# 'attributes': { +# 'permission': permissions.WRITE, +# 'bibliographic': True +# } +# } +# } +# res = self.app.put_json_api(self.url_creator, data, auth=self.user.auth) +# assert res.status_code == 200 +# attributes = res.json['data']['attributes'] +# assert attributes['permission'] == permissions.WRITE + +# self.project.reload() +# assert self.project.get_permissions(self.user) == [permissions.READ, permissions.WRITE] + + +@pytest.mark.django_db +class TestNodeContributorPartialUpdate: + + @pytest.fixture() + def contrib(self): + return AuthUserFactory() + + @pytest.fixture() + def project(self, user, contrib): + project = ProjectFactory(creator=user) + project.add_contributor(contrib, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True) + return project + + @pytest.fixture() + def url_creator(self, user, project): + return '/{}nodes/{}/contributors/{}/'.format(API_BASE, project._id, user._id) + + @pytest.fixture() + def url_contrib(self, contrib, project): + return '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, self.user_two._id) + + def test_patch_bibliographic_only(self, app, user, project, url_creator): + creator_id = '{}-{}'.format(project._id, user._id) data = { 'data': { 'id': creator_id, @@ -733,17 +772,17 @@ def test_patch_bibliographic_only(self): } } } - res = self.app.patch_json_api(self.url_creator, data, auth=self.user.auth) - assert_equal(res.status_code, 200) - self.project.reload() - assert_equal(self.project.get_permissions(self.user), [permissions.READ, permissions.WRITE, permissions.ADMIN]) - assert_false(self.project.get_visible(self.user)) - - def test_patch_permission_only(self): - user_three = AuthUserFactory() - self.project.add_contributor(user_three, permissions=[permissions.READ, permissions.WRITE], visible=False, save=True) - url_contributor = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, user_three._id) - contributor_id = '{}-{}'.format(self.project._id, user_three._id) + res = app.patch_json_api(url_creator, data, auth=user.auth) + assert res.status_code == 200 + project.reload() + assert project.get_permissions(user) == [permissions.READ, permissions.WRITE, permissions.ADMIN] + assert not project.get_visible(user) + + def test_patch_permission_only(self, app, user, project): + user_read_contrib = AuthUserFactory() + project.add_contributor(user_read_contrib, permissions=[permissions.READ, permissions.WRITE], visible=False, save=True) + url_read_contrib = '/{}nodes/{}/contributors/{}/'.format(API_BASE, project._id, user_read_contrib._id) + contributor_id = '{}-{}'.format(project._id, user_read_contrib._id) data = { 'data': { 'id': contributor_id, @@ -753,129 +792,150 @@ def test_patch_permission_only(self): } } } - res = self.app.patch_json_api(url_contributor, data, auth=self.user.auth) - assert_equal(res.status_code, 200) - self.project.reload() - assert_equal(self.project.get_permissions(user_three), [permissions.READ]) - assert_false(self.project.get_visible(user_three)) - - -class TestNodeContributorDelete(ApiTestCase): - def setUp(self): - super(TestNodeContributorDelete, self).setUp() - self.user = AuthUserFactory() - self.user_two = AuthUserFactory() - self.user_three = AuthUserFactory() - - self.project = ProjectFactory(creator=self.user) - self.project.add_contributor(self.user_two, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True) - - self.url_user = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, self.user._id) - self.url_user_two = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, self.user_two._id) - self.url_user_three = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, self.user_three._id) + res = app.patch_json_api(url_read_contrib, data, auth=user.auth) + assert res.status_code == 200 + project.reload() + assert project.get_permissions(user_read_contrib) == [permissions.READ] + assert not project.get_visible(user_read_contrib) - @assert_logs(NodeLog.CONTRIB_REMOVED, 'project') - def test_remove_contributor_admin(self): - # Disconnect contributor_removed so that we don't check in files - # We can remove this when StoredFileNode is implemented in osf-models - with disconnected_from_listeners(contributor_removed): - res = self.app.delete(self.url_user_two, auth=self.user.auth) - assert_equal(res.status_code, 204) - self.project.reload() - assert_not_in(self.user_two, self.project.contributors) +@pytest.mark.django_db +class TestNodeContributorDelete: - def test_remove_contributor_non_admin_is_forbidden(self): - self.project.add_contributor(self.user_three, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True) + @pytest.fixture() + def user_write_contrib(self): + return AuthUserFactory() - res = self.app.delete(self.url_user_three, auth=self.user_two.auth, expect_errors=True) - assert_equal(res.status_code, 403) + @pytest.fixture() + def user_non_contrib(self): + return AuthUserFactory() - self.project.reload() - assert_in(self.user_three, self.project.contributors) + @pytest.fixture() + def project(self, user, user_write_contrib): + project = ProjectFactory(creator=user) + project.add_contributor( + user_write_contrib, + permissions=[permissions.READ, permissions.WRITE], + visible=True, + save=True) + return project - @assert_logs(NodeLog.CONTRIB_REMOVED, 'project') - def test_remove_self_non_admin(self): - self.project.add_contributor(self.user_three, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True) + @pytest.fixture() + def url_user(self, project, user): + return '/{}nodes/{}/contributors/{}/'.format(API_BASE, project._id, user._id) - # Disconnect contributor_removed so that we don't check in files - # We can remove this when StoredFileNode is implemented in osf-models - with disconnected_from_listeners(contributor_removed): - res = self.app.delete(self.url_user_three, auth=self.user_three.auth) - assert_equal(res.status_code, 204) - - self.project.reload() - assert_not_in(self.user_three, self.project.contributors) + @pytest.fixture() + def url_user_write_contrib(self, project, user_write_contrib): + return '/{}nodes/{}/contributors/{}/'.format(API_BASE, project._id, user_write_contrib._id) - def test_remove_contributor_non_contributor(self): - res = self.app.delete(self.url_user_two, auth=self.user_three.auth, expect_errors=True) - assert_equal(res.status_code, 403) + @pytest.fixture() + def url_user_non_contrib(self, project, user_non_contrib): + return '/{}nodes/{}/contributors/{}/'.format(API_BASE, project._id, user_non_contrib._id) - self.project.reload() - assert_in(self.user_two, self.project.contributors) + def test_remove_errors(self, app, user, user_write_contrib, user_non_contrib, project, url_user, url_user_write_contrib, url_user_non_contrib): - def test_remove_contributor_not_logged_in(self): - res = self.app.delete(self.url_user_two, expect_errors=True) - assert_equal(res.status_code, 401) + # test_remove_contributor_non_contributor + res = app.delete(url_user_write_contrib, auth=user_non_contrib.auth, expect_errors=True) + assert res.status_code == 403 - self.project.reload() - assert_in(self.user_two, self.project.contributors) + project.reload() + assert user_write_contrib in project.contributors - def test_remove_non_contributor_admin(self): - assert_not_in(self.user_three, self.project.contributors) - res = self.app.delete(self.url_user_three, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 404) + # test_remove_contributor_not_logged_in + res = app.delete(url_user_write_contrib, expect_errors=True) + assert res.status_code == 401 - self.project.reload() - assert_not_in(self.user_three, self.project.contributors) - - def test_remove_non_existing_user_admin(self): - url_user_fake = '/{}nodes/{}/contributors/{}/'.format(API_BASE, self.project._id, 'fake') - # Disconnect contributor_removed so that we don't check in files - # We can remove this when StoredFileNode is implemented in osf-models - with disconnected_from_listeners(contributor_removed): - res = self.app.delete(url_user_fake, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 404) + project.reload() + assert user_write_contrib in project.contributors - @assert_logs(NodeLog.CONTRIB_REMOVED, 'project') - def test_remove_self_contributor_not_unique_admin(self): - self.project.add_permission(self.user_two, permissions.ADMIN, save=True) - # Disconnect contributor_removed so that we don't check in files - # We can remove this when StoredFileNode is implemented in osf-models - with disconnected_from_listeners(contributor_removed): - res = self.app.delete(self.url_user, auth=self.user.auth) - assert_equal(res.status_code, 204) + # test_remove_non_contributor_admin + assert user_non_contrib not in project.contributors + res = app.delete(url_user_non_contrib, auth=user.auth, expect_errors=True) + assert res.status_code == 404 - self.project.reload() - assert_not_in(self.user, self.project.contributors) + project.reload() + assert user_non_contrib not in project.contributors - @assert_logs(NodeLog.CONTRIB_REMOVED, 'project') - def test_can_remove_self_as_contributor_not_unique_admin(self): - self.project.add_permission(self.user_two, permissions.ADMIN, save=True) + # test_remove_non_existing_user_admin + url_user_fake = '/{}nodes/{}/contributors/{}/'.format(API_BASE, project._id, 'fake') # Disconnect contributor_removed so that we don't check in files # We can remove this when StoredFileNode is implemented in osf-models with disconnected_from_listeners(contributor_removed): - res = self.app.delete(self.url_user_two, auth=self.user_two.auth) - assert_equal(res.status_code, 204) + res = app.delete(url_user_fake, auth=user.auth, expect_errors=True) + assert res.status_code == 404 - self.project.reload() - assert_not_in(self.user_two, self.project.contributors) - - def test_remove_self_contributor_unique_admin(self): + # test_remove_self_contributor_unique_admin # Disconnect contributor_removed so that we don't check in files # We can remove this when StoredFileNode is implemented in osf-models with disconnected_from_listeners(contributor_removed): - res = self.app.delete(self.url_user, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - - self.project.reload() - assert_in(self.user, self.project.contributors) - - def test_can_not_remove_only_bibliographic_contributor(self): - self.project.add_permission(self.user_two, permissions.ADMIN, save=True) - self.project.set_visible(self.user_two, False, save=True) - res = self.app.delete(self.url_user, auth=self.user.auth, expect_errors=True) - assert_equal(res.status_code, 400) - - self.project.reload() - assert_in(self.user, self.project.contributors) + res = app.delete(url_user, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + + project.reload() + assert user in project.contributors + + def test_can_not_remove_only_bibliographic_contributor(self, app, user, project, user_write_contrib, url_user): + project.add_permission(user_write_contrib, permissions.ADMIN, save=True) + project.set_visible(user_write_contrib, False, save=True) + res = app.delete(url_user, auth=user.auth, expect_errors=True) + assert res.status_code == 400 + + project.reload() + assert user in project.contributors + + def test_remove_contributor_non_admin_is_forbidden(self, app, user_write_contrib, user_non_contrib, project, url_user_non_contrib): + project.add_contributor(user_non_contrib, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True) + + res = app.delete(url_user_non_contrib, auth=user_write_contrib.auth, expect_errors=True) + assert res.status_code == 403 + + project.reload() + assert user_non_contrib in project.contributors + + # @assert_logs(NodeLog.CONTRIB_REMOVED, 'project') + # def test_remove_contributor_admin(self): + # # Disconnect contributor_removed so that we don't check in files + # # We can remove this when StoredFileNode is implemented in osf-models + # with disconnected_from_listeners(contributor_removed): + # res = self.app.delete(self.url_user_two, auth=self.user.auth) + # assert res.status_code == 204 + + # self.project.reload() + # assert self.user_two not in self.project.contributors + + # @assert_logs(NodeLog.CONTRIB_REMOVED, 'project') + # def test_remove_self_non_admin(self): + # self.project.add_contributor(self.user_three, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True) + + # # Disconnect contributor_removed so that we don't check in files + # # We can remove this when StoredFileNode is implemented in osf-models + # with disconnected_from_listeners(contributor_removed): + # res = self.app.delete(self.url_user_three, auth=self.user_three.auth) + # assert res.status_code == 204 + + # self.project.reload() + # assert self.user_three not in self.project.contributors + + # @assert_logs(NodeLog.CONTRIB_REMOVED, 'project') + # def test_remove_self_contributor_not_unique_admin(self): + # self.project.add_permission(self.user_two, permissions.ADMIN, save=True) + # # Disconnect contributor_removed so that we don't check in files + # # We can remove this when StoredFileNode is implemented in osf-models + # with disconnected_from_listeners(contributor_removed): + # res = self.app.delete(self.url_user, auth=self.user.auth) + # assert res.status_code == 204 + + # self.project.reload() + # assert self.user not in self.project.contributors + + # @assert_logs(NodeLog.CONTRIB_REMOVED, 'project') + # def test_can_remove_self_as_contributor_not_unique_admin(self): + # self.project.add_permission(self.user_two, permissions.ADMIN, save=True) + # # Disconnect contributor_removed so that we don't check in files + # # We can remove this when StoredFileNode is implemented in osf-models + # with disconnected_from_listeners(contributor_removed): + # res = self.app.delete(self.url_user_two, auth=self.user_two.auth) + # assert res.status_code == 204 + + # self.project.reload() + # assert self.user_two not in self.project.contributors From 71d79309cfc2442ec610a0a8b8fb5e02a3924e81 Mon Sep 17 00:00:00 2001 From: Rheisen Dennis Date: Mon, 10 Jul 2017 11:36:59 -0400 Subject: [PATCH 27/62] convert remaining node_contributors_detail tests to pytest, add assert_latest_log_not to utils --- .../views/test_node_contributors_detail.py | 457 +++++++++--------- tests/utils.py | 10 + 2 files changed, 241 insertions(+), 226 deletions(-) diff --git a/api_tests/nodes/views/test_node_contributors_detail.py b/api_tests/nodes/views/test_node_contributors_detail.py index 8e9b68eba3a..710e4f3bc89 100644 --- a/api_tests/nodes/views/test_node_contributors_detail.py +++ b/api_tests/nodes/views/test_node_contributors_detail.py @@ -8,7 +8,7 @@ AuthUserFactory, ) from rest_framework import exceptions -from tests.utils import assert_logs, assert_not_logs +from tests.utils import assert_latest_log, assert_latest_log_not from website.util import permissions, disconnected_from_listeners from website.project.signals import contributor_removed @@ -190,29 +190,29 @@ def test_initial_order(self, app, user, contribs, project, contrib_user_id): found_contributors = True assert found_contributors, 'Did not compare any contributors.' -# @assert_logs(NodeLog.CONTRIB_REORDERED, 'project') -# def test_move_top_contributor_down_one_and_also_log(self): -# contributor_to_move = self.contribs[0]._id -# contributor_id = '{}-{}'.format(self.project._id, contributor_to_move) -# former_second_contributor = self.contribs[1] -# url = '{}{}/'.format(self.base_contributor_url, contributor_to_move) -# data = { -# 'data': { -# 'id': contributor_id, -# 'type': 'contributors', -# 'attributes': { -# 'index': 1 -# } -# } -# } -# res_patch = self.app.patch_json_api(url, data, auth=self.user.auth) -# assert res_patch.status_code == 200 -# self.project.reload() -# res = self.app.get('/{}nodes/{}/contributors/'.format(API_BASE, self.project._id), auth=self.user.auth) -# assert res.status_code == 200 -# contributor_list = res.json['data'] -# assert self.contrib_user_id(contributor_list[1]) == contributor_to_move -# assert self.contrib_user_id(contributor_list[0]) == former_second_contributor._id + def test_move_top_contributor_down_one_and_also_log(self, app, user, contribs, project, contrib_user_id, url_contrib_base): + with assert_latest_log(NodeLog.CONTRIB_REORDERED, project): + contributor_to_move = contribs[0]._id + contributor_id = '{}-{}'.format(project._id, contributor_to_move) + former_second_contributor = contribs[1] + url = '{}{}/'.format(url_contrib_base, contributor_to_move) + data = { + 'data': { + 'id': contributor_id, + 'type': 'contributors', + 'attributes': { + 'index': 1 + } + } + } + res_patch = app.patch_json_api(url, data, auth=user.auth) + assert res_patch.status_code == 200 + project.reload() + res = app.get('/{}nodes/{}/contributors/'.format(API_BASE, project._id), auth=user.auth) + assert res.status_code == 200 + contributor_list = res.json['data'] + assert contrib_user_id(contributor_list[1]) == contributor_to_move + assert contrib_user_id(contributor_list[0]) == former_second_contributor._id def test_move_second_contributor_up_one_to_top(self, app, user, contribs, project, contrib_user_id, url_contrib_base): contributor_to_move = contribs[1]._id @@ -573,171 +573,172 @@ def test_remove_all_bibliographic_statuses_contributors(self, app, user, contrib project.reload() assert project.get_visible(user) -# @assert_logs(NodeLog.PERMISSIONS_UPDATED, 'project', -3) -# @assert_logs(NodeLog.PERMISSIONS_UPDATED, 'project', -2) -# @assert_logs(NodeLog.PERMISSIONS_UPDATED, 'project') -# def test_change_contributor_permissions(self): -# contrib_id = '{}-{}'.format(self.project._id, self.contrib._id) -# data = { -# 'data': { -# 'id': contrib_id, -# 'type': 'contributors', -# 'attributes': { -# 'permission': permissions.ADMIN, -# 'bibliographic': True -# } -# } -# } -# res = self.app.put_json_api(self.url_contrib, data, auth=self.user.auth) -# assert res.status_code == 200 -# attributes = res.json['data']['attributes'] -# assert attributes['permission'] == permissions.ADMIN - -# self.project.reload() -# assert self.project.get_permissions(self.contrib) == [permissions.READ, permissions.WRITE, permissions.ADMIN] - -# data = { -# 'data': { -# 'id': contrib_id, -# 'type': 'contributors', -# 'attributes': { -# 'permission': permissions.WRITE, -# 'bibliographic': True -# } -# } -# } -# res = self.app.put_json_api(self.url_contrib, data, auth=self.user.auth) -# assert res.status_code == 200 -# attributes = res.json['data']['attributes'] -# assert attributes['permission'] == permissions.WRITE - -# self.project.reload() -# assert self.project.get_permissions(self.contrib) == [permissions.READ, permissions.WRITE] - -# data = { -# 'data': { -# 'id': contrib_id, -# 'type': 'contributors', -# 'attributes': { -# 'permission': permissions.READ, -# 'bibliographic': True -# } -# } -# } -# res = self.app.put_json_api(self.url_contrib, data, auth=self.user.auth) -# assert res.status_code == 200 -# attributes = res.json['data']['attributes'] -# assert attributes['permission'] == permissions.READ - -# self.project.reload() -# assert self.project.get_permissions(self.contrib) == [permissions.READ] - -# @assert_logs(NodeLog.MADE_CONTRIBUTOR_INVISIBLE, 'project', -2) -# @assert_logs(NodeLog.MADE_CONTRIBUTOR_VISIBLE, 'project') -# def test_change_contributor_bibliographic(self): -# contrib_id = '{}-{}'.format(self.project._id, self.contrib._id) -# data = { -# 'data': { -# 'id': contrib_id, -# 'type': 'contributors', -# 'attributes': { -# 'bibliographic': False -# } -# } -# } -# res = self.app.put_json_api(self.url_contrib, data, auth=self.user.auth) -# assert res.status_code == 200 -# attributes = res.json['data']['attributes'] -# assert attributes['bibliographic'] == False - -# self.project.reload() -# assert not self.project.get_visible(self.contrib) - -# data = { -# 'data': { -# 'id': contrib_id, -# 'type': 'contributors', -# 'attributes': { -# 'bibliographic': True -# } -# } -# } -# res = self.app.put_json_api(self.url_contrib, data, auth=self.user.auth) -# assert res.status_code == 200 -# attributes = res.json['data']['attributes'] -# assert attributes['bibliographic'] == True - -# self.project.reload() -# assert self.project.get_visible(self.contrib) - -# @assert_logs(NodeLog.PERMISSIONS_UPDATED, 'project', -2) -# @assert_logs(NodeLog.MADE_CONTRIBUTOR_INVISIBLE, 'project') -# def test_change_contributor_permission_and_bibliographic(self): -# contrib_id = '{}-{}'.format(self.project._id, self.contrib._id) -# data = { -# 'data': { -# 'id': contrib_id, -# 'type': 'contributors', -# 'attributes': { -# 'permission': permissions.READ, -# 'bibliographic': False -# } -# } -# } -# res = self.app.put_json_api(self.url_contrib, data, auth=self.user.auth) -# assert res.status_code == 200 -# attributes = res.json['data']['attributes'] -# assert attributes['permission'] == permissions.READ -# assert attributes['bibliographic'] == False - -# self.project.reload() -# assert self.project.get_permissions(self.contrib) == [permissions.READ] -# assert not self.project.get_visible(self.contrib) - -# @assert_not_logs(NodeLog.PERMISSIONS_UPDATED, 'project') -# def test_not_change_contributor(self): -# contrib_id = '{}-{}'.format(self.project._id, self.contrib._id) -# data = { -# 'data': { -# 'id': contrib_id, -# 'type': 'contributors', -# 'attributes': { -# 'permission': None, -# 'bibliographic': True -# } -# } -# } -# res = self.app.put_json_api(self.url_contrib, data, auth=self.user.auth) -# assert res.status_code == 200 -# attributes = res.json['data']['attributes'] -# assert attributes['permission'] == permissions.WRITE -# assert attributes['bibliographic'] == True - -# self.project.reload() -# assert self.project.get_permissions(self.contrib) == [permissions.READ, permissions.WRITE] -# assert self.project.get_visible(self.contrib) - -# @assert_logs(NodeLog.PERMISSIONS_UPDATED, 'project') -# def test_change_admin_self_with_other_admin(self): -# self.project.add_permission(self.contrib, permissions.ADMIN, save=True) -# contrib_id = '{}-{}'.format(self.project._id, self.user._id) -# data = { -# 'data': { -# 'id': contrib_id, -# 'type': 'contributors', -# 'attributes': { -# 'permission': permissions.WRITE, -# 'bibliographic': True -# } -# } -# } -# res = self.app.put_json_api(self.url_creator, data, auth=self.user.auth) -# assert res.status_code == 200 -# attributes = res.json['data']['attributes'] -# assert attributes['permission'] == permissions.WRITE - -# self.project.reload() -# assert self.project.get_permissions(self.user) == [permissions.READ, permissions.WRITE] + def test_change_contributor_permissions(self, app, user, contrib, project, url_contrib): + contrib_id = '{}-{}'.format(project._id, contrib._id) + + with assert_latest_log(NodeLog.PERMISSIONS_UPDATED, project): + data = { + 'data': { + 'id': contrib_id, + 'type': 'contributors', + 'attributes': { + 'permission': permissions.ADMIN, + 'bibliographic': True + } + } + } + res = app.put_json_api(url_contrib, data, auth=user.auth) + assert res.status_code == 200 + attributes = res.json['data']['attributes'] + assert attributes['permission'] == permissions.ADMIN + + project.reload() + assert project.get_permissions(contrib) == [permissions.READ, permissions.WRITE, permissions.ADMIN] + + with assert_latest_log(NodeLog.PERMISSIONS_UPDATED, project): + data = { + 'data': { + 'id': contrib_id, + 'type': 'contributors', + 'attributes': { + 'permission': permissions.WRITE, + 'bibliographic': True + } + } + } + res = app.put_json_api(url_contrib, data, auth=user.auth) + assert res.status_code == 200 + attributes = res.json['data']['attributes'] + assert attributes['permission'] == permissions.WRITE + + project.reload() + assert project.get_permissions(contrib) == [permissions.READ, permissions.WRITE] + + with assert_latest_log(NodeLog.PERMISSIONS_UPDATED, project): + data = { + 'data': { + 'id': contrib_id, + 'type': 'contributors', + 'attributes': { + 'permission': permissions.READ, + 'bibliographic': True + } + } + } + res = app.put_json_api(url_contrib, data, auth=user.auth) + assert res.status_code == 200 + attributes = res.json['data']['attributes'] + assert attributes['permission'] == permissions.READ + + project.reload() + assert project.get_permissions(contrib) == [permissions.READ] + + def test_change_contributor_bibliographic(self, app, user, contrib, project, url_contrib): + contrib_id = '{}-{}'.format(project._id, contrib._id) + with assert_latest_log(NodeLog.MADE_CONTRIBUTOR_INVISIBLE, project): + data = { + 'data': { + 'id': contrib_id, + 'type': 'contributors', + 'attributes': { + 'bibliographic': False + } + } + } + res = app.put_json_api(url_contrib, data, auth=user.auth) + assert res.status_code == 200 + attributes = res.json['data']['attributes'] + assert attributes['bibliographic'] == False + + project.reload() + assert not project.get_visible(contrib) + + with assert_latest_log(NodeLog.MADE_CONTRIBUTOR_VISIBLE, project): + data = { + 'data': { + 'id': contrib_id, + 'type': 'contributors', + 'attributes': { + 'bibliographic': True + } + } + } + res = app.put_json_api(url_contrib, data, auth=user.auth) + assert res.status_code == 200 + attributes = res.json['data']['attributes'] + assert attributes['bibliographic'] == True + + project.reload() + assert project.get_visible(contrib) + + def test_change_contributor_permission_and_bibliographic(self, app, user, contrib, project, url_contrib): + with assert_latest_log(NodeLog.PERMISSIONS_UPDATED, project, 1), assert_latest_log(NodeLog.MADE_CONTRIBUTOR_INVISIBLE, project): + contrib_id = '{}-{}'.format(project._id, contrib._id) + data = { + 'data': { + 'id': contrib_id, + 'type': 'contributors', + 'attributes': { + 'permission': permissions.READ, + 'bibliographic': False + } + } + } + res = app.put_json_api(url_contrib, data, auth=user.auth) + assert res.status_code == 200 + attributes = res.json['data']['attributes'] + assert attributes['permission'] == permissions.READ + assert attributes['bibliographic'] == False + + project.reload() + assert project.get_permissions(contrib) == [permissions.READ] + assert not project.get_visible(contrib) + + # @assert_not_logs(NodeLog.PERMISSIONS_UPDATED, 'project') + def test_not_change_contributor(self, app, user, contrib, project, url_contrib): + with assert_latest_log_not(NodeLog.PERMISSIONS_UPDATED, project): + contrib_id = '{}-{}'.format(project._id, contrib._id) + data = { + 'data': { + 'id': contrib_id, + 'type': 'contributors', + 'attributes': { + 'permission': None, + 'bibliographic': True + } + } + } + res = app.put_json_api(url_contrib, data, auth=user.auth) + assert res.status_code == 200 + attributes = res.json['data']['attributes'] + assert attributes['permission'] == permissions.WRITE + assert attributes['bibliographic'] == True + + project.reload() + assert project.get_permissions(contrib) == [permissions.READ, permissions.WRITE] + assert project.get_visible(contrib) + + def test_change_admin_self_with_other_admin(self, app, user, contrib, project, url_creator): + with assert_latest_log(NodeLog.PERMISSIONS_UPDATED, project): + project.add_permission(contrib, permissions.ADMIN, save=True) + contrib_id = '{}-{}'.format(project._id, user._id) + data = { + 'data': { + 'id': contrib_id, + 'type': 'contributors', + 'attributes': { + 'permission': permissions.WRITE, + 'bibliographic': True + } + } + } + res = app.put_json_api(url_creator, data, auth=user.auth) + assert res.status_code == 200 + attributes = res.json['data']['attributes'] + assert attributes['permission'] == permissions.WRITE + + project.reload() + assert project.get_permissions(user) == [permissions.READ, permissions.WRITE] @pytest.mark.django_db @@ -893,49 +894,53 @@ def test_remove_contributor_non_admin_is_forbidden(self, app, user_write_contrib assert user_non_contrib in project.contributors # @assert_logs(NodeLog.CONTRIB_REMOVED, 'project') - # def test_remove_contributor_admin(self): - # # Disconnect contributor_removed so that we don't check in files - # # We can remove this when StoredFileNode is implemented in osf-models - # with disconnected_from_listeners(contributor_removed): - # res = self.app.delete(self.url_user_two, auth=self.user.auth) - # assert res.status_code == 204 + def test_remove_contributor_admin(self, app, user, user_write_contrib, project, url_user_write_contrib): + with assert_latest_log(NodeLog.CONTRIB_REMOVED, project): + # Disconnect contributor_removed so that we don't check in files + # We can remove this when StoredFileNode is implemented in osf-models + with disconnected_from_listeners(contributor_removed): + res = app.delete(url_user_write_contrib, auth=user.auth) + assert res.status_code == 204 - # self.project.reload() - # assert self.user_two not in self.project.contributors + project.reload() + assert user_write_contrib not in project.contributors # @assert_logs(NodeLog.CONTRIB_REMOVED, 'project') - # def test_remove_self_non_admin(self): - # self.project.add_contributor(self.user_three, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True) + def test_remove_self_non_admin(self, app, user_non_contrib, project, url_user_non_contrib): + with assert_latest_log(NodeLog.CONTRIB_REMOVED, project): + project.add_contributor(user_non_contrib, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True) - # # Disconnect contributor_removed so that we don't check in files - # # We can remove this when StoredFileNode is implemented in osf-models - # with disconnected_from_listeners(contributor_removed): - # res = self.app.delete(self.url_user_three, auth=self.user_three.auth) - # assert res.status_code == 204 + # Disconnect contributor_removed so that we don't check in files + # We can remove this when StoredFileNode is implemented in osf-models + with disconnected_from_listeners(contributor_removed): + res = app.delete(url_user_non_contrib, auth=user_non_contrib.auth) + assert res.status_code == 204 - # self.project.reload() - # assert self.user_three not in self.project.contributors + project.reload() + assert user_non_contrib not in project.contributors # @assert_logs(NodeLog.CONTRIB_REMOVED, 'project') - # def test_remove_self_contributor_not_unique_admin(self): - # self.project.add_permission(self.user_two, permissions.ADMIN, save=True) - # # Disconnect contributor_removed so that we don't check in files - # # We can remove this when StoredFileNode is implemented in osf-models - # with disconnected_from_listeners(contributor_removed): - # res = self.app.delete(self.url_user, auth=self.user.auth) - # assert res.status_code == 204 - - # self.project.reload() - # assert self.user not in self.project.contributors + def test_remove_self_contributor_not_unique_admin(self, app, user, user_write_contrib, project, url_user): + with assert_latest_log(NodeLog.CONTRIB_REMOVED, project): + project.add_permission(user_write_contrib, permissions.ADMIN, save=True) + # Disconnect contributor_removed so that we don't check in files + # We can remove this when StoredFileNode is implemented in osf-models + with disconnected_from_listeners(contributor_removed): + res = app.delete(url_user, auth=user.auth) + assert res.status_code == 204 + + project.reload() + assert user not in project.contributors # @assert_logs(NodeLog.CONTRIB_REMOVED, 'project') - # def test_can_remove_self_as_contributor_not_unique_admin(self): - # self.project.add_permission(self.user_two, permissions.ADMIN, save=True) - # # Disconnect contributor_removed so that we don't check in files - # # We can remove this when StoredFileNode is implemented in osf-models - # with disconnected_from_listeners(contributor_removed): - # res = self.app.delete(self.url_user_two, auth=self.user_two.auth) - # assert res.status_code == 204 - - # self.project.reload() - # assert self.user_two not in self.project.contributors + def test_can_remove_self_as_contributor_not_unique_admin(self, app, user_write_contrib, project, url_user_write_contrib): + with assert_latest_log(NodeLog.CONTRIB_REMOVED, project): + project.add_permission(user_write_contrib, permissions.ADMIN, save=True) + # Disconnect contributor_removed so that we don't check in files + # We can remove this when StoredFileNode is implemented in osf-models + with disconnected_from_listeners(contributor_removed): + res = app.delete(url_user_write_contrib, auth=user_write_contrib.auth) + assert res.status_code == 204 + + project.reload() + assert user_write_contrib not in project.contributors diff --git a/tests/utils.py b/tests/utils.py index 8c6387e4bd2..56a79aa5215 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -80,6 +80,16 @@ def assert_latest_log(log_action, node_key, index=0): assert last_log._id != new_log._id assert new_log.action == log_action +@contextlib.contextmanager +def assert_latest_log_not(log_action, node_key, index=0): + node = node_key + last_log = node.logs.latest() + node.reload() + yield + new_log = node.logs.order_by('-date')[index] + assert new_log.action != log_action + assert last_log._id == new_log._id + @contextlib.contextmanager def mock_archive(project, schema=None, auth=None, data=None, parent=None, embargo=False, embargo_end_date=None, From d2e32893d0a7890d7b8a888341eaf0df71ff8bec Mon Sep 17 00:00:00 2001 From: Rheisen Dennis Date: Tue, 11 Jul 2017 11:10:13 -0400 Subject: [PATCH 28/62] rename fixtures, change comment format, small code readability improvements --- .../nodes/views/test_node_comments_list.py | 109 +++++++++--------- .../views/test_node_contributors_detail.py | 8 +- 2 files changed, 55 insertions(+), 62 deletions(-) diff --git a/api_tests/nodes/views/test_node_comments_list.py b/api_tests/nodes/views/test_node_comments_list.py index 59c59a3447d..8f7c18d4a3d 100644 --- a/api_tests/nodes/views/test_node_comments_list.py +++ b/api_tests/nodes/views/test_node_comments_list.py @@ -29,80 +29,80 @@ def user_non_contrib(self): return AuthUserFactory() @pytest.fixture() - def project_private(self): + def project_private_dict(self): raise NotImplementedError @pytest.fixture() - def project_public(self): + def project_public_dict(self): raise NotImplementedError @pytest.fixture() - def registration(self): + def registration_dict(self): raise NotImplementedError - def test_return_comments(self, app, user, user_non_contrib, project_public, project_private, registration): + def test_return_comments(self, app, user, user_non_contrib, project_public_dict, project_private_dict, registration_dict): # test_return_public_node_comments_logged_out_user - res = app.get(project_public['url']) + res = app.get(project_public_dict['url']) assert res.status_code == 200 comment_json = res.json['data'] comment_ids = [comment['id'] for comment in comment_json] assert len(comment_json) == 1 - assert project_public['comment']._id in comment_ids + assert project_public_dict['comment']._id in comment_ids # test_return_public_node_comments_logged_in_user - res = app.get(project_public['url'], auth=user_non_contrib) + res = app.get(project_public_dict['url'], auth=user_non_contrib) assert res.status_code == 200 comment_json = res.json['data'] comment_ids = [comment['id'] for comment in comment_json] assert len(comment_json) == 1 - assert project_public['comment']._id in comment_ids + assert project_public_dict['comment']._id in comment_ids # test_return_private_node_comments_logged_out_user - res = app.get(project_private['url'], expect_errors=True) + res = app.get(project_private_dict['url'], expect_errors=True) assert res.status_code == 401 assert res.json['errors'][0]['detail'] == exceptions.NotAuthenticated.default_detail # test_return_private_node_comments_logged_in_non_contributor - res = app.get(project_private['url'], auth=user_non_contrib, expect_errors=True) + res = app.get(project_private_dict['url'], auth=user_non_contrib, expect_errors=True) assert res.status_code == 401 assert res.json['errors'][0]['detail'] == exceptions.NotAuthenticated.default_detail # test_return_private_node_comments_logged_in_contributor - res = app.get(project_private['url'], auth=user.auth) + res = app.get(project_private_dict['url'], auth=user.auth) assert res.status_code == 200 comment_json = res.json['data'] comment_ids = [comment['id'] for comment in comment_json] assert len(comment_json) == 1 - assert project_private['comment']._id in comment_ids + assert project_private_dict['comment']._id in comment_ids # test_return_registration_comments_logged_in_contributor - res = app.get(registration['url'], auth=user.auth) + res = app.get(registration_dict['url'], auth=user.auth) assert res.status_code == 200 comment_json = res.json['data'] comment_ids = [comment['id'] for comment in comment_json] assert len(comment_json) == 1 - assert registration['comment']._id in comment_ids + assert registration_dict['comment']._id in comment_ids - def test_return_both_deleted_and_undeleted_comments(self, app, user, project_private, mock_update_search=None): - deleted_comment = CommentFactory(node=project_private['project'], user=user, target=project_private['comment'].target, is_deleted=True) - res = app.get(project_private['url'], auth=user.auth) + def test_return_both_deleted_and_undeleted_comments(self, app, user, project_private_dict, mock_update_search=None): + deleted_comment = CommentFactory(node=project_private_dict['project'], user=user, target=project_private_dict['comment'].target, is_deleted=True) + res = app.get(project_private_dict['url'], auth=user.auth) assert res.status_code == 200 comment_json = res.json['data'] comment_ids = [comment['id'] for comment in comment_json] - assert project_private['comment']._id in comment_ids + assert project_private_dict['comment']._id in comment_ids assert deleted_comment._id in comment_ids - def test_node_comments_pagination(self, app, user, project_public): + def test_node_comments_pagination(self, app, user, project_public_dict): # test_node_comments_list_pagination - url = '{}?filter[target]={}&related_counts=False'.format(project_public['url'], project_public['project']._id) + url = '{}?filter[target]={}&related_counts=False'.format(project_public_dict['url'], project_public_dict['project']._id) res = app.get(url, user=user, auth=user.auth) assert res.status_code == 200 assert res.json['links']['meta']['unread'] == 0 # test_node_comments_list_updated_pagination - url = '{}?filter[target]={}&related_counts=False&version=2.1'.format(project_public['url'], project_public['project']._id) + url = '{}?filter[target]={}&related_counts=False&version=2.1'.format(project_public_dict['url'], project_public_dict['project']._id) res = app.get(url, user=user, auth=user.auth) assert res.status_code == 200 assert res.json['meta']['unread'] == 0 @@ -112,21 +112,21 @@ def test_node_comments_pagination(self, app, user, project_public): class TestNodeCommentsList(NodeCommentsListMixin): @pytest.fixture() - def project_private(self, user): + def project_private_dict(self, user): project_private = ProjectFactory(is_public=False, creator=user) comment_private = CommentFactory(node=project_private, user=user) url_private = '/{}nodes/{}/comments/'.format(API_BASE, project_private._id) return {'project': project_private, 'comment': comment_private, 'url': url_private} @pytest.fixture() - def project_public(self, user): + def project_public_dict(self, user): project_public = ProjectFactory(is_public=True, creator=user) comment_public = CommentFactory(node=project_public, user=user) url_public = '/{}nodes/{}/comments/'.format(API_BASE, project_public._id) return {'project': project_public, 'comment': comment_public, 'url': url_public} @pytest.fixture() - def registration(self, user): + def registration_dict(self, user): registration = RegistrationFactory(creator=user) comment_registration = CommentFactory(node=registration, user=user) url_registration = '/{}registrations/{}/comments/'.format(API_BASE, registration._id) @@ -137,15 +137,15 @@ def registration(self, user): class TestNodeCommentsListFiles(NodeCommentsListMixin): @pytest.fixture() - def project_private(self, user): + def project_private_dict(self, user): project_private = ProjectFactory(is_public=False, creator=user) - file = test_utils.create_test_file(project_private, user) - comment_private = CommentFactory(node=project_private, user=user, target=file.get_guid(), page='files') + file_private = test_utils.create_test_file(project_private, user) + comment_private = CommentFactory(node=project_private, user=user, target=file_private.get_guid(), page='files') url_private = '/{}nodes/{}/comments/'.format(API_BASE, project_private._id) - return {'project': project_private, 'file': file, 'comment': comment_private, 'url': url_private} + return {'project': project_private, 'file': file_private, 'comment': comment_private, 'url': url_private} @pytest.fixture() - def project_public(self, user): + def project_public_dict(self, user): project_public = ProjectFactory(is_public=True, creator=user) file_public = test_utils.create_test_file(project_public, user) comment_public = CommentFactory(node=project_public, user=user, target=file_public.get_guid(), page='files') @@ -153,31 +153,31 @@ def project_public(self, user): return {'project': project_public, 'file': file_public, 'comment': comment_public, 'url': url_public} @pytest.fixture() - def registration(self, user): + def registration_dict(self, user): registration = RegistrationFactory(creator=user) file_registration = test_utils.create_test_file(registration, user) comment_registration = CommentFactory(node=registration, user=user, target=file_registration.get_guid(), page='files') url_registration = '/{}registrations/{}/comments/'.format(API_BASE, registration._id) return {'registration': registration, 'file': file_registration, 'comment': comment_registration, 'url': url_registration} - def test_comments_on_deleted_files_are_not_returned(self, app, user, project_private): + def test_comments_on_deleted_files_are_not_returned(self, app, user, project_private_dict): # Delete commented file - osfstorage = project_private['project'].get_addon('osfstorage') + osfstorage = project_private_dict['project'].get_addon('osfstorage') root_node = osfstorage.get_root() - # root_node.delete(project_private['file']) - project_private['file'].delete(user=user) - res = app.get(project_private['url'], auth=user.auth) + # root_node.delete(project_private_dict['file']) + project_private_dict['file'].delete(user=user) + res = app.get(project_private_dict['url'], auth=user.auth) assert res.status_code == 200 comment_json = res.json['data'] comment_ids = [comment['id'] for comment in comment_json] - assert project_private['comment']._id not in comment_ids + assert project_private_dict['comment']._id not in comment_ids @pytest.mark.django_db class TestNodeCommentsListWiki(NodeCommentsListMixin): @pytest.fixture() - def project_private(self, user): + def project_private_dict(self, user): project_private = ProjectFactory(is_public=False, creator=user) wiki_private = NodeWikiFactory(node=project_private, user=user) comment_private = CommentFactory(node=project_private, user=user, target=Guid.load(wiki_private._id), page='wiki') @@ -185,7 +185,7 @@ def project_private(self, user): return {'project': project_private, 'wiki': wiki_private, 'comment': comment_private, 'url': url_private} @pytest.fixture() - def project_public(self, user): + def project_public_dict(self, user): project_public = ProjectFactory(is_public=True, creator=user) wiki_public = NodeWikiFactory(node=project_public, user=user) comment_public = CommentFactory(node=project_public, user=user, target=Guid.load(wiki_public._id), page='wiki') @@ -193,21 +193,21 @@ def project_public(self, user): return {'project': project_public, 'wiki': wiki_public, 'comment': comment_public, 'url': url_public} @pytest.fixture() - def registration(self, user): + def registration_dict(self, user): registration = RegistrationFactory(creator=user) wiki_registration = NodeWikiFactory(node=registration, user=user) comment_registration = CommentFactory(node=registration, user=user, target=Guid.load(wiki_registration._id), page='wiki') url_registration = '/{}registrations/{}/comments/'.format(API_BASE, registration._id) return {'registration': registration, 'wiki': wiki_registration, 'comment': comment_registration, 'url': url_registration} - def test_comments_on_deleted_wikis_are_not_returned(self, app, user, project_private, mock_update_search=None): + def test_comments_on_deleted_wikis_are_not_returned(self, app, user, project_private_dict, mock_update_search=None): # Delete wiki - project_private['project'].delete_node_wiki(project_private['wiki'].page_name, core.Auth(user)) - res = app.get(project_private['url'], auth=user.auth) + project_private_dict['project'].delete_node_wiki(project_private_dict['wiki'].page_name, core.Auth(user)) + res = app.get(project_private_dict['url'], auth=user.auth) assert res.status_code == 200 comment_json = res.json['data'] comment_ids = [comment['id'] for comment in comment_json] - assert project_private['comment']._id not in comment_ids + assert project_private_dict['comment']._id not in comment_ids @pytest.mark.django_db class NodeCommentsCreateMixin(object): @@ -267,67 +267,62 @@ def test_node_comments(self, app, user, user_read_contrib, user_non_contrib, pro assert res.json['errors'][0]['detail'] == exceptions.NotAuthenticated.default_detail # test_private_node_with_public_comment_level_admin_can_comment - """ Test admin contributors can still comment on a private project with comment_level == 'public' """ + # Test admin contributors can still comment on a private project with comment_level == 'public' project_dict = project_private_comment_public res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user.auth) assert res.status_code == 201 assert res.json['data']['attributes']['content'] == project_dict['payload']['data']['attributes']['content'] # test_private_node_with_public_comment_level_read_only_contributor_can_comment - """ Test read-only contributors can still comment on a private project with comment_level == 'public' """ + # Test read-only contributors can still comment on a private project with comment_level == 'public' project_dict = project_private_comment_public res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user_read_contrib.auth) assert res.status_code == 201 assert res.json['data']['attributes']['content'] == project_dict['payload']['data']['attributes']['content'] # test_private_node_with_public_comment_level_non_contributor_cannot_comment - """ Test non-contributors cannot comment on a private project with comment_level == 'public' """ + # Test non-contributors cannot comment on a private project with comment_level == 'public' project_dict = project_private_comment_public res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user_non_contrib.auth, expect_errors=True) assert res.status_code == 403 # test_private_node_with_public_comment_level_logged_out_user_cannot_comment - """ Test logged out users cannot comment on a private project with comment_level == 'public' """ + # Test logged out users cannot comment on a private project with comment_level == 'public' project_dict = project_private_comment_public res = app.post_json_api(project_dict['url'], project_dict['payload'], expect_errors=True) assert res.status_code == 401 assert res.json['errors'][0]['detail'] == exceptions.NotAuthenticated.default_detail # test_public_project_with_public_comment_level_admin_can_comment - """ Test admin contributor can still comment on a public project when it is - configured so any logged-in user can comment (comment_level == 'public') """ + # Test admin contributor can still comment on a public project when it is configured so any logged-in user can comment (comment_level == 'public') project_dict = project_public_comment_public res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user.auth) assert res.status_code == 201 assert res.json['data']['attributes']['content'] == project_dict['payload']['data']['attributes']['content'] # test_public_project_with_public_comment_level_read_only_contributor_can_comment - """ Test read-only contributor can still comment on a public project when it is - configured so any logged-in user can comment (comment_level == 'public') """ + # Test read-only contributor can still comment on a public project when it is configured so any logged-in user can comment (comment_level == 'public') project_dict = project_public_comment_public res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user_read_contrib.auth) assert res.status_code == 201 assert res.json['data']['attributes']['content'] == project_dict['payload']['data']['attributes']['content'] # test_public_project_with_public_comment_level_non_contributor_can_comment - """ Test non-contributors can comment on a public project when it is - configured so any logged-in user can comment (comment_level == 'public') """ + # Test non-contributors can comment on a public project when it is configured so any logged-in user can comment (comment_level == 'public') project_dict = project_public_comment_public res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user_non_contrib.auth) assert res.status_code == 201 assert res.json['data']['attributes']['content'] == project_dict['payload']['data']['attributes']['content'] # test_public_project_with_public_comment_level_logged_out_user_cannot_comment - """ Test logged out users cannot comment on a public project when it is - configured so any logged-in user can comment (comment_level == 'public') """ + # Test logged out users cannot comment on a public project when it is configured so any logged-in user can comment (comment_level == 'public') project_dict = project_public_comment_public res = app.post_json_api(project_dict['url'], project_dict['payload'], expect_errors=True) assert res.status_code == 401 assert res.json['errors'][0]['detail'] == exceptions.NotAuthenticated.default_detail # test_public_node_private_comment_level_admin_can_comment - """ Test only contributors can comment on a public project when it is - configured so only contributors can comment (comment_level == 'private') """ + # Test only contributors can comment on a public project when it is configured so only contributors can comment (comment_level == 'private') project_dict = project_public_comment_private res = app.post_json_api(project_dict['url'], project_dict['payload'], auth=user.auth) assert res.status_code == 201 diff --git a/api_tests/nodes/views/test_node_contributors_detail.py b/api_tests/nodes/views/test_node_contributors_detail.py index 710e4f3bc89..bf221255cfa 100644 --- a/api_tests/nodes/views/test_node_contributors_detail.py +++ b/api_tests/nodes/views/test_node_contributors_detail.py @@ -138,15 +138,13 @@ class TestNodeContributorOrdering: @pytest.fixture() def contribs(self, user): - contribs = [AuthUserFactory() for number in range(1, 10)] - contribs.insert(0, user) - return contribs + return [user] + [AuthUserFactory() for _ in range(9)] @pytest.fixture() def project(self, user, contribs): project = ProjectFactory(creator=user) for contrib in contribs: - if contrib._id is not user._id: + if contrib._id != user._id: project.add_contributor( contrib, permissions=[permissions.READ, permissions.WRITE], @@ -184,7 +182,7 @@ def test_initial_order(self, app, user, contribs, project, contrib_user_id): assert res.status_code == 200 contributor_list = res.json['data'] found_contributors = False - for i in range(0, len(contribs)): + for i in range(len(contribs)): assert contribs[i]._id == contrib_user_id(contributor_list[i]) assert i == contributor_list[i]['attributes']['index'] found_contributors = True From 7cd88c657bcf3d639fd7fe12f9b7f6af62fd5b4d Mon Sep 17 00:00:00 2001 From: Rheisen Dennis Date: Wed, 12 Jul 2017 11:33:26 -0400 Subject: [PATCH 29/62] remove parametrize and comment_level fixture --- .../views/test_comment_report_list.py | 35 +++++++------------ 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/api_tests/comments/views/test_comment_report_list.py b/api_tests/comments/views/test_comment_report_list.py index c3ff0583865..9580eb7b852 100644 --- a/api_tests/comments/views/test_comment_report_list.py +++ b/api_tests/comments/views/test_comment_report_list.py @@ -142,9 +142,11 @@ def test_public_node_non_contrib_reporter_can_view_own_report(self, app, non_con assert len(report_json) == 1 assert non_contrib._id in report_ids - @pytest.mark.parametrize('comment_level', ['private']) - def test_public_node_private_comment_level_non_contrib_cannot_see_reports(self, app, non_contrib, public_url, comment_level): + def test_public_node_private_comment_level_non_contrib_cannot_see_reports(self, app, non_contrib, public_project, public_url): + public_project.comment_level = 'private' + public_project.save() res = app.get(public_url, auth=non_contrib.auth, expect_errors=True) + print res assert res.status_code == 403 assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail @@ -260,8 +262,9 @@ def test_public_node_report_comment_auth_misc(self, app, user, contributor, non_ assert res.status_code == 201 assert res.json['data']['id'] == non_contrib._id - @pytest.mark.parametrize('comment_level', ['private']) - def test_public_node_private_comment_level_non_contrib_cannot_report_comment(self, app, non_contrib, comment_level, public_url): + def test_public_node_private_comment_level_non_contrib_cannot_report_comment(self, app, non_contrib, public_project, public_url): + public_project.comment_level = 'private' + public_project.save() res = app.get(public_url, auth=non_contrib.auth, expect_errors=True) assert res.status_code == 403 assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail @@ -293,8 +296,8 @@ def private_url(self, user, comment): # public_project_comment_reports @pytest.fixture() - def public_project(self, user, contributor, comment_level): - public_project = ProjectFactory.create(is_public=True, creator=user, comment_level=comment_level) + def public_project(self, user, contributor): + public_project = ProjectFactory.create(is_public=True, creator=user, comment_level='public') public_project.add_contributor(contributor=contributor, save=True) return public_project @@ -315,10 +318,6 @@ def public_comment(self, user, contributor, public_project): def public_url(self, user, public_comment): return '/{}comments/{}/reports/'.format(API_BASE, public_comment._id) - @pytest.fixture() - def comment_level(self): - return 'public' - class TestWikiCommentReportsView(CommentReportsMixin): # private_project_comment_reports @@ -352,8 +351,8 @@ def private_url(self, user, comment): # public_project_comment_reports @pytest.fixture() - def public_project(self, user, contributor, comment_level): - public_project = ProjectFactory.create(is_public=True, creator=user, comment_level=comment_level) + def public_project(self, user, contributor): + public_project = ProjectFactory.create(is_public=True, creator=user, comment_level='public') public_project.add_contributor(contributor=contributor, save=True) return public_project @@ -379,10 +378,6 @@ def public_comment(self, user, contributor, public_project, public_wiki): def public_url(self, user, public_comment): return '/{}comments/{}/reports/'.format(API_BASE, public_comment._id) - @pytest.fixture() - def comment_level(self): - return 'public' - class TestFileCommentReportsView(CommentReportsMixin): # private_project_comment_reports @@ -415,8 +410,8 @@ def private_url(self, user, comment): # public_project_comment_reports @pytest.fixture() - def public_project(self, user, contributor, comment_level): - public_project = ProjectFactory.create(is_public=True, creator=user, comment_level=comment_level) + def public_project(self, user, contributor): + public_project = ProjectFactory.create(is_public=True, creator=user, comment_level='public') public_project.add_contributor(contributor=contributor, save=True) return public_project @@ -440,7 +435,3 @@ def public_comment(self, user, contributor, public_project, public_file): @pytest.fixture() def public_url(self, user, public_comment): return '/{}comments/{}/reports/'.format(API_BASE, public_comment._id) - - @pytest.fixture() - def comment_level(self): - return 'public' From 0710716a61fea1b51001e67a61b966804f25aed3 Mon Sep 17 00:00:00 2001 From: Steven Loria Date: Thu, 13 Jul 2017 15:05:43 -0400 Subject: [PATCH 30/62] Revert "Revert "SHARE subject serialization [OSF-8227]"" --- api/preprints/serializers.py | 5 +++-- osf/models/preprint_service.py | 9 +++++---- tests/test_preprints.py | 28 ++++++++++++++++++---------- website/preprints/tasks.py | 26 ++++++++++++++++++-------- website/util/share.py | 17 +++++++++++++++++ 5 files changed, 61 insertions(+), 24 deletions(-) diff --git a/api/preprints/serializers.py b/api/preprints/serializers.py index 63c4560b79f..99c9137899c 100644 --- a/api/preprints/serializers.py +++ b/api/preprints/serializers.py @@ -209,7 +209,7 @@ def update(self, preprint, validated_data): def set_field(self, func, val, auth, save=False): try: - func(val, auth, save=save) + func(val, auth) except PermissionsError as e: raise exceptions.PermissionDenied(detail=e.message) except ValueError as e: @@ -246,7 +246,8 @@ def create(self, validated_data): raise Conflict('Only one preprint per provider can be submitted for a node. Check `meta[existing_resource_id]`.', meta={'existing_resource_id': conflict._id}) preprint = PreprintService(node=node, provider=provider) - self.set_field(preprint.set_primary_file, primary_file, auth, save=True) + self.set_field(preprint.set_primary_file, primary_file, auth) + preprint.save() preprint.node._has_abandoned_preprint = True preprint.node.save() diff --git a/osf/models/preprint_service.py b/osf/models/preprint_service.py index 5c33f3382f4..4035ecf1305 100644 --- a/osf/models/preprint_service.py +++ b/osf/models/preprint_service.py @@ -115,10 +115,11 @@ def get_subjects(self): ret.append(subj_hierarchy) return ret - def set_subjects(self, preprint_subjects, auth, save=False): + def set_subjects(self, preprint_subjects, auth): if not self.node.has_permission(auth.user, ADMIN): raise PermissionsError('Only admins can change a preprint\'s subjects.') + old_subjects = list(self.subjects.values_list('id', flat=True)) self.subjects.clear() for subj_list in preprint_subjects: subj_hierarchy = [] @@ -129,8 +130,7 @@ def set_subjects(self, preprint_subjects, auth, save=False): for s_id in subj_hierarchy: self.subjects.add(Subject.load(s_id)) - if save: - self.save() + self.save(old_subjects=old_subjects) def set_primary_file(self, preprint_file, auth, save=False): if not self.node.has_permission(auth.user, ADMIN): @@ -226,8 +226,9 @@ def set_identifier_values(self, doi, ark, save=False): def save(self, *args, **kwargs): first_save = not bool(self.pk) saved_fields = self.get_dirty_fields() or [] + old_subjects = kwargs.pop('old_subjects', []) ret = super(PreprintService, self).save(*args, **kwargs) if (not first_save and 'is_published' in saved_fields) or self.is_published: - enqueue_task(on_preprint_updated.s(self._id)) + enqueue_task(on_preprint_updated.s(self._id, old_subjects)) return ret diff --git a/tests/test_preprints.py b/tests/test_preprints.py index 3e18d3a778f..9fb3c6da209 100644 --- a/tests/test_preprints.py +++ b/tests/test_preprints.py @@ -85,7 +85,7 @@ def test_is_preprint_property_new_file_to_published(self): with assert_raises(ValueError): self.preprint.set_published(True, auth=self.auth, save=True) self.preprint.provider = PreprintProviderFactory() - self.preprint.set_subjects([[SubjectFactory()._id]], auth=self.auth, save=True) + self.preprint.set_subjects([[SubjectFactory()._id]], auth=self.auth) self.project.reload() assert_false(self.project.is_preprint) self.preprint.set_published(True, auth=self.auth, save=True) @@ -100,7 +100,7 @@ def test_project_made_public(self): with assert_raises(ValueError): self.preprint.set_published(True, auth=self.auth, save=True) self.preprint.provider = PreprintProviderFactory() - self.preprint.set_subjects([[SubjectFactory()._id]], auth=self.auth, save=True) + self.preprint.set_subjects([[SubjectFactory()._id]], auth=self.auth) self.project.reload() assert_false(self.project.is_public) self.preprint.set_published(True, auth=self.auth, save=True) @@ -160,7 +160,7 @@ def setUp(self): def test_nonadmin_cannot_set_subjects(self): initial_subjects = list(self.preprint.subjects.all()) with assert_raises(PermissionsError): - self.preprint.set_subjects([[SubjectFactory()._id]], auth=Auth(self.write_contrib), save=True) + self.preprint.set_subjects([[SubjectFactory()._id]], auth=Auth(self.write_contrib)) self.preprint.reload() assert_equal(initial_subjects, list(self.preprint.subjects.all())) @@ -191,7 +191,7 @@ def test_nonadmin_cannot_publish(self): def test_admin_can_set_subjects(self): initial_subjects = list(self.preprint.subjects.all()) - self.preprint.set_subjects([[SubjectFactory()._id]], auth=Auth(self.user), save=True) + self.preprint.set_subjects([[SubjectFactory()._id]], auth=Auth(self.user)) self.preprint.reload() assert_not_equal(initial_subjects, list(self.preprint.subjects.all())) @@ -355,7 +355,7 @@ def setUp(self): self.preprint.node.creator.suffix = '' self.preprint.node.creator.save() - self.preprint.set_subjects([[SubjectFactory()._id]], auth=Auth(self.preprint.node.creator), save=False) + self.preprint.set_subjects([[SubjectFactory()._id]], auth=Auth(self.preprint.node.creator)) def tearDown(self): handlers.celery_before_request() @@ -381,8 +381,16 @@ def test_format_preprint(self): subjects = [nodes.pop(k) for k, v in nodes.items() if v['@type'] == 'subject'] through_subjects = [nodes.pop(k) for k, v in nodes.items() if v['@type'] == 'throughsubjects'] - assert sorted(subject['@id'] for subject in subjects) == sorted(tt['subject']['@id'] for tt in through_subjects) - assert sorted(subject['name'] for subject in subjects) == [s.bepress_text for h in self.preprint.subject_hierarchy for s in h] + s_ids = [s['@id'] for s in subjects] + ts_ids = [ts['subject']['@id'] for ts in through_subjects] + cs_ids = [i for i in set(s.get('central_synonym', {}).get('@id') for s in subjects) if i] + for ts in ts_ids: + assert ts in s_ids + assert ts not in cs_ids # Only aliased subjects are connected to self.preprint + for s in subjects: + subject = Subject.objects.get(text=s['name']) + assert s['uri'].endswith('v2/taxonomies/{}/'.format(subject._id)) # This cannot change + assert set(subject['name'] for subject in subjects) == set([s.text for s in self.preprint.subjects.all()] + [s.bepress_subject.text for s in self.preprint.subjects.filter(bepress_subject__isnull=False)]) people = sorted([nodes.pop(k) for k, v in nodes.items() if v['@type'] == 'person'], key=lambda x: x['given_name']) expected_people = sorted([{ @@ -458,7 +466,7 @@ def test_format_preprint_nones(self): self.preprint.node.tags = [] self.preprint.date_published = None self.preprint.node.preprint_article_doi = None - self.preprint.set_subjects([], auth=Auth(self.preprint.node.creator), save=False) + self.preprint.set_subjects([], auth=Auth(self.preprint.node.creator)) res = format_preprint(self.preprint) @@ -609,12 +617,12 @@ def test_save_published_called(self, mock_on_preprint_updated): @mock.patch('website.preprints.tasks.on_preprint_updated.s') def test_save_published_subject_change_called(self, mock_on_preprint_updated): self.preprint.is_published = True - self.preprint.set_subjects([[self.subject_two._id]], auth=self.auth, save=True) + self.preprint.set_subjects([[self.subject_two._id]], auth=self.auth) assert mock_on_preprint_updated.called @mock.patch('website.preprints.tasks.on_preprint_updated.s') def test_save_unpublished_subject_change_not_called(self, mock_on_preprint_updated): - self.preprint.set_subjects([[self.subject_two._id]], auth=self.auth, save=True) + self.preprint.set_subjects([[self.subject_two._id]], auth=self.auth) assert not mock_on_preprint_updated.called @mock.patch('website.preprints.tasks.requests') diff --git a/website/preprints/tasks.py b/website/preprints/tasks.py index d3671fa36f1..6722d32394c 100644 --- a/website/preprints/tasks.py +++ b/website/preprints/tasks.py @@ -8,7 +8,7 @@ from framework import sentry from website import settings -from website.util.share import GraphNode, format_contributor +from website.util.share import GraphNode, format_contributor, format_subject from website.identifiers.utils import request_identifiers_from_ezid, get_ezid_client, build_ezid_metadata, parse_identifiers @@ -16,12 +16,13 @@ @celery_app.task(ignore_results=True) -def on_preprint_updated(preprint_id, update_share=True): +def on_preprint_updated(preprint_id, update_share=True, old_subjects=None): # WARNING: Only perform Read-Only operations in an asynchronous task, until Repeatable Read/Serializable # transactions are implemented in View and Task application layers. from osf.models import PreprintService preprint = PreprintService.load(preprint_id) - + if old_subjects is None: + old_subjects = [] if preprint.node: status = 'public' if preprint.node.is_public else 'unavailable' try: @@ -39,14 +40,18 @@ def on_preprint_updated(preprint_id, update_share=True): 'attributes': { 'tasks': [], 'raw': None, - 'data': {'@graph': format_preprint(preprint)} + 'data': {'@graph': format_preprint(preprint, old_subjects)} } } }, headers={'Authorization': 'Bearer {}'.format(preprint.provider.access_token), 'Content-Type': 'application/vnd.api+json'}) logger.debug(resp.content) resp.raise_for_status() -def format_preprint(preprint): +def format_preprint(preprint, old_subjects=None): + if old_subjects is None: + old_subjects = [] + from osf.models import Subject + old_subjects = [Subject.objects.get(id=s) for s in old_subjects] preprint_graph = GraphNode('preprint', **{ 'title': preprint.node.title, 'description': preprint.node.description or '', @@ -83,10 +88,15 @@ def format_preprint(preprint): for tag in preprint.node.tags.values_list('name', flat=True) if tag ] - preprint_graph.attrs['subjects'] = [ - GraphNode('throughsubjects', creative_work=preprint_graph, subject=GraphNode('subject', name=subject)) - for subject in set(s.bepress_text for s in preprint.subjects.all()) + current_subjects = [ + GraphNode('throughsubjects', creative_work=preprint_graph, subject=format_subject(s)) + for s in preprint.subjects.all() + ] + deleted_subjects = [ + GraphNode('throughsubjects', creative_work=preprint_graph, is_deleted=True, subject=format_subject(s)) + for s in old_subjects if not preprint.subjects.filter(id=s.id).exists() ] + preprint_graph.attrs['subjects'] = current_subjects + deleted_subjects to_visit.extend(format_contributor(preprint_graph, user, preprint.node.get_visible(user), i) for i, user in enumerate(preprint.node.contributors)) to_visit.extend(GraphNode('AgentWorkRelation', creative_work=preprint_graph, agent=GraphNode('institution', name=institution)) diff --git a/website/util/share.py b/website/util/share.py index ee56315b8a5..1ecb39b7759 100644 --- a/website/util/share.py +++ b/website/util/share.py @@ -67,3 +67,20 @@ def format_contributor(preprint, user, bibliographic, index): creative_work=preprint, cited_as=user.fullname, ) + +def format_subject(subject, context=None): + if context is None: + context = {} + if subject is None: + return None + if subject.id in context: + return context[subject.id] + context[subject.id] = GraphNode( + 'subject', + name=subject.text, + is_deleted=False, + uri=subject.absolute_api_v2_url, + ) + context[subject.id].attrs['parent'] = format_subject(subject.parent, context) + context[subject.id].attrs['central_synonym'] = format_subject(subject.bepress_subject, context) + return context[subject.id] From f1a6f9b255eebf6aee529de14a7578cfd70d3f06 Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Thu, 13 Jul 2017 16:26:42 -0400 Subject: [PATCH 31/62] Fix namings, get rid of fixture]s --- .../licenses/views/test_license_detail.py | 21 +++++-------------- api_tests/licenses/views/test_license_list.py | 17 ++++----------- 2 files changed, 9 insertions(+), 29 deletions(-) diff --git a/api_tests/licenses/views/test_license_detail.py b/api_tests/licenses/views/test_license_detail.py index 4d81c574261..865848ee5d1 100644 --- a/api_tests/licenses/views/test_license_detail.py +++ b/api_tests/licenses/views/test_license_detail.py @@ -6,23 +6,12 @@ @pytest.mark.django_db class TestLicenseDetail: - @pytest.fixture() - def license(self): - return NodeLicense.find()[0] - @pytest.fixture() - def url_license(self, license): - return '/{}licenses/{}/'.format(API_BASE, license._id) - - @pytest.fixture() - def res_license(self, app, url_license): - return app.get(url_license) - - @pytest.fixture() - def data_license(self, res_license): - return res_license.json['data'] - - def test_license_detail(self, license, res_license, data_license): + def test_license_detail(self, app): + license = NodeLicense.find()[0] + url_license = '/{}licenses/{}/'.format(API_BASE, license._id) + res_license = app.get(url_license) + data_license = res_license.json['data'] #test_license_detail_success(self, res_license): assert res_license.status_code == 200 diff --git a/api_tests/licenses/views/test_license_list.py b/api_tests/licenses/views/test_license_list.py index 0ceaaa54624..945e9eaebf4 100644 --- a/api_tests/licenses/views/test_license_list.py +++ b/api_tests/licenses/views/test_license_list.py @@ -6,20 +6,11 @@ @pytest.mark.django_db class TestLicenseList: - @pytest.fixture() - def licenses(self): - return NodeLicense.find() + def test_license_list(self, app): + licenses = NodeLicense.find() + url_licenses = '/{}licenses/'.format(API_BASE) + res_licenses = app.get(url_licenses) - @pytest.fixture() - def url_licenses(self): - return '/{}licenses/'.format(API_BASE) - - @pytest.fixture() - def res_licenses(self, app, url_licenses): - return app.get(url_licenses) - - - def test_license_list(self, licenses, app, url_licenses, res_licenses): #test_license_list_success assert res_licenses.status_code == 200 assert res_licenses.content_type == 'application/vnd.api+json' From f726101b39618bb0e7c72d471a8ac726642d0812 Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Thu, 13 Jul 2017 16:44:44 -0400 Subject: [PATCH 32/62] Remove unneeded protected mode on fixture, extra lines --- api_tests/guids/views/test_guid_detail.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/api_tests/guids/views/test_guid_detail.py b/api_tests/guids/views/test_guid_detail.py index f5f490b6017..def12c03f55 100644 --- a/api_tests/guids/views/test_guid_detail.py +++ b/api_tests/guids/views/test_guid_detail.py @@ -3,7 +3,6 @@ from addons.osfstorage.models import OsfStorageFile from addons.wiki.tests.factories import NodeWikiFactory from api.base.settings.defaults import API_BASE - from osf_tests.factories import ( AuthUserFactory, ProjectFactory, @@ -26,7 +25,7 @@ def project(self): return ProjectFactory() @pytest.fixture() - def _add_private_link(self, project): + def add_private_link(self, project): def private_link(anonymous=False): view_only_link = PrivateLinkFactory(anonymous=anonymous) view_only_link.nodes.add(project) @@ -92,10 +91,10 @@ def test_redirects(self, app, project, url_guids_detail, user): res = app.get(url, auth=user.auth, expect_errors=True) assert res.status_code == 404 - def test_redirects_through_view_only_link(self, app, project, _add_private_link, user): + def test_redirects_through_view_only_link(self, app, project, add_private_link, user): #test_redirect_when_viewing_private_project_through_view_only_link - view_only_link = _add_private_link() + view_only_link = add_private_link() url = '/{}guids/{}/?view_only={}'.format(API_BASE, project._id, view_only_link.key) res = app.get(url, auth=user.auth) redirect_url = '{}{}nodes/{}/?view_only={}'.format(API_DOMAIN, API_BASE, project._id, view_only_link.key) From e0469c64be1cf48834bc5d1caaab5b7d7fd18dea Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Fri, 14 Jul 2017 10:51:29 -0400 Subject: [PATCH 33/62] Fix imports list, use django Q object, remove unneeded fixtures --- .../views/test_institution_auth.py | 13 ++++++------ .../views/test_institution_detail.py | 20 ++++++------------- .../views/test_institution_list.py | 3 +-- .../views/test_institution_users_list.py | 19 ++++-------------- 4 files changed, 17 insertions(+), 38 deletions(-) diff --git a/api_tests/institutions/views/test_institution_auth.py b/api_tests/institutions/views/test_institution_auth.py index 157232d2673..9d4323a96f2 100644 --- a/api_tests/institutions/views/test_institution_auth.py +++ b/api_tests/institutions/views/test_institution_auth.py @@ -1,18 +1,17 @@ import pytest import json - import jwt import jwe -from modularodm import Q +from django.db.models import Q from api.base import settings from api.base.settings.defaults import API_BASE from framework.auth import signals +from osf.models import OSFUser as User from osf_tests.factories import ( InstitutionFactory, UserFactory, ) -from osf.models import OSFUser as User from tests.base import capture_signals @pytest.mark.django_db @@ -60,7 +59,7 @@ def payload(username, fullname='Fake User', given_name='', family_name=''): def test_creates_user(self, app, url_auth_institution, institution, make_payload): username = 'hmoco@circle.edu' - assert User.find(Q('username', 'eq', username)).count() == 0 + assert User.objects.filter(Q(username=username)).count() == 0 with capture_signals() as mock_signals: res = app.post(url_auth_institution, make_payload(username)) @@ -68,7 +67,7 @@ def test_creates_user(self, app, url_auth_institution, institution, make_payload assert res.status_code == 204 assert mock_signals.signals_sent() == set([signals.user_confirmed]) - user = User.find_one(Q('username', 'eq', username)) + user = User.objects.filter(Q(username=username)).get() assert user assert institution in user.affiliated_institutions.all() @@ -111,7 +110,7 @@ def test_user_names_guessed_if_not_provided(self, app, make_payload, url_auth_in res = app.post(url_auth_institution, make_payload(username)) assert res.status_code == 204 - user = User.find_one(Q('username', 'eq', username)) + user = User.objects.filter(Q(username=username)).get() assert user assert user.fullname == 'Fake User' @@ -124,7 +123,7 @@ def test_user_names_used_when_provided(self, app, url_auth_institution, make_pay res = app.post(url_auth_institution, make_payload(username, family_name='West', given_name='Kanye')) assert res.status_code == 204 - user = User.find_one(Q('username', 'eq', username)) + user = User.objects.filter(Q(username=username)).get() assert user assert user.fullname == 'Fake User' diff --git a/api_tests/institutions/views/test_institution_detail.py b/api_tests/institutions/views/test_institution_detail.py index cab7b62049b..2fc0fdd7ded 100644 --- a/api_tests/institutions/views/test_institution_detail.py +++ b/api_tests/institutions/views/test_institution_detail.py @@ -6,24 +6,16 @@ @pytest.mark.django_db class TestInstitutionDetail: - @pytest.fixture() - def institution(self): - return InstitutionFactory() + def test_detail_response(self, app): + institution = InstitutionFactory() - @pytest.fixture() - def url_institution(self): - def url(id): - return '/{}institutions/{}/'.format(API_BASE, id) - return url - - - def test_detail_response(self, app, institution, url_institution): #return_wrong_id - res = app.get(url_institution(id='1PO'), expect_errors=True) + url = '/{}institutions/{}/'.format(API_BASE, '1PO') + res = app.get(url, expect_errors=True) assert res.status_code == 404 #test_return_with_id - res = app.get(url_institution(id=institution._id)) - + url = '/{}institutions/{}/'.format(API_BASE, institution._id) + res = app.get(url) assert res.status_code == 200 assert res.json['data']['attributes']['name'] == institution.name diff --git a/api_tests/institutions/views/test_institution_list.py b/api_tests/institutions/views/test_institution_list.py index b9fe0e02f7a..b4ac959868e 100644 --- a/api_tests/institutions/views/test_institution_list.py +++ b/api_tests/institutions/views/test_institution_list.py @@ -1,9 +1,8 @@ import pytest from api.base.settings.defaults import API_BASE - -from osf_tests.factories import InstitutionFactory from osf.models import AbstractNode as Node +from osf_tests.factories import InstitutionFactory @pytest.mark.django_db class TestInstitutionList: diff --git a/api_tests/institutions/views/test_institution_users_list.py b/api_tests/institutions/views/test_institution_users_list.py index 9464beed897..1ef4c4923f3 100644 --- a/api_tests/institutions/views/test_institution_users_list.py +++ b/api_tests/institutions/views/test_institution_users_list.py @@ -9,30 +9,19 @@ @pytest.mark.django_db class TestInstitutionUsersList: - @pytest.fixture() - def institution(self): - return InstitutionFactory() + def test_return_all_users(self, app): + institution = InstitutionFactory() - @pytest.fixture() - def user_one(self, institution): user_one = UserFactory() user_one.affiliated_institutions.add(institution) user_one.save() - return user_one - @pytest.fixture() - def user_two(self, institution): user_two = UserFactory() user_two.affiliated_institutions.add(institution) user_two.save() - return user_two - @pytest.fixture() - def url_institution_user(self, institution): - return '/{0}institutions/{1}/users/'.format(API_BASE, institution._id) - - def test_return_all_users(self, app, institution, user_one, user_two, url_institution_user): - res = app.get(url_institution_user) + url = '/{0}institutions/{1}/users/'.format(API_BASE, institution._id) + res = app.get(url) assert res.status_code == 200 From 15cce09501262c8424eb721d4c11cc5473953dea Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Fri, 14 Jul 2017 11:56:57 -0400 Subject: [PATCH 34/62] Remove unneeded fixtures; fix imports listing --- .../views/test_metaschemas_detail.py | 28 ++++++++----------- .../views/test_metaschemas_list.py | 24 ++++++---------- 2 files changed, 20 insertions(+), 32 deletions(-) diff --git a/api_tests/metaschemas/views/test_metaschemas_detail.py b/api_tests/metaschemas/views/test_metaschemas_detail.py index 36d7c1cf24e..86150c15ed1 100644 --- a/api_tests/metaschemas/views/test_metaschemas_detail.py +++ b/api_tests/metaschemas/views/test_metaschemas_detail.py @@ -3,30 +3,24 @@ from api.base.settings.defaults import API_BASE from osf.models import MetaSchema from osf_tests.factories import ( - AuthUserFactory + AuthUserFactory, ) from website.project.metadata.schemas import LATEST_SCHEMA_VERSION -from website.project.model import Q @pytest.mark.django_db class TestMetaSchemaDetail: - @pytest.fixture() - def user(self): - return AuthUserFactory() + def test_metaschemas_detail_visibility(self, app): - @pytest.fixture() - def schema(self): - return MetaSchema.find_one(Q('name', 'eq', 'Prereg Challenge') & Q('schema_version', 'eq', LATEST_SCHEMA_VERSION)) + user = AuthUserFactory() + schema = MetaSchema.objects.filter(name='Prereg Challenge', schema_version=LATEST_SCHEMA_VERSION).first() - @pytest.fixture() - def url_metaschemas_detail(self, schema): - return '/{}metaschemas/{}/'.format(API_BASE, schema._id) - - def test_metaschemas_detail_visibility(self, app, schema, url_metaschemas_detail, user): + def url_metaschemas_detail(schema_id): + return '/{}metaschemas/{}/'.format(API_BASE, schema_id) #test_pass_authenticated_user_can_retrieve_schema - res = app.get(url_metaschemas_detail, auth=user.auth) + url = url_metaschemas_detail(schema._id) + res = app.get(url, auth=user.auth) assert res.status_code == 200 data = res.json['data']['attributes'] assert data['name'] == 'Prereg Challenge' @@ -35,12 +29,12 @@ def test_metaschemas_detail_visibility(self, app, schema, url_metaschemas_detail assert res.json['data']['id'] == schema._id #test_pass_unauthenticated_user_can_view_schemas - res = app.get(url_metaschemas_detail) + res = app.get(url) assert res.status_code == 200 #test_inactive_metaschema_returned inactive_schema = MetaSchema.objects.get(name='Election Research Preacceptance Competition', active=False) - url = '/{}metaschemas/{}/'.format(API_BASE, inactive_schema._id) + url = url_metaschemas_detail(inactive_schema._id) res = app.get(url) assert res.status_code == 200 assert res.json['data']['attributes']['name'] == 'Election Research Preacceptance Competition' @@ -48,7 +42,7 @@ def test_metaschemas_detail_visibility(self, app, schema, url_metaschemas_detail #test_non_latest_version_metaschema_returned old_schema = MetaSchema.objects.get(name='OSF-Standard Pre-Data Collection Registration', schema_version=1) - url = '/{}metaschemas/{}/'.format(API_BASE, old_schema._id) + url = url_metaschemas_detail(old_schema._id) res = app.get(url) assert res.status_code == 200 assert res.json['data']['attributes']['name'] == 'OSF-Standard Pre-Data Collection Registration' diff --git a/api_tests/metaschemas/views/test_metaschemas_list.py b/api_tests/metaschemas/views/test_metaschemas_list.py index 6b2b3ba3d94..f71e251c495 100644 --- a/api_tests/metaschemas/views/test_metaschemas_list.py +++ b/api_tests/metaschemas/views/test_metaschemas_list.py @@ -3,37 +3,31 @@ from api.base.settings.defaults import API_BASE from osf.models.metaschema import MetaSchema from osf_tests.factories import ( - AuthUserFactory + AuthUserFactory, ) from website.project.metadata.schemas import LATEST_SCHEMA_VERSION @pytest.mark.django_db class TestMetaSchemaList: - @pytest.fixture() - def user(self): - return AuthUserFactory() + def test_metaschemas_list_crud(self, app): - @pytest.fixture() - def url_metaschemas_list(self): - return '/{}metaschemas/'.format(API_BASE) + user = AuthUserFactory() + url= '/{}metaschemas/'.format(API_BASE) - def test_metaschemas_list_visibility_create_update(self, app, url_metaschemas_list, user): #test_pass_authenticated_user_can_view_schemas - res = app.get(url_metaschemas_list, auth=user.auth) + res = app.get(url, auth=user.auth) assert res.status_code == 200 - assert ( - len(res.json['data']) == - MetaSchema.objects.filter(active=True, schema_version=LATEST_SCHEMA_VERSION).count()) + assert (len(res.json['data']) == MetaSchema.objects.filter(active=True, schema_version=LATEST_SCHEMA_VERSION).count()) #test_cannot_update_metaschemas - res = app.put_json_api(url_metaschemas_list, auth=user.auth, expect_errors=True) + res = app.put_json_api(url, auth=user.auth, expect_errors=True) assert res.status_code == 405 #test_cannot_post_metaschemas - res = app.post_json_api(url_metaschemas_list, auth=user.auth, expect_errors=True) + res = app.post_json_api(url, auth=user.auth, expect_errors=True) assert res.status_code == 405 #test_pass_unauthenticated_user_can_view_schemas - res = app.get(url_metaschemas_list) + res = app.get(url) assert res.status_code == 200 From 16a2d678387cd1954780708f068971fca527e81c Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Fri, 14 Jul 2017 12:45:16 -0400 Subject: [PATCH 35/62] Remove unneeded fixtures; fix imports listing --- api_tests/logs/views/test_log_detail.py | 20 ++++++++++---------- api_tests/logs/views/test_log_embeds.py | 4 ++-- api_tests/logs/views/test_log_params.py | 6 +++--- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/api_tests/logs/views/test_log_detail.py b/api_tests/logs/views/test_log_detail.py index 2eb5cddd985..5f23bb5a55c 100644 --- a/api_tests/logs/views/test_log_detail.py +++ b/api_tests/logs/views/test_log_detail.py @@ -72,19 +72,19 @@ def url_logs(self): @pytest.fixture() def url_log_private_nodes(self, log_private, url_logs): - return url_logs + '{}/nodes/'.format(log_private._id) + return '{}{}/nodes/'.format(url_logs, log_private._id) @pytest.fixture() def url_log_public_nodes(self, log_public, url_logs): - return url_logs + '{}/nodes/'.format(log_public._id) + return '{}{}/nodes/'.format(url_logs, log_public._id) @pytest.fixture() def url_log_detail_private(self, log_private, url_logs): - return url_logs + '{}/'.format(log_private._id) + return '{}{}/'.format(url_logs, log_private._id) @pytest.fixture() def url_log_detail_public(self, log_public, url_logs): - return url_logs + '{}/'.format(log_public._id) + return '{}{}/'.format(url_logs, log_public._id) @pytest.mark.django_db class TestLogDetail(LogsTestCase): @@ -118,7 +118,7 @@ def test_log_detail_public(self, app, url_log_detail_public, log_public, user_tw assert data['id'] == log_public._id #test_log_detail_data_format_api - res = app.get(url_log_detail_public + '?format=api', auth=user_one.auth) + res = app.get('{}?format=api'.format(url_log_detail_public), auth=user_one.auth) assert res.status_code == 200 assert log_public._id in unicode(res.body, 'utf-8') @@ -144,7 +144,7 @@ def component(self, user_one, node): return NodeFactory(parent=node, creator=user_one) @pytest.fixture() - def file(self, user_one, component): + def file_(self, user_one, component): return api_utils.create_test_file(node=component, user=user_one) @pytest.fixture() @@ -156,16 +156,16 @@ def url_component_logs(self, component): return '/{}nodes/{}/logs/'.format(API_BASE, component._id) @pytest.fixture() - def node_with_log(self, node, user_one, file, component): + def node_with_log(self, node, user_one, file_, component): node.add_log( 'osf_storage_file_moved', auth=Auth(user_one), params={ 'node': node._id, 'project': node.parent_id, - 'path': file.materialized_path, + 'path': file_.materialized_path, 'source': { - 'materialized': file.materialized_path, + 'materialized': file_.materialized_path, 'addon': 'osfstorage', 'node': { '_id': component._id, @@ -174,7 +174,7 @@ def node_with_log(self, node, user_one, file, component): } }, 'destination': { - 'materialized': file.materialized_path, + 'materialized': file_.materialized_path, 'addon': 'osfstorage', 'node': { '_id': node._id, diff --git a/api_tests/logs/views/test_log_embeds.py b/api_tests/logs/views/test_log_embeds.py index c40c8205073..ebf68ab95dd 100644 --- a/api_tests/logs/views/test_log_embeds.py +++ b/api_tests/logs/views/test_log_embeds.py @@ -4,7 +4,7 @@ from osf_tests.factories import ( ProjectFactory, AuthUserFactory, - RegistrationFactory + RegistrationFactory, ) @pytest.mark.django_db @@ -67,4 +67,4 @@ def test_log_embed_types(self, app, registration_log, make_url_registration_log, res = app.get(url_registration_log, expect_errors=True) assert res.status_code == 400 - assert res.json['errors'][0]['detail'] == "The following fields are not embeddable: action" + assert res.json['errors'][0]['detail'] == 'The following fields are not embeddable: action' diff --git a/api_tests/logs/views/test_log_params.py b/api_tests/logs/views/test_log_params.py index 66147a49a23..f9018146f64 100644 --- a/api_tests/logs/views/test_log_params.py +++ b/api_tests/logs/views/test_log_params.py @@ -4,7 +4,7 @@ from framework.auth.core import Auth from osf_tests.factories import ( ProjectFactory, - PrivateLinkFactory + PrivateLinkFactory, ) from test_log_detail import LogsTestCase @@ -14,7 +14,7 @@ class TestLogContributors(LogsTestCase): def test_contributor_added_log_has_contributor_info_in_params(self, app, node_private, contributor_log_private, url_logs, user_one): - url = url_logs + '{}/'.format(contributor_log_private._id) + url = '{}{}/'.format(url_logs, contributor_log_private._id) res = app.get(url, auth=user_one.auth) assert res.status_code == 200 params = res.json['data']['attributes']['params'] @@ -56,7 +56,7 @@ def test_params_do_not_appear_on_private_project_with_anonymous_view_only_link(s private_link.nodes.add(node_private) private_link.save() - url = url_logs + '{}/'.format(contributor_log_private._id) + url = '{}{}/'.format(url_logs, contributor_log_private._id) res = app.get(url, {'view_only': private_link.key}, expect_errors=True) assert res.status_code == 200 From dae4b283a2c45ba38c4796f155ad07fad6db8623 Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Fri, 14 Jul 2017 12:58:57 -0400 Subject: [PATCH 36/62] Use is not == to assert False --- api_tests/metaschemas/views/test_metaschemas_detail.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_tests/metaschemas/views/test_metaschemas_detail.py b/api_tests/metaschemas/views/test_metaschemas_detail.py index 86150c15ed1..8bbfc67f0e3 100644 --- a/api_tests/metaschemas/views/test_metaschemas_detail.py +++ b/api_tests/metaschemas/views/test_metaschemas_detail.py @@ -38,7 +38,7 @@ def url_metaschemas_detail(schema_id): res = app.get(url) assert res.status_code == 200 assert res.json['data']['attributes']['name'] == 'Election Research Preacceptance Competition' - assert res.json['data']['attributes']['active'] == False + assert res.json['data']['attributes']['active'] is False #test_non_latest_version_metaschema_returned old_schema = MetaSchema.objects.get(name='OSF-Standard Pre-Data Collection Registration', schema_version=1) From 3976b831283c618856be6201d56cbe1f4f84d3f5 Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Fri, 14 Jul 2017 14:59:05 -0400 Subject: [PATCH 37/62] Add space around operator --- api_tests/metaschemas/views/test_metaschemas_list.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_tests/metaschemas/views/test_metaschemas_list.py b/api_tests/metaschemas/views/test_metaschemas_list.py index f71e251c495..abef05bd1c4 100644 --- a/api_tests/metaschemas/views/test_metaschemas_list.py +++ b/api_tests/metaschemas/views/test_metaschemas_list.py @@ -13,7 +13,7 @@ class TestMetaSchemaList: def test_metaschemas_list_crud(self, app): user = AuthUserFactory() - url= '/{}metaschemas/'.format(API_BASE) + url = '/{}metaschemas/'.format(API_BASE) #test_pass_authenticated_user_can_view_schemas res = app.get(url, auth=user.auth) From 2963671769ae9e1619151d8b6d983f2871bbb4dc Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Fri, 14 Jul 2017 15:38:16 -0400 Subject: [PATCH 38/62] Do not use file as fixture name --- api_tests/logs/views/test_log_detail.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/api_tests/logs/views/test_log_detail.py b/api_tests/logs/views/test_log_detail.py index 5f23bb5a55c..0d587f0b736 100644 --- a/api_tests/logs/views/test_log_detail.py +++ b/api_tests/logs/views/test_log_detail.py @@ -144,7 +144,7 @@ def component(self, user_one, node): return NodeFactory(parent=node, creator=user_one) @pytest.fixture() - def file_(self, user_one, component): + def file_component(self, user_one, component): return api_utils.create_test_file(node=component, user=user_one) @pytest.fixture() @@ -156,16 +156,16 @@ def url_component_logs(self, component): return '/{}nodes/{}/logs/'.format(API_BASE, component._id) @pytest.fixture() - def node_with_log(self, node, user_one, file_, component): + def node_with_log(self, node, user_one, file_component, component): node.add_log( 'osf_storage_file_moved', auth=Auth(user_one), params={ 'node': node._id, 'project': node.parent_id, - 'path': file_.materialized_path, + 'path': file_component.materialized_path, 'source': { - 'materialized': file_.materialized_path, + 'materialized': file_component.materialized_path, 'addon': 'osfstorage', 'node': { '_id': component._id, @@ -174,7 +174,7 @@ def node_with_log(self, node, user_one, file_, component): } }, 'destination': { - 'materialized': file_.materialized_path, + 'materialized': file_component.materialized_path, 'addon': 'osfstorage', 'node': { '_id': node._id, From 6fbcc17c06bab41171fae533984d7892b2a7d5b6 Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Mon, 17 Jul 2017 11:02:59 -0400 Subject: [PATCH 39/62] Use non fixture functions, remove unnecessary Q/find usage --- .../views/test_institution_auth.py | 87 ++++++++----------- .../views/test_institution_list.py | 12 +-- .../test_institution_relationship_nodes.py | 51 +++++------ 3 files changed, 65 insertions(+), 85 deletions(-) diff --git a/api_tests/institutions/views/test_institution_auth.py b/api_tests/institutions/views/test_institution_auth.py index 9d4323a96f2..bb36a73b975 100644 --- a/api_tests/institutions/views/test_institution_auth.py +++ b/api_tests/institutions/views/test_institution_auth.py @@ -3,7 +3,6 @@ import jwt import jwe -from django.db.models import Q from api.base import settings from api.base.settings.defaults import API_BASE from framework.auth import signals @@ -14,72 +13,62 @@ ) from tests.base import capture_signals +def make_user(username, fullname): + return UserFactory(username=username, fullname=fullname) + +def make_payload(institution, username, fullname='Fake User', given_name='', family_name=''): + data = { + 'provider': { + 'id': institution._id, + 'user': { + 'middleNames': '', + 'familyName': family_name, + 'givenName': given_name, + 'fullname': fullname, + 'suffix': '', + 'username': username + } + } + } + return jwe.encrypt(jwt.encode({ + 'sub': username, + 'data': json.dumps(data) + }, settings.JWT_SECRET, algorithm='HS256'), settings.JWE_SECRET) + @pytest.mark.django_db class TestInstitutionAuth: @pytest.fixture() def institution(self): - institution = InstitutionFactory() - institution.save() - return institution + return InstitutionFactory() @pytest.fixture() def url_auth_institution(self): return '/{0}institutions/auth/'.format(API_BASE) - @pytest.fixture() - def make_user(self): - def user(username, fullname): - return UserFactory(username=username, fullname=fullname) - return user - - @pytest.fixture() - def make_payload(self, institution): - def payload(username, fullname='Fake User', given_name='', family_name=''): - data = { - 'provider': { - 'id': institution._id, - 'user': { - 'middleNames': '', - 'familyName': family_name, - 'givenName': given_name, - 'fullname': fullname, - 'suffix': '', - 'username': username - } - } - } - return jwe.encrypt(jwt.encode({ - 'sub': username, - 'data': json.dumps(data) - }, settings.JWT_SECRET, algorithm='HS256'), settings.JWE_SECRET) - - return payload - - - def test_creates_user(self, app, url_auth_institution, institution, make_payload): + def test_creates_user(self, app, url_auth_institution, institution): username = 'hmoco@circle.edu' - assert User.objects.filter(Q(username=username)).count() == 0 + assert User.objects.filter(username=username).count() == 0 with capture_signals() as mock_signals: - res = app.post(url_auth_institution, make_payload(username)) + res = app.post(url_auth_institution, make_payload(institution, username)) assert res.status_code == 204 assert mock_signals.signals_sent() == set([signals.user_confirmed]) - user = User.objects.filter(Q(username=username)).get() + user = User.objects.filter(username=username).first() assert user assert institution in user.affiliated_institutions.all() - def test_adds_institution(self, app, make_user, make_payload, institution, url_auth_institution): + def test_adds_institution(self, app, institution, url_auth_institution): username = 'hmoco@circle.edu' - user = make_user(username,'Mr Moco') + user = make_user(username, 'Mr Moco') user.save() with capture_signals() as mock_signals: - res = app.post(url_auth_institution, make_payload(username)) + res = app.post(url_auth_institution, make_payload(institution, username)) assert res.status_code == 204 assert mock_signals.signals_sent() == set() @@ -87,14 +76,14 @@ def test_adds_institution(self, app, make_user, make_payload, institution, url_a user.reload() assert institution in user.affiliated_institutions.all() - def test_finds_user(self, app, make_user, make_payload, institution, url_auth_institution): + def test_finds_user(self, app, institution, url_auth_institution): username = 'hmoco@circle.edu' user = make_user(username, 'Mr Moco') user.affiliated_institutions.add(institution) user.save() - res = app.post(url_auth_institution, make_payload(username)) + res = app.post(url_auth_institution, make_payload(institution, username)) assert res.status_code == 204 user.reload() @@ -104,26 +93,26 @@ def test_bad_token(self, app, url_auth_institution): res = app.post(url_auth_institution, 'al;kjasdfljadf', expect_errors=True) assert res.status_code == 403 - def test_user_names_guessed_if_not_provided(self, app, make_payload, url_auth_institution): + def test_user_names_guessed_if_not_provided(self, app, institution, url_auth_institution): # Regression for https://openscience.atlassian.net/browse/OSF-7212 username = 'fake@user.edu' - res = app.post(url_auth_institution, make_payload(username)) + res = app.post(url_auth_institution, make_payload(institution, username)) assert res.status_code == 204 - user = User.objects.filter(Q(username=username)).get() + user = User.objects.filter(username=username).first() assert user assert user.fullname == 'Fake User' assert user.given_name == 'Fake' assert user.family_name == 'User' - def test_user_names_used_when_provided(self, app, url_auth_institution, make_payload): + def test_user_names_used_when_provided(self, app, institution, url_auth_institution): # Regression for https://openscience.atlassian.net/browse/OSF-7212 username = 'fake@user.edu' - res = app.post(url_auth_institution, make_payload(username, family_name='West', given_name='Kanye')) + res = app.post(url_auth_institution, make_payload(institution, username, family_name='West', given_name='Kanye')) assert res.status_code == 204 - user = User.objects.filter(Q(username=username)).get() + user = User.objects.filter(username=username).first() assert user assert user.fullname == 'Fake User' diff --git a/api_tests/institutions/views/test_institution_list.py b/api_tests/institutions/views/test_institution_list.py index b4ac959868e..ffc3d31c6dd 100644 --- a/api_tests/institutions/views/test_institution_list.py +++ b/api_tests/institutions/views/test_institution_list.py @@ -19,16 +19,10 @@ def institution_two(self): def url_institution(self): return '/{}institutions/'.format(API_BASE) - @pytest.fixture() - def res_institutions(self, app, url_institution): - return app.get(url_institution) - - @pytest.fixture() - def data_institutions(self, res_institutions): - return res_institutions.json['data'] - + def test_return_all_institutions(self, app, institution_one, institution_two, url_institution): + res_institutions = app.get(url_institution) + data_institutions = res_institutions.json['data'] - def test_return_all_institutions(self, institution_one, institution_two, url_institution, res_institutions, data_institutions): assert res_institutions.status_code == 200 ids = [each['id'] for each in data_institutions] diff --git a/api_tests/institutions/views/test_institution_relationship_nodes.py b/api_tests/institutions/views/test_institution_relationship_nodes.py index c02bc842347..4132365fbc7 100644 --- a/api_tests/institutions/views/test_institution_relationship_nodes.py +++ b/api_tests/institutions/views/test_institution_relationship_nodes.py @@ -9,6 +9,12 @@ ) from website.util import permissions +def make_payload(*node_ids): + data = [ + {'type': 'nodes', 'id': id_} for id_ in node_ids + ] + return {'data': data} + @pytest.mark.django_db class TestInstitutionRelationshipNodes: @@ -49,16 +55,7 @@ def url_institution_nodes(self, institution): return '/{}institutions/{}/relationships/nodes/'.format(API_BASE, institution._id) - @pytest.fixture() - def make_payload(self): - def payload(*node_ids): - data = [ - {'type': 'nodes', 'id': id_} for id_ in node_ids - ] - return {'data': data} - return payload - - def test_auth_get_nodes(self, institution, user, node, node_public, node_private, app, url_institution_nodes): + def test_auth_get_nodes(self, app, institution, user, node, node_public, node_private, url_institution_nodes): #test_get_nodes_no_auth res = app.get(url_institution_nodes) @@ -77,7 +74,7 @@ def test_auth_get_nodes(self, institution, user, node, node_public, node_private assert node_public._id in node_ids assert node_private._id not in node_ids - def test_node_or_type_does_not_exist(self, app, user, url_institution_nodes, make_payload): + def test_node_or_type_does_not_exist(self, app, user, url_institution_nodes): #test_node_does_not_exist res = app.post_json_api( url_institution_nodes, @@ -99,7 +96,7 @@ def test_node_or_type_does_not_exist(self, app, user, url_institution_nodes, mak assert res.status_code == 409 - def test_user_with_nodes_and_permissions(self, user, app, url_institution_nodes, make_payload, institution): + def test_user_with_nodes_and_permissions(self, user, app, url_institution_nodes, institution): node = NodeFactory(creator=user) res = app.post_json_api( url_institution_nodes, @@ -114,7 +111,7 @@ def test_user_with_nodes_and_permissions(self, user, app, url_institution_nodes, node.reload() assert institution in node.affiliated_institutions.all() - def test_user_does_not_have_node(self, app, url_institution_nodes, make_payload, user, institution): + def test_user_does_not_have_node(self, app, url_institution_nodes, user, institution): node = NodeFactory() res = app.post_json_api( url_institution_nodes, @@ -127,7 +124,7 @@ def test_user_does_not_have_node(self, app, url_institution_nodes, make_payload, node.reload() assert institution not in node.affiliated_institutions.all() - def test_user_is_admin(self, app, url_institution_nodes, make_payload, user, institution): + def test_user_is_admin(self, app, url_institution_nodes, user, institution): node = NodeFactory(creator=user) res = app.post_json_api( url_institution_nodes, @@ -138,7 +135,7 @@ def test_user_is_admin(self, app, url_institution_nodes, make_payload, user, ins node.reload() assert institution in node.affiliated_institutions.all() - def test_user_is_read_write(self, app, url_institution_nodes, make_payload, institution): + def test_user_is_read_write(self, app, url_institution_nodes, institution): user = AuthUserFactory() user.affiliated_institutions.add(institution) node = NodeFactory() @@ -154,7 +151,7 @@ def test_user_is_read_write(self, app, url_institution_nodes, make_payload, inst node.reload() assert institution in node.affiliated_institutions.all() - def test_user_is_read_only(self, app, url_institution_nodes, make_payload, institution): + def test_user_is_read_only(self, app, url_institution_nodes, institution): user = AuthUserFactory() user.affiliated_institutions.add(institution) node = NodeFactory() @@ -172,7 +169,7 @@ def test_user_is_read_only(self, app, url_institution_nodes, make_payload, insti node.reload() assert institution not in node.affiliated_institutions.all() - def test_user_is_admin_but_not_affiliated(self, app, url_institution_nodes, make_payload, institution): + def test_user_is_admin_but_not_affiliated(self, app, url_institution_nodes, institution): user = AuthUserFactory() node = NodeFactory(creator=user) res = app.post_json_api( @@ -186,7 +183,7 @@ def test_user_is_admin_but_not_affiliated(self, app, url_institution_nodes, make node.reload() assert institution not in node.affiliated_institutions.all() - def test_add_some_with_permissions_others_without(self, user, app, url_institution_nodes, make_payload, institution): + def test_add_some_with_permissions_others_without(self, user, app, url_institution_nodes, institution): node_one = NodeFactory(creator=user) node_two = NodeFactory() res = app.post_json_api( @@ -202,7 +199,7 @@ def test_add_some_with_permissions_others_without(self, user, app, url_instituti assert institution not in node_one.affiliated_institutions.all() assert institution not in node_two.affiliated_institutions.all() - def test_add_some_existant_others_not(self, institution, node, app, url_institution_nodes, make_payload, user): + def test_add_some_existant_others_not(self, institution, node, app, url_institution_nodes, user): assert institution in node.affiliated_institutions.all() node_one= NodeFactory(creator=user) @@ -218,7 +215,7 @@ def test_add_some_existant_others_not(self, institution, node, app, url_institut assert institution in node.affiliated_institutions.all() assert institution in node_one.affiliated_institutions.all() - def test_only_add_existent_with_mixed_permissions(self, institution, node, node_public, app, url_institution_nodes, make_payload, user): + def test_only_add_existent_with_mixed_permissions(self, institution, node, node_public, app, url_institution_nodes, user): assert institution in node.affiliated_institutions.all() assert institution in node_public.affiliated_institutions.all() @@ -235,7 +232,7 @@ def test_only_add_existent_with_mixed_permissions(self, institution, node, node_ assert institution in node.affiliated_institutions.all() assert institution in node_public.affiliated_institutions.all() - def test_only_add_existent_with_permissions(self, user, node, institution, app, url_institution_nodes, make_payload): + def test_only_add_existent_with_permissions(self, user, node, institution, app, url_institution_nodes): node_one = NodeFactory(creator=user) node_one.affiliated_institutions.add(institution) node_one.save() @@ -250,7 +247,7 @@ def test_only_add_existent_with_permissions(self, user, node, institution, app, assert res.status_code == 204 - def test_delete_user_is_admin(self, app, url_institution_nodes, make_payload, node, user, institution): + def test_delete_user_is_admin(self, app, url_institution_nodes, node, user, institution): res = app.delete_json_api( url_institution_nodes, make_payload(node._id), @@ -260,7 +257,7 @@ def test_delete_user_is_admin(self, app, url_institution_nodes, make_payload, no assert res.status_code == 204 assert institution not in node.affiliated_institutions.all() - def test_delete_user_is_read_write(self, node_private, user, app, url_institution_nodes, make_payload, institution): + def test_delete_user_is_read_write(self, node_private, user, app, url_institution_nodes, institution): node_private.add_contributor(user) node_private.save() @@ -274,7 +271,7 @@ def test_delete_user_is_read_write(self, node_private, user, app, url_institutio assert res.status_code == 204 assert institution not in node_private.affiliated_institutions.all() - def test_delete_user_is_read_only(self, node_private, user, app, url_institution_nodes, make_payload, institution): + def test_delete_user_is_read_only(self, node_private, user, app, url_institution_nodes, institution): node_private.add_contributor(user, permissions='read') node_private.save() @@ -289,7 +286,7 @@ def test_delete_user_is_read_only(self, node_private, user, app, url_institution assert res.status_code == 403 assert institution in node_private.affiliated_institutions.all() - def test_delete_user_is_admin_and_affiliated_with_inst(self, institution, node, app, url_institution_nodes, make_payload, user): + def test_delete_user_is_admin_and_affiliated_with_inst(self, institution, node, app, url_institution_nodes, user): assert institution in node.affiliated_institutions.all() res = app.delete_json_api( @@ -302,7 +299,7 @@ def test_delete_user_is_admin_and_affiliated_with_inst(self, institution, node, node.reload() assert institution not in node.affiliated_institutions.all() - def test_delete_user_is_admin_but_not_affiliated_with_inst(self, institution, app, url_institution_nodes, make_payload): + def test_delete_user_is_admin_but_not_affiliated_with_inst(self, institution, app, url_institution_nodes): user = AuthUserFactory() node = NodeFactory(creator=user) node.affiliated_institutions.add(institution) @@ -319,7 +316,7 @@ def test_delete_user_is_admin_but_not_affiliated_with_inst(self, institution, ap node.reload() assert institution not in node.affiliated_institutions.all() - def test_delete_user_is_affiliated_with_inst_and_mixed_permissions_on_nodes(self, app, url_institution_nodes, make_payload, node, node_public, user): + def test_delete_user_is_affiliated_with_inst_and_mixed_permissions_on_nodes(self, app, url_institution_nodes, node, node_public, user): res = app.delete_json_api( url_institution_nodes, make_payload(node._id, node_public._id), From 37fbfbb31163783f3479e55ff7f3c50d5368805d Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Mon, 17 Jul 2017 11:31:50 -0400 Subject: [PATCH 40/62] Remove unnecessary import, use is not == for false/true/none --- api_tests/logs/views/test_log_detail.py | 5 ----- api_tests/logs/views/test_log_params.py | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/api_tests/logs/views/test_log_detail.py b/api_tests/logs/views/test_log_detail.py index 0d587f0b736..948dea0625f 100644 --- a/api_tests/logs/views/test_log_detail.py +++ b/api_tests/logs/views/test_log_detail.py @@ -3,7 +3,6 @@ from api.base.settings.defaults import API_BASE from api_tests import utils as api_utils from framework.auth.core import Auth -from osf.models import NodeLog from osf_tests.factories import ( ProjectFactory, AuthUserFactory, @@ -22,10 +21,6 @@ def user_one(self): def user_two(self): return AuthUserFactory() - @pytest.fixture() - def action_set(self): - return NodeLog.actions - @pytest.fixture() def node_private(self, user_one): node_private = ProjectFactory(is_public=False) diff --git a/api_tests/logs/views/test_log_params.py b/api_tests/logs/views/test_log_params.py index f9018146f64..4d402ee0526 100644 --- a/api_tests/logs/views/test_log_params.py +++ b/api_tests/logs/views/test_log_params.py @@ -27,7 +27,7 @@ def test_contributor_added_log_has_contributor_info_in_params(self, app, node_pr assert contributors['family_name'] == user_one.family_name assert contributors['full_name'] == user_one.fullname assert contributors['given_name'] == user_one.given_name - assert contributors['unregistered_name'] == None + assert contributors['unregistered_name'] is None def test_unregistered_contributor_added_has_contributor_info_in_params(self, app, user_one): project = ProjectFactory(creator=user_one) From 5d9be37bdfeb6babcf3fa91f86fcea7c6d586313 Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Mon, 17 Jul 2017 12:34:17 -0400 Subject: [PATCH 41/62] Remove unneeded inner function --- api_tests/metaschemas/views/test_metaschemas_detail.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/api_tests/metaschemas/views/test_metaschemas_detail.py b/api_tests/metaschemas/views/test_metaschemas_detail.py index 8bbfc67f0e3..f038ae5b7bc 100644 --- a/api_tests/metaschemas/views/test_metaschemas_detail.py +++ b/api_tests/metaschemas/views/test_metaschemas_detail.py @@ -7,6 +7,7 @@ ) from website.project.metadata.schemas import LATEST_SCHEMA_VERSION + @pytest.mark.django_db class TestMetaSchemaDetail: @@ -15,11 +16,8 @@ def test_metaschemas_detail_visibility(self, app): user = AuthUserFactory() schema = MetaSchema.objects.filter(name='Prereg Challenge', schema_version=LATEST_SCHEMA_VERSION).first() - def url_metaschemas_detail(schema_id): - return '/{}metaschemas/{}/'.format(API_BASE, schema_id) - #test_pass_authenticated_user_can_retrieve_schema - url = url_metaschemas_detail(schema._id) + url = '/{}metaschemas/{}/'.format(API_BASE, schema._id) res = app.get(url, auth=user.auth) assert res.status_code == 200 data = res.json['data']['attributes'] @@ -34,7 +32,7 @@ def url_metaschemas_detail(schema_id): #test_inactive_metaschema_returned inactive_schema = MetaSchema.objects.get(name='Election Research Preacceptance Competition', active=False) - url = url_metaschemas_detail(inactive_schema._id) + url = '/{}metaschemas/{}/'.format(API_BASE, inactive_schema._id) res = app.get(url) assert res.status_code == 200 assert res.json['data']['attributes']['name'] == 'Election Research Preacceptance Competition' @@ -42,7 +40,7 @@ def url_metaschemas_detail(schema_id): #test_non_latest_version_metaschema_returned old_schema = MetaSchema.objects.get(name='OSF-Standard Pre-Data Collection Registration', schema_version=1) - url = url_metaschemas_detail(old_schema._id) + url = '/{}metaschemas/{}/'.format(API_BASE, old_schema._id) res = app.get(url) assert res.status_code == 200 assert res.json['data']['attributes']['name'] == 'OSF-Standard Pre-Data Collection Registration' From 904ec400ba58bd1ed624f799a9334f2eb26baf33 Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Mon, 17 Jul 2017 13:01:23 -0400 Subject: [PATCH 42/62] Remove soon deprecated find() --- api_tests/licenses/views/test_license_detail.py | 10 +++++----- api_tests/licenses/views/test_license_list.py | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/api_tests/licenses/views/test_license_detail.py b/api_tests/licenses/views/test_license_detail.py index 865848ee5d1..4b49caf4691 100644 --- a/api_tests/licenses/views/test_license_detail.py +++ b/api_tests/licenses/views/test_license_detail.py @@ -8,8 +8,8 @@ class TestLicenseDetail: def test_license_detail(self, app): - license = NodeLicense.find()[0] - url_license = '/{}licenses/{}/'.format(API_BASE, license._id) + license_node = NodeLicense.objects.first() + url_license = '/{}licenses/{}/'.format(API_BASE, license_node._id) res_license = app.get(url_license) data_license = res_license.json['data'] @@ -19,10 +19,10 @@ def test_license_detail(self, app): #test_license_top_level(self, license, data_license): assert data_license['type'] == 'licenses' - assert data_license['id'] == license._id + assert data_license['id'] == license_node._id #test_license_name(self, data_license, license): - assert data_license['attributes']['name'] == license.name + assert data_license['attributes']['name'] == license_node.name #test_license_text(self, data_license, license): - assert data_license['attributes']['text'] == license.text + assert data_license['attributes']['text'] == license_node.text diff --git a/api_tests/licenses/views/test_license_list.py b/api_tests/licenses/views/test_license_list.py index 945e9eaebf4..8d93d3befae 100644 --- a/api_tests/licenses/views/test_license_list.py +++ b/api_tests/licenses/views/test_license_list.py @@ -7,7 +7,8 @@ class TestLicenseList: def test_license_list(self, app): - licenses = NodeLicense.find() + licenses = NodeLicense.objects.all() + license_node = licenses[0] url_licenses = '/{}licenses/'.format(API_BASE) res_licenses = app.get(url_licenses) @@ -20,16 +21,15 @@ def test_license_list(self, app): assert total == licenses.count() #test_license_list_name_filter - license = licenses[0] - url = '/{}licenses/?filter[name]={}'.format(API_BASE, license.name) + url = '/{}licenses/?filter[name]={}'.format(API_BASE, license_node.name) res = app.get(url) data = res.json['data'][0] - assert data['attributes']['name'] == license.name - assert data['id'] == license._id + assert data['attributes']['name'] == license_node.name + assert data['id'] == license_node._id #test_license_list_id_filter(self, licenses): - url = '/{}licenses/?filter[id]={}'.format(API_BASE, license._id) + url = '/{}licenses/?filter[id]={}'.format(API_BASE, license_node._id) res = app.get(url) data = res.json['data'][0] - assert data['attributes']['name'] == license.name - assert data['id'] == license._id + assert data['attributes']['name'] == license_node.name + assert data['id'] == license_node._id From 015a4e0ee4040049afd550f7f03325346e6c8613 Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Mon, 17 Jul 2017 13:28:14 -0400 Subject: [PATCH 43/62] Remove unnecessary fixture functions --- api_tests/guids/views/test_guid_detail.py | 36 ++++++++--------------- 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/api_tests/guids/views/test_guid_detail.py b/api_tests/guids/views/test_guid_detail.py index def12c03f55..296aa96a111 100644 --- a/api_tests/guids/views/test_guid_detail.py +++ b/api_tests/guids/views/test_guid_detail.py @@ -24,24 +24,9 @@ def user(self): def project(self): return ProjectFactory() - @pytest.fixture() - def add_private_link(self, project): - def private_link(anonymous=False): - view_only_link = PrivateLinkFactory(anonymous=anonymous) - view_only_link.nodes.add(project) - view_only_link.save() - return view_only_link - return private_link - - @pytest.fixture() - def url_guids_detail(self): - def url(id): - return '/{}guids/{}/'.format(API_BASE, id) - return url - - def test_redirects(self, app, project, url_guids_detail, user): + def test_redirects(self, app, project, user): #test_redirect_to_node_view - url = url_guids_detail(project._id) + url = '/{}guids/{}/'.format(API_BASE, project._id) res = app.get(url, auth=user.auth) redirect_url = '{}{}nodes/{}/'.format(API_DOMAIN, API_BASE, project._id) assert res.status_code == 302 @@ -49,7 +34,7 @@ def test_redirects(self, app, project, url_guids_detail, user): #test_redirect_to_registration_view registration = RegistrationFactory() - url = url_guids_detail(registration._id) + url = '/{}guids/{}/'.format(API_BASE, registration._id) res = app.get(url, auth=user.auth) redirect_url = '{}{}registrations/{}/'.format(API_DOMAIN, API_BASE, registration._id) assert res.status_code == 302 @@ -57,7 +42,7 @@ def test_redirects(self, app, project, url_guids_detail, user): #test_redirect_to_collections_view collection = CollectionFactory() - url = url_guids_detail(collection._id) + url = '/{}guids/{}/'.format(API_BASE, collection._id) res = app.get(url, auth=user.auth) redirect_url = '{}{}collections/{}/'.format(API_DOMAIN, API_BASE, collection._id) assert res.status_code == 302 @@ -72,7 +57,7 @@ def test_redirects(self, app, project, url_guids_detail, user): ) test_file.save() guid = test_file.get_guid(create=True) - url = url_guids_detail(guid._id) + url = '/{}guids/{}/'.format(API_BASE, guid._id) res = app.get(url, auth=user.auth) redirect_url = '{}{}files/{}/'.format(API_DOMAIN, API_BASE, test_file._id) assert res.status_code == 302 @@ -80,21 +65,24 @@ def test_redirects(self, app, project, url_guids_detail, user): #test_redirect_to_comment_view comment = CommentFactory() - url = url_guids_detail(comment._id) + url = '/{}guids/{}/'.format(API_BASE, comment._id) res = app.get(url, auth=user.auth) redirect_url = '{}{}comments/{}/'.format(API_DOMAIN, API_BASE, comment._id) assert res.status_code == 302 assert res.location == redirect_url #test_redirect_throws_404_for_invalid_guids - url = url_guids_detail('fakeguid') + url = '/{}guids/{}/'.format(API_BASE, 'fakeguid') res = app.get(url, auth=user.auth, expect_errors=True) assert res.status_code == 404 - def test_redirects_through_view_only_link(self, app, project, add_private_link, user): + def test_redirects_through_view_only_link(self, app, project, user): #test_redirect_when_viewing_private_project_through_view_only_link - view_only_link = add_private_link() + view_only_link = PrivateLinkFactory(anonymous=False) + view_only_link.nodes.add(project) + view_only_link.save() + url = '/{}guids/{}/?view_only={}'.format(API_BASE, project._id, view_only_link.key) res = app.get(url, auth=user.auth) redirect_url = '{}{}nodes/{}/?view_only={}'.format(API_DOMAIN, API_BASE, project._id, view_only_link.key) From 14ce0603ba49c9ea86e8a202f0a802678ad15c22 Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Mon, 17 Jul 2017 14:16:51 -0400 Subject: [PATCH 44/62] Add node fixture no affiliations --- .../test_institution_relationship_nodes.py | 116 +++++++++--------- 1 file changed, 57 insertions(+), 59 deletions(-) diff --git a/api_tests/institutions/views/test_institution_relationship_nodes.py b/api_tests/institutions/views/test_institution_relationship_nodes.py index 4132365fbc7..dec5c9820eb 100644 --- a/api_tests/institutions/views/test_institution_relationship_nodes.py +++ b/api_tests/institutions/views/test_institution_relationship_nodes.py @@ -22,6 +22,10 @@ class TestInstitutionRelationshipNodes: def institution(self): return InstitutionFactory() + @pytest.fixture() + def node(self): + return NodeFactory() + @pytest.fixture() def user(self, institution): user = AuthUserFactory() @@ -30,12 +34,16 @@ def user(self, institution): return user @pytest.fixture() - def node(self, user, institution): + def node_one(self, user, institution): node = NodeFactory(creator=user) node.affiliated_institutions.add(institution) node.save() return node + @pytest.fixture() + def node_two(self, user): + return NodeFactory(creator=user) + @pytest.fixture() def node_public(self, user, institution): node_public = NodeFactory(is_public=True) @@ -55,13 +63,13 @@ def url_institution_nodes(self, institution): return '/{}institutions/{}/relationships/nodes/'.format(API_BASE, institution._id) - def test_auth_get_nodes(self, app, institution, user, node, node_public, node_private, url_institution_nodes): + def test_auth_get_nodes(self, app, institution, user, node_one, node_public, node_private, url_institution_nodes): #test_get_nodes_no_auth res = app.get(url_institution_nodes) assert res.status_code == 200 node_ids = [node_['id'] for node_ in res.json['data']] - assert node._id not in node_ids + assert node_one._id not in node_ids assert node_public._id in node_ids assert node_private._id not in node_ids @@ -70,11 +78,11 @@ def test_auth_get_nodes(self, app, institution, user, node, node_public, node_pr assert res.status_code == 200 node_ids = [node_['id'] for node_ in res.json['data']] - assert node._id in node_ids + assert node_one._id in node_ids assert node_public._id in node_ids assert node_private._id not in node_ids - def test_node_or_type_does_not_exist(self, app, user, url_institution_nodes): + def test_node_or_type_does_not_exist(self, app, user, node_two, url_institution_nodes): #test_node_does_not_exist res = app.post_json_api( url_institution_nodes, @@ -86,33 +94,30 @@ def test_node_or_type_does_not_exist(self, app, user, url_institution_nodes): assert res.status_code == 404 #test_node_type_does_not_exist - node = NodeFactory(creator=user) res = app.post_json_api( url_institution_nodes, - {'data': [{'type': 'dugtrio', 'id': node._id}]}, + {'data': [{'type': 'dugtrio', 'id': node_two._id}]}, expect_errors=True, auth=user.auth ) assert res.status_code == 409 - def test_user_with_nodes_and_permissions(self, user, app, url_institution_nodes, institution): - node = NodeFactory(creator=user) + def test_user_with_nodes_and_permissions(self, user, app, node_two, url_institution_nodes, institution): res = app.post_json_api( url_institution_nodes, - make_payload(node._id), + make_payload(node_two._id), auth=user.auth ) assert res.status_code == 201 node_ids = [node_['id'] for node_ in res.json['data']] - assert node._id in node_ids + assert node_two._id in node_ids - node.reload() - assert institution in node.affiliated_institutions.all() + node_two.reload() + assert institution in node_two.affiliated_institutions.all() - def test_user_does_not_have_node(self, app, url_institution_nodes, user, institution): - node = NodeFactory() + def test_user_does_not_have_node(self, app, node, url_institution_nodes, user, institution): res = app.post_json_api( url_institution_nodes, make_payload(node._id), @@ -124,21 +129,19 @@ def test_user_does_not_have_node(self, app, url_institution_nodes, user, institu node.reload() assert institution not in node.affiliated_institutions.all() - def test_user_is_admin(self, app, url_institution_nodes, user, institution): - node = NodeFactory(creator=user) + def test_user_is_admin(self, app, node_two, url_institution_nodes, user, institution): res = app.post_json_api( url_institution_nodes, - make_payload(node._id), + make_payload(node_two._id), auth=user.auth ) assert res.status_code == 201 - node.reload() - assert institution in node.affiliated_institutions.all() + node_two.reload() + assert institution in node_two.affiliated_institutions.all() - def test_user_is_read_write(self, app, url_institution_nodes, institution): + def test_user_is_read_write(self, app, node, url_institution_nodes, institution): user = AuthUserFactory() user.affiliated_institutions.add(institution) - node = NodeFactory() node.add_contributor(user) node.save() res = app.post_json_api( @@ -151,10 +154,9 @@ def test_user_is_read_write(self, app, url_institution_nodes, institution): node.reload() assert institution in node.affiliated_institutions.all() - def test_user_is_read_only(self, app, url_institution_nodes, institution): + def test_user_is_read_only(self, app, node, url_institution_nodes, institution): user = AuthUserFactory() user.affiliated_institutions.add(institution) - node = NodeFactory() node.add_contributor(user, permissions=[permissions.READ]) node.save() @@ -183,81 +185,77 @@ def test_user_is_admin_but_not_affiliated(self, app, url_institution_nodes, inst node.reload() assert institution not in node.affiliated_institutions.all() - def test_add_some_with_permissions_others_without(self, user, app, url_institution_nodes, institution): - node_one = NodeFactory(creator=user) - node_two = NodeFactory() + def test_add_some_with_permissions_others_without(self, user, node, node_two, app, url_institution_nodes, institution): res = app.post_json_api( url_institution_nodes, - make_payload(node_one._id, node_two._id), + make_payload(node_two._id, node._id), expect_errors=True, auth=user.auth ) assert res.status_code == 403 - node_one.reload() node_two.reload() - assert institution not in node_one.affiliated_institutions.all() + node.reload() assert institution not in node_two.affiliated_institutions.all() + assert institution not in node.affiliated_institutions.all() - def test_add_some_existant_others_not(self, institution, node, app, url_institution_nodes, user): - assert institution in node.affiliated_institutions.all() + def test_add_some_existant_others_not(self, institution, node_one, node_two, app, url_institution_nodes, user): + assert institution in node_one.affiliated_institutions.all() - node_one= NodeFactory(creator=user) res = app.post_json_api( url_institution_nodes, - make_payload(node_one._id, node._id), + make_payload(node_two._id, node_one._id), auth=user.auth ) assert res.status_code == 201 - node.reload() node_one.reload() - assert institution in node.affiliated_institutions.all() + node_two.reload() assert institution in node_one.affiliated_institutions.all() + assert institution in node_two.affiliated_institutions.all() - def test_only_add_existent_with_mixed_permissions(self, institution, node, node_public, app, url_institution_nodes, user): - assert institution in node.affiliated_institutions.all() + def test_only_add_existent_with_mixed_permissions(self, institution, node_one, node_public, app, url_institution_nodes, user): + assert institution in node_one.affiliated_institutions.all() assert institution in node_public.affiliated_institutions.all() res = app.post_json_api( url_institution_nodes, - make_payload(node_public._id, node._id), + make_payload(node_public._id, node_one._id), expect_errors=True, auth=user.auth ) assert res.status_code == 403 - node.reload() + node_one.reload() node_public.reload() - assert institution in node.affiliated_institutions.all() + assert institution in node_one.affiliated_institutions.all() assert institution in node_public.affiliated_institutions.all() - def test_only_add_existent_with_permissions(self, user, node, institution, app, url_institution_nodes): - node_one = NodeFactory(creator=user) - node_one.affiliated_institutions.add(institution) - node_one.save() - assert institution in node.affiliated_institutions.all() + def test_only_add_existent_with_permissions(self, user, node_one, node_two, institution, app, url_institution_nodes): + node_two.affiliated_institutions.add(institution) + node_two.save() assert institution in node_one.affiliated_institutions.all() + assert institution in node_two.affiliated_institutions.all() res = app.post_json_api( url_institution_nodes, - make_payload(node_one._id, node._id), + make_payload(node_two._id, node_one._id), auth=user.auth ) assert res.status_code == 204 - def test_delete_user_is_admin(self, app, url_institution_nodes, node, user, institution): + def test_delete_user_is_admin(self, app, url_institution_nodes, node_one, user, institution): res = app.delete_json_api( url_institution_nodes, - make_payload(node._id), + make_payload(node_one._id), auth=user.auth ) - node.reload() + node_one.reload() assert res.status_code == 204 - assert institution not in node.affiliated_institutions.all() + assert institution not in node_one.affiliated_institutions.all() - def test_delete_user_is_read_write(self, node_private, user, app, url_institution_nodes, institution): + def test_delete_user_is_read_write(self, app, node_private, user, url_institution_nodes, institution): node_private.add_contributor(user) node_private.save() @@ -286,18 +284,18 @@ def test_delete_user_is_read_only(self, node_private, user, app, url_institution assert res.status_code == 403 assert institution in node_private.affiliated_institutions.all() - def test_delete_user_is_admin_and_affiliated_with_inst(self, institution, node, app, url_institution_nodes, user): - assert institution in node.affiliated_institutions.all() + def test_delete_user_is_admin_and_affiliated_with_inst(self, institution, node_one, app, url_institution_nodes, user): + assert institution in node_one.affiliated_institutions.all() res = app.delete_json_api( url_institution_nodes, - make_payload(node._id), + make_payload(node_one._id), auth=user.auth ) assert res.status_code == 204 - node.reload() - assert institution not in node.affiliated_institutions.all() + node_one.reload() + assert institution not in node_one.affiliated_institutions.all() def test_delete_user_is_admin_but_not_affiliated_with_inst(self, institution, app, url_institution_nodes): user = AuthUserFactory() @@ -316,10 +314,10 @@ def test_delete_user_is_admin_but_not_affiliated_with_inst(self, institution, ap node.reload() assert institution not in node.affiliated_institutions.all() - def test_delete_user_is_affiliated_with_inst_and_mixed_permissions_on_nodes(self, app, url_institution_nodes, node, node_public, user): + def test_delete_user_is_affiliated_with_inst_and_mixed_permissions_on_nodes(self, app, url_institution_nodes, node_one, node_public, user): res = app.delete_json_api( url_institution_nodes, - make_payload(node._id, node_public._id), + make_payload(node_one._id, node_public._id), expect_errors=True, auth=user.auth ) From 77b8bb59c8eb60455c7ace33a7f4127de20a1a22 Mon Sep 17 00:00:00 2001 From: Steven Loria Date: Tue, 18 Jul 2017 15:00:23 -0400 Subject: [PATCH 45/62] Remove print --- api_tests/comments/views/test_comment_report_list.py | 1 - 1 file changed, 1 deletion(-) diff --git a/api_tests/comments/views/test_comment_report_list.py b/api_tests/comments/views/test_comment_report_list.py index 9580eb7b852..f0a36f8697f 100644 --- a/api_tests/comments/views/test_comment_report_list.py +++ b/api_tests/comments/views/test_comment_report_list.py @@ -146,7 +146,6 @@ def test_public_node_private_comment_level_non_contrib_cannot_see_reports(self, public_project.comment_level = 'private' public_project.save() res = app.get(public_url, auth=non_contrib.auth, expect_errors=True) - print res assert res.status_code == 403 assert res.json['errors'][0]['detail'] == exceptions.PermissionDenied.default_detail From b51d20aded70c5d0babe94dd91a967560ffa075c Mon Sep 17 00:00:00 2001 From: Casey Rollins Date: Wed, 19 Jul 2017 14:07:01 -0400 Subject: [PATCH 46/62] Add SportrXiv custom taxonomy. - Use QS filtering on included_subjects in populate_custom_taxonomies --- .../commands/populate_custom_taxonomies.py | 5 +- website/static/sportrxiv_custom_taxonomy.json | 100 ++++++++++++++++++ 2 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 website/static/sportrxiv_custom_taxonomy.json diff --git a/osf/management/commands/populate_custom_taxonomies.py b/osf/management/commands/populate_custom_taxonomies.py index 0691facb7e1..2d855441a11 100644 --- a/osf/management/commands/populate_custom_taxonomies.py +++ b/osf/management/commands/populate_custom_taxonomies.py @@ -20,13 +20,14 @@ def validate_input(custom_provider, data): excludes = data.get('exclude', []) customs = data.get('custom', {}) merges = data.get('merge', {}) + assert not set(includes) & set(excludes), 'There must be no overlap between includes and excludes' for text in includes: assert Subject.objects.filter(provider=BEPRESS_PROVIDER, text=text).exists(), 'Unable to find included subject with text {}'.format(text) included_subjects = Subject.objects.filter(provider=BEPRESS_PROVIDER, text__in=includes).include_children() logger.info('Successfully validated `include`') for text in excludes: - excluded = Subject.objects.get(provider=BEPRESS_PROVIDER, text=text) # May raise not found error - assert excluded.object_hierarchy[0].text in includes, 'Excluded subject with text {} was not included'.format(text) + assert Subject.objects.get(provider=BEPRESS_PROVIDER, text=text).exists(), 'Unable to find excluded subject with text {}'.format(text) + assert included_subjects.filter(text=text), 'Excluded subject with text {} was not included'.format(text) included_subjects.exclude(text__in=excludes) logger.info('Successfully validated `exclude`') for cust_name, map_dict in customs.iteritems(): diff --git a/website/static/sportrxiv_custom_taxonomy.json b/website/static/sportrxiv_custom_taxonomy.json new file mode 100644 index 00000000000..1c8b7ce05db --- /dev/null +++ b/website/static/sportrxiv_custom_taxonomy.json @@ -0,0 +1,100 @@ +{ + "include": [ + "Rehabilitation and Therapy", + "Theatre and Performance Studies" + ], + "exclude": [ + "Acting", + "Playwriting", + "Theatre History", + "Other Theatre and Performance Studies", + "Dramatic Literature, Criticism and Theory" + ], + "custom": { + "Medicine and Health": { + "parent": "Rehabilitation and Therapy", + "bepress": "Sociology" + }, + "Sport and Exercise Science": { + "parent": "", + "bepress": "Kinesiology" + }, + "Exercise Immunology": { + "parent": "Sport and Exercise Science", + "bepress": "Exercise Science" + }, + "Motor Control and Development": { + "parent": "Sport and Exercise Science", + "bepress": "Motor Control" + }, + "Other Sport and Exercise Science": { + "parent": "Sport and Exercise Science", + "bepress": "Kinesiology" + }, + "Performance Analysis": { + "parent": "Sport and Exercise Science", + "bepress": "Kinesiology" + }, + "Physical Activity": { + "parent": "Sport and Exercise Science", + "bepress": "Kinesiology" + }, + "Sport and Exercise Physiology": { + "parent": "Sport and Exercise Science", + "bepress": "Physiology" + }, + "Psychology of Sport and Exercise": { + "parent": "Sport and Exercise Science", + "bepress": "Psychology of Movement" + }, + "Sport and Exercise Biomechanics": { + "parent": "Sport and Exercise Science", + "bepress": "Biomechanics" + }, + "Sport and Exercise Medicine": { + "parent": "Sport and Exercise Science", + "bepress": "Medical Specialties" + }, + "Strength and Conditioning": { + "parent": "Sport and Exercise Science", + "bepress": "Kinesiology" + }, + "Sport and Exercise Studies": { + "parent": "", + "bepress": "Social and Behavioral Sciences" + }, + "Adventure and Expeditionary Education": { + "parent": "Sport and Exercise Studies", + "bepress": "Expeditionary Education" + }, + "Outdoor Education": { + "parent": "Sport and Exercise Studies", + "bepress": "Social and Behavioral Sciences" + }, + "Sport and Exercise Pedagogy": { + "parent": "Sport and Exercise Studies", + "bepress": "Social and Behavioral Sciences" + }, + "Sport Development": { + "parent": "Sport and Exercise Studies", + "bepress": "Social and Behavioral Sciences" + }, + "Sport History": { + "parent": "Sport and Exercise Studies", + "bepress": "Social and Behavioral Sciences" + }, + "Sport Management": { + "parent": "Sport and Exercise Studies", + "bepress": "Business" + }, + "Sport Philosophy": { + "parent": "Sport and Exercise Studies", + "bepress": "Social and Behavioral Sciences" + }, + "Sport Sociology": { + "parent": "Sport and Exercise Studies", + "bepress": "Social and Behavioral Sciences" + } + }, + "merge": {} +} From a6e769cf7d55d9a865aef98d9a83299ce1693385 Mon Sep 17 00:00:00 2001 From: Matt Frazier Date: Wed, 19 Jul 2017 15:10:31 -0400 Subject: [PATCH 47/62] Add Subject.path property -For SHARE compat [#OSF-8308] --- api/taxonomies/serializers.py | 1 + .../taxonomies/views/test_taxonomy_list.py | 8 +++++++ osf/models/subject.py | 5 ++++ tests/test_subjects.py | 24 ++++++++++++++----- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/api/taxonomies/serializers.py b/api/taxonomies/serializers.py index 1f3780bd140..a42a6ce8ab7 100644 --- a/api/taxonomies/serializers.py +++ b/api/taxonomies/serializers.py @@ -31,6 +31,7 @@ class TaxonomySerializer(JSONAPISerializer): ) parent = TaxonomyField() child_count = ser.IntegerField() + path = ser.CharField(read_only=True) links = LinksField({ 'parents': 'get_parent_urls', diff --git a/api_tests/taxonomies/views/test_taxonomy_list.py b/api_tests/taxonomies/views/test_taxonomy_list.py index 628adeab49b..193f8ba2b17 100644 --- a/api_tests/taxonomies/views/test_taxonomy_list.py +++ b/api_tests/taxonomies/views/test_taxonomy_list.py @@ -68,3 +68,11 @@ def test_taxonomy_filter_by_parent(self): for parent in subject['attributes']['parents']: parents_ids.append(parent['id']) assert_in(self.subject1._id, parents_ids) + + def test_taxonomy_path(self): + for item in self.data: + subj = Subject.objects.get(_id=item['id']) + path_parts = item['attributes']['path'].split('/') + assert path_parts[0] in ['bepress', subj.provider._id] + for index, text in enumerate([s.text for s in subj.object_hierarchy]): + assert path_parts[index + 1] == text diff --git a/osf/models/subject.py b/osf/models/subject.py index 3fae80cda6c..c53db4a3039 100644 --- a/osf/models/subject.py +++ b/osf/models/subject.py @@ -47,6 +47,11 @@ def child_count(self): def get_absolute_url(self): return self.absolute_api_v2_url + @cached_property + def path(self): + provider_id = self.provider._id if bool(self.bepress_subject) else 'bepress' + return '{}/{}'.format(provider_id, '/'.join([s.text for s in self.object_hierarchy])) + @cached_property def bepress_text(self): if self.bepress_subject: diff --git a/tests/test_subjects.py b/tests/test_subjects.py index c619ce4a090..ef3b76a9180 100644 --- a/tests/test_subjects.py +++ b/tests/test_subjects.py @@ -155,11 +155,23 @@ def test_max_highlighted_count(self): self.subject.save() class TestSubjectProperties(OsfTestCase): + def setUp(self): + super(TestSubjectProperties, self).setUp() + + self.osf_provider = PreprintProviderFactory(_id='osf') + self.asdf_provider = PreprintProviderFactory(_id='asdf') + self.bepress_subj = SubjectFactory(text='BePress Text', provider=self.osf_provider) + self.other_subj = SubjectFactory(text='Other Text', bepress_subject=self.bepress_subj, provider=self.asdf_provider) + def test_bepress_text(self): - osf_provider = PreprintProviderFactory(_id='osf') - asdf_provider = PreprintProviderFactory(_id='asdf') - bepress_subj = SubjectFactory(text='BePress Text', provider=osf_provider) - other_subj = SubjectFactory(text='Other Text', bepress_subject=bepress_subj, provider=asdf_provider) + assert self.other_subj.bepress_text == 'BePress Text' + assert self.bepress_subj.bepress_text == 'BePress Text' + + def test_path(self): + self.bepress_child = SubjectFactory(text='BePress Child', provider=self.osf_provider, parent=self.bepress_subj) + self.other_child = SubjectFactory(text='Other Child', bepress_subject=self.bepress_subj, provider=self.asdf_provider, parent=self.other_subj) - assert other_subj.bepress_text == 'BePress Text' - assert bepress_subj.bepress_text == 'BePress Text' + assert self.bepress_subj.path == 'bepress/BePress Text' + assert self.bepress_child.path == 'bepress/BePress Text/BePress Child' + assert self.other_subj.path == 'asdf/Other Text' + assert self.other_child.path == 'asdf/Other Text/Other Child' From 6c67af9e25c90fb9bc75d2277c0fe6f5d8769c6f Mon Sep 17 00:00:00 2001 From: Matt Frazier Date: Wed, 19 Jul 2017 17:51:36 -0400 Subject: [PATCH 48/62] Prefer boolean to string for subject provider indication --- api/taxonomies/serializers.py | 5 +++- .../test_preprint_provider_subjects_list.py | 17 +++++++++++++ .../taxonomies/views/test_taxonomy_list.py | 8 ------- osf/models/subject.py | 5 ---- tests/test_subjects.py | 24 +++++-------------- 5 files changed, 27 insertions(+), 32 deletions(-) diff --git a/api/taxonomies/serializers.py b/api/taxonomies/serializers.py index a42a6ce8ab7..36267a1f1ff 100644 --- a/api/taxonomies/serializers.py +++ b/api/taxonomies/serializers.py @@ -31,13 +31,16 @@ class TaxonomySerializer(JSONAPISerializer): ) parent = TaxonomyField() child_count = ser.IntegerField() - path = ser.CharField(read_only=True) + is_bepress = ser.SerializerMethodField() links = LinksField({ 'parents': 'get_parent_urls', 'self': 'get_absolute_url', }) + def get_is_bepress(self, obj): + return not bool(obj.bepress_subject) + def get_parents(self, obj): if not obj.parent: return [] diff --git a/api_tests/preprint_providers/views/test_preprint_provider_subjects_list.py b/api_tests/preprint_providers/views/test_preprint_provider_subjects_list.py index 173e136a9c2..e22695b6878 100644 --- a/api_tests/preprint_providers/views/test_preprint_provider_subjects_list.py +++ b/api_tests/preprint_providers/views/test_preprint_provider_subjects_list.py @@ -252,3 +252,20 @@ def test_mapped_subjects_filter_wrong_provider(self): assert res.status_code == 200 assert len(res.json['data']) == 1 assert res.json['data'][0]['id'] == self.subj_aa._id + +class TestCustomTaxonomy(ApiTestCase): + def setUp(self): + super(TestCustomTaxonomy, self).setUp() + self.osf_provider = PreprintProviderFactory(_id='osf') + self.asdf_provider = PreprintProviderFactory(_id='asdf') + bepress_subj = SubjectFactory(text='BePress Text', provider=self.osf_provider) + other_subj = SubjectFactory(text='Other Text', bepress_subject=bepress_subj, provider=self.asdf_provider) + self.url = '/{}preprint_providers/{}/taxonomies/' + + def test_taxonomy_is_bepress(self): + bepress_res = self.app.get(self.url.format(API_BASE, self.osf_provider._id)) + asdf_res = self.app.get(self.url.format(API_BASE, self.asdf_provider._id)) + + assert len(bepress_res.json['data']) == len(asdf_res.json['data']) == 1 + assert bepress_res.json['data'][0]['attributes']['is_bepress'] == True + assert asdf_res.json['data'][0]['attributes']['is_bepress'] == False diff --git a/api_tests/taxonomies/views/test_taxonomy_list.py b/api_tests/taxonomies/views/test_taxonomy_list.py index 193f8ba2b17..628adeab49b 100644 --- a/api_tests/taxonomies/views/test_taxonomy_list.py +++ b/api_tests/taxonomies/views/test_taxonomy_list.py @@ -68,11 +68,3 @@ def test_taxonomy_filter_by_parent(self): for parent in subject['attributes']['parents']: parents_ids.append(parent['id']) assert_in(self.subject1._id, parents_ids) - - def test_taxonomy_path(self): - for item in self.data: - subj = Subject.objects.get(_id=item['id']) - path_parts = item['attributes']['path'].split('/') - assert path_parts[0] in ['bepress', subj.provider._id] - for index, text in enumerate([s.text for s in subj.object_hierarchy]): - assert path_parts[index + 1] == text diff --git a/osf/models/subject.py b/osf/models/subject.py index c53db4a3039..3fae80cda6c 100644 --- a/osf/models/subject.py +++ b/osf/models/subject.py @@ -47,11 +47,6 @@ def child_count(self): def get_absolute_url(self): return self.absolute_api_v2_url - @cached_property - def path(self): - provider_id = self.provider._id if bool(self.bepress_subject) else 'bepress' - return '{}/{}'.format(provider_id, '/'.join([s.text for s in self.object_hierarchy])) - @cached_property def bepress_text(self): if self.bepress_subject: diff --git a/tests/test_subjects.py b/tests/test_subjects.py index ef3b76a9180..c619ce4a090 100644 --- a/tests/test_subjects.py +++ b/tests/test_subjects.py @@ -155,23 +155,11 @@ def test_max_highlighted_count(self): self.subject.save() class TestSubjectProperties(OsfTestCase): - def setUp(self): - super(TestSubjectProperties, self).setUp() - - self.osf_provider = PreprintProviderFactory(_id='osf') - self.asdf_provider = PreprintProviderFactory(_id='asdf') - self.bepress_subj = SubjectFactory(text='BePress Text', provider=self.osf_provider) - self.other_subj = SubjectFactory(text='Other Text', bepress_subject=self.bepress_subj, provider=self.asdf_provider) - def test_bepress_text(self): - assert self.other_subj.bepress_text == 'BePress Text' - assert self.bepress_subj.bepress_text == 'BePress Text' - - def test_path(self): - self.bepress_child = SubjectFactory(text='BePress Child', provider=self.osf_provider, parent=self.bepress_subj) - self.other_child = SubjectFactory(text='Other Child', bepress_subject=self.bepress_subj, provider=self.asdf_provider, parent=self.other_subj) + osf_provider = PreprintProviderFactory(_id='osf') + asdf_provider = PreprintProviderFactory(_id='asdf') + bepress_subj = SubjectFactory(text='BePress Text', provider=osf_provider) + other_subj = SubjectFactory(text='Other Text', bepress_subject=bepress_subj, provider=asdf_provider) - assert self.bepress_subj.path == 'bepress/BePress Text' - assert self.bepress_child.path == 'bepress/BePress Text/BePress Child' - assert self.other_subj.path == 'asdf/Other Text' - assert self.other_child.path == 'asdf/Other Text/Other Child' + assert other_subj.bepress_text == 'BePress Text' + assert bepress_subj.bepress_text == 'BePress Text' From c36c31c983312f4819b8dc57cb136f93a15d24de Mon Sep 17 00:00:00 2001 From: Casey Rollins Date: Thu, 20 Jul 2017 13:21:01 -0400 Subject: [PATCH 49/62] Error if excldued subject DNE or was not included. --- .../commands/populate_custom_taxonomies.py | 7 +- website/static/sportrxiv_custom_taxonomy.json | 100 ------------------ 2 files changed, 5 insertions(+), 102 deletions(-) delete mode 100644 website/static/sportrxiv_custom_taxonomy.json diff --git a/osf/management/commands/populate_custom_taxonomies.py b/osf/management/commands/populate_custom_taxonomies.py index 2d855441a11..ecf5dee6ade 100644 --- a/osf/management/commands/populate_custom_taxonomies.py +++ b/osf/management/commands/populate_custom_taxonomies.py @@ -26,8 +26,11 @@ def validate_input(custom_provider, data): included_subjects = Subject.objects.filter(provider=BEPRESS_PROVIDER, text__in=includes).include_children() logger.info('Successfully validated `include`') for text in excludes: - assert Subject.objects.get(provider=BEPRESS_PROVIDER, text=text).exists(), 'Unable to find excluded subject with text {}'.format(text) - assert included_subjects.filter(text=text), 'Excluded subject with text {} was not included'.format(text) + try: + Subject.objects.get(provider=BEPRESS_PROVIDER, text=text) + except Subject.DoesNotExist: + raise RuntimeError('Unable to find excluded subject with text {}'.format(text)) + assert included_subjects.filter(text=text).exists(), 'Excluded subject with text {} was not included'.format(text) included_subjects.exclude(text__in=excludes) logger.info('Successfully validated `exclude`') for cust_name, map_dict in customs.iteritems(): diff --git a/website/static/sportrxiv_custom_taxonomy.json b/website/static/sportrxiv_custom_taxonomy.json deleted file mode 100644 index 1c8b7ce05db..00000000000 --- a/website/static/sportrxiv_custom_taxonomy.json +++ /dev/null @@ -1,100 +0,0 @@ -{ - "include": [ - "Rehabilitation and Therapy", - "Theatre and Performance Studies" - ], - "exclude": [ - "Acting", - "Playwriting", - "Theatre History", - "Other Theatre and Performance Studies", - "Dramatic Literature, Criticism and Theory" - ], - "custom": { - "Medicine and Health": { - "parent": "Rehabilitation and Therapy", - "bepress": "Sociology" - }, - "Sport and Exercise Science": { - "parent": "", - "bepress": "Kinesiology" - }, - "Exercise Immunology": { - "parent": "Sport and Exercise Science", - "bepress": "Exercise Science" - }, - "Motor Control and Development": { - "parent": "Sport and Exercise Science", - "bepress": "Motor Control" - }, - "Other Sport and Exercise Science": { - "parent": "Sport and Exercise Science", - "bepress": "Kinesiology" - }, - "Performance Analysis": { - "parent": "Sport and Exercise Science", - "bepress": "Kinesiology" - }, - "Physical Activity": { - "parent": "Sport and Exercise Science", - "bepress": "Kinesiology" - }, - "Sport and Exercise Physiology": { - "parent": "Sport and Exercise Science", - "bepress": "Physiology" - }, - "Psychology of Sport and Exercise": { - "parent": "Sport and Exercise Science", - "bepress": "Psychology of Movement" - }, - "Sport and Exercise Biomechanics": { - "parent": "Sport and Exercise Science", - "bepress": "Biomechanics" - }, - "Sport and Exercise Medicine": { - "parent": "Sport and Exercise Science", - "bepress": "Medical Specialties" - }, - "Strength and Conditioning": { - "parent": "Sport and Exercise Science", - "bepress": "Kinesiology" - }, - "Sport and Exercise Studies": { - "parent": "", - "bepress": "Social and Behavioral Sciences" - }, - "Adventure and Expeditionary Education": { - "parent": "Sport and Exercise Studies", - "bepress": "Expeditionary Education" - }, - "Outdoor Education": { - "parent": "Sport and Exercise Studies", - "bepress": "Social and Behavioral Sciences" - }, - "Sport and Exercise Pedagogy": { - "parent": "Sport and Exercise Studies", - "bepress": "Social and Behavioral Sciences" - }, - "Sport Development": { - "parent": "Sport and Exercise Studies", - "bepress": "Social and Behavioral Sciences" - }, - "Sport History": { - "parent": "Sport and Exercise Studies", - "bepress": "Social and Behavioral Sciences" - }, - "Sport Management": { - "parent": "Sport and Exercise Studies", - "bepress": "Business" - }, - "Sport Philosophy": { - "parent": "Sport and Exercise Studies", - "bepress": "Social and Behavioral Sciences" - }, - "Sport Sociology": { - "parent": "Sport and Exercise Studies", - "bepress": "Social and Behavioral Sciences" - } - }, - "merge": {} -} From 21cac86f7a23f051f9ee69d3a49791fbf067dc06 Mon Sep 17 00:00:00 2001 From: Matt Frazier Date: Thu, 20 Jul 2017 14:24:51 -0400 Subject: [PATCH 50/62] Add `share_title` to PrepriPro, TaxonomySerializer --- api/taxonomies/serializers.py | 5 +---- .../test_preprint_provider_subjects_list.py | 10 +++++----- .../0042_preprintprovider_share_title.py | 20 +++++++++++++++++++ osf/models/preprint_provider.py | 1 + 4 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 osf/migrations/0042_preprintprovider_share_title.py diff --git a/api/taxonomies/serializers.py b/api/taxonomies/serializers.py index 36267a1f1ff..e03329125f8 100644 --- a/api/taxonomies/serializers.py +++ b/api/taxonomies/serializers.py @@ -31,16 +31,13 @@ class TaxonomySerializer(JSONAPISerializer): ) parent = TaxonomyField() child_count = ser.IntegerField() - is_bepress = ser.SerializerMethodField() + share_title = ser.CharField(source='provider.share_title', read_only=True) links = LinksField({ 'parents': 'get_parent_urls', 'self': 'get_absolute_url', }) - def get_is_bepress(self, obj): - return not bool(obj.bepress_subject) - def get_parents(self, obj): if not obj.parent: return [] diff --git a/api_tests/preprint_providers/views/test_preprint_provider_subjects_list.py b/api_tests/preprint_providers/views/test_preprint_provider_subjects_list.py index e22695b6878..7f8241de459 100644 --- a/api_tests/preprint_providers/views/test_preprint_provider_subjects_list.py +++ b/api_tests/preprint_providers/views/test_preprint_provider_subjects_list.py @@ -256,16 +256,16 @@ def test_mapped_subjects_filter_wrong_provider(self): class TestCustomTaxonomy(ApiTestCase): def setUp(self): super(TestCustomTaxonomy, self).setUp() - self.osf_provider = PreprintProviderFactory(_id='osf') - self.asdf_provider = PreprintProviderFactory(_id='asdf') + self.osf_provider = PreprintProviderFactory(_id='osf', share_title='bepress') + self.asdf_provider = PreprintProviderFactory(_id='asdf', share_title='ASDF') bepress_subj = SubjectFactory(text='BePress Text', provider=self.osf_provider) other_subj = SubjectFactory(text='Other Text', bepress_subject=bepress_subj, provider=self.asdf_provider) self.url = '/{}preprint_providers/{}/taxonomies/' - def test_taxonomy_is_bepress(self): + def test_taxonomy_share_title(self): bepress_res = self.app.get(self.url.format(API_BASE, self.osf_provider._id)) asdf_res = self.app.get(self.url.format(API_BASE, self.asdf_provider._id)) assert len(bepress_res.json['data']) == len(asdf_res.json['data']) == 1 - assert bepress_res.json['data'][0]['attributes']['is_bepress'] == True - assert asdf_res.json['data'][0]['attributes']['is_bepress'] == False + assert bepress_res.json['data'][0]['attributes']['share_title'] == self.osf_provider.share_title + assert asdf_res.json['data'][0]['attributes']['share_title'] == self.asdf_provider.share_title diff --git a/osf/migrations/0042_preprintprovider_share_title.py b/osf/migrations/0042_preprintprovider_share_title.py new file mode 100644 index 00000000000..c22b1b82247 --- /dev/null +++ b/osf/migrations/0042_preprintprovider_share_title.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.2 on 2017-07-20 18:24 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('osf', '0041_auto_20170706_1024'), + ] + + operations = [ + migrations.AddField( + model_name='preprintprovider', + name='share_title', + field=models.TextField(blank=True, default=b''), + ), + ] diff --git a/osf/models/preprint_provider.py b/osf/models/preprint_provider.py index 715a7f58371..39d101ecc70 100644 --- a/osf/models/preprint_provider.py +++ b/osf/models/preprint_provider.py @@ -29,6 +29,7 @@ class PreprintProvider(ObjectIDMixin, BaseModel): social_instagram = models.CharField(null=True, blank=True, max_length=200) # max length on prod: 8 footer_links = models.TextField(default='', blank=True) share_source = models.CharField(blank=True, max_length=200) + share_title = models.TextField(default='', blank=True) allow_submissions = models.BooleanField(default=True) additional_providers = fields.ArrayField(models.CharField(max_length=200), default=list, blank=True) From c646c264198ee4ab2f4d6d314e60026404e2502a Mon Sep 17 00:00:00 2001 From: Matt Frazier Date: Thu, 20 Jul 2017 14:25:59 -0400 Subject: [PATCH 51/62] Deprecate unbranded TaxonomyList --- api/base/settings/defaults.py | 1 + api/base/versioning.py | 15 +++++++++++++++ api/taxonomies/views.py | 4 +++- api_tests/taxonomies/views/test_taxonomy_list.py | 4 ++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/api/base/settings/defaults.py b/api/base/settings/defaults.py index 2abac9efabb..97f53b04c30 100644 --- a/api/base/settings/defaults.py +++ b/api/base/settings/defaults.py @@ -153,6 +153,7 @@ '2.3', '2.4', '2.5', + '2.6', ), 'DEFAULT_FILTER_BACKENDS': ('api.base.filters.ODMOrderingFilter',), 'DEFAULT_PAGINATION_CLASS': 'api.base.pagination.JSONAPIPagination', diff --git a/api/base/versioning.py b/api/base/versioning.py index caad7263077..29b3ae2e91f 100644 --- a/api/base/versioning.py +++ b/api/base/versioning.py @@ -105,3 +105,18 @@ def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, * return utils.absolute_reverse( viewname, query_kwargs=query_kwargs, args=args, kwargs=kwargs ) + +class DeprecatedEndpointMixin(object): + @property + def min_version(self): + return '2.0' + + @property + def max_version(self): + raise NotImplementedError('Deprecated endpoints must define `max_version`') + + def determine_version(self, request, *args, **kwargs): + version, scheme = super(DeprecatedEndpointMixin, self).determine_version(request, *args, **kwargs) + if utils.is_deprecated(version, self.min_version, self.max_version): + raise drf_exceptions.NotFound() + return version, scheme diff --git a/api/taxonomies/views.py b/api/taxonomies/views.py index ff8584758f8..af5304f9be8 100644 --- a/api/taxonomies/views.py +++ b/api/taxonomies/views.py @@ -5,12 +5,13 @@ from api.base.filters import ODMFilterMixin from api.base.pagination import NoMaxPageSizePagination from api.base import permissions as base_permissions +from api.base.versioning import DeprecatedEndpointMixin from api.taxonomies.serializers import TaxonomySerializer from osf.models import Subject from framework.auth.oauth_scopes import CoreScopes -class TaxonomyList(JSONAPIBaseView, generics.ListAPIView, ODMFilterMixin): +class TaxonomyList(DeprecatedEndpointMixin, JSONAPIBaseView, generics.ListAPIView, ODMFilterMixin): '''[BePress taxonomy subject](https://www.bepress.com/wp-content/uploads/2016/12/Digital-Commons-Disciplines-taxonomy-2017-01.pdf) instance. *Read-only* ##Note @@ -47,6 +48,7 @@ class TaxonomyList(JSONAPIBaseView, generics.ListAPIView, ODMFilterMixin): pagination_class = NoMaxPageSizePagination view_category = 'taxonomies' view_name = 'taxonomy-list' + max_version = '2.5' # overrides ListAPIView def get_default_odm_query(self): diff --git a/api_tests/taxonomies/views/test_taxonomy_list.py b/api_tests/taxonomies/views/test_taxonomy_list.py index 628adeab49b..890bab52b90 100644 --- a/api_tests/taxonomies/views/test_taxonomy_list.py +++ b/api_tests/taxonomies/views/test_taxonomy_list.py @@ -68,3 +68,7 @@ def test_taxonomy_filter_by_parent(self): for parent in subject['attributes']['parents']: parents_ids.append(parent['id']) assert_in(self.subject1._id, parents_ids) + + def test_is_deprecated(self): + res = self.app.get('{}?version=2.6'.format(self.url), expect_errors=True) + assert res.status_code == 404 From 34476e775225d50c7db3eef44e8b758a48f2b71f Mon Sep 17 00:00:00 2001 From: Fabrice Mizero Date: Mon, 24 Jul 2017 08:45:12 -0400 Subject: [PATCH 52/62] Bump academicons --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index 651b0ea5d9e..73f1ef7f70c 100644 --- a/bower.json +++ b/bower.json @@ -19,6 +19,6 @@ "raven-js": "2.1.0", "clipboard": "^1.6.1", "At.js": "CenterForOpenScience/At.js#cos", - "academicons": "1.7.0" + "academicons": "1.8.0" } } From 0f2fb7c73123723541b38ef075f0f744a0377e17 Mon Sep 17 00:00:00 2001 From: Matt Frazier Date: Mon, 24 Jul 2017 15:35:11 -0400 Subject: [PATCH 53/62] Fix bad merge -update test --- osf/models/preprint_service.py | 2 +- tests/test_preprints.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/osf/models/preprint_service.py b/osf/models/preprint_service.py index 4035ecf1305..f594e7c1d59 100644 --- a/osf/models/preprint_service.py +++ b/osf/models/preprint_service.py @@ -230,5 +230,5 @@ def save(self, *args, **kwargs): ret = super(PreprintService, self).save(*args, **kwargs) if (not first_save and 'is_published' in saved_fields) or self.is_published: - enqueue_task(on_preprint_updated.s(self._id, old_subjects)) + enqueue_task(on_preprint_updated.s(self._id, old_subjects=old_subjects)) return ret diff --git a/tests/test_preprints.py b/tests/test_preprints.py index 9fb3c6da209..2c8b744d522 100644 --- a/tests/test_preprints.py +++ b/tests/test_preprints.py @@ -619,6 +619,7 @@ def test_save_published_subject_change_called(self, mock_on_preprint_updated): self.preprint.is_published = True self.preprint.set_subjects([[self.subject_two._id]], auth=self.auth) assert mock_on_preprint_updated.called + assert {'old_subjects': [self.subject.id]} in mock_on_preprint_updated.call_args @mock.patch('website.preprints.tasks.on_preprint_updated.s') def test_save_unpublished_subject_change_not_called(self, mock_on_preprint_updated): From f30f62dedc2b45dcb7e093b909dbeab77215d48f Mon Sep 17 00:00:00 2001 From: Rheisen Dennis Date: Tue, 25 Jul 2017 10:25:22 -0400 Subject: [PATCH 54/62] [feature] Shorten Travis Logs [OSF-8102] (#7330) * test addopts = -p no:warnings * test moving -p no:warnings * reset pytest.ini to original state, modify conftest files with more silent loggers * add rest_framework/pagination and tests/base to silent loggers * modify conftest to include website.project & osf.migrations.0001_initial * add django to silent loggers * remove all silent loggers just to see if things change * add silent loggers * set all logging level to critical * try pytest ignoring user warnings * try disabling all pytest warnings * try removing adopting no warnings * comment silent loggers * show deprecation and pending deprecation warnings once * try using setLevel in conftest to see if framework logging overrides * try using logging.getLogger() * try logging.disable(logging.WARNING) * try using silent loggers with logging.disable * revert back to disabling logs that aren't critical * revert changes to conftest files * fix osf_tests/conftest.py --- pytest.ini | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pytest.ini b/pytest.ini index 7637d1e9620..dce1e0ae69a 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,3 +1,7 @@ [pytest] DJANGO_SETTINGS_MODULE=osf_tests.settings addopts = --tb=short --reuse-db +filterwarnings = + once::UserWarning + once::DeprecationWarning + once::PendingDeprecationWarning From 138be6811bce86c9da7364101358c48883db1c28 Mon Sep 17 00:00:00 2001 From: Matt Frazier Date: Tue, 25 Jul 2017 14:15:53 -0400 Subject: [PATCH 55/62] Tell SHARE about .subject changes --- osf/management/commands/populate_custom_taxonomies.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osf/management/commands/populate_custom_taxonomies.py b/osf/management/commands/populate_custom_taxonomies.py index ecf5dee6ade..31416afcf28 100644 --- a/osf/management/commands/populate_custom_taxonomies.py +++ b/osf/management/commands/populate_custom_taxonomies.py @@ -105,12 +105,13 @@ def map_preprints_to_custom_subjects(custom_provider, merge_dict): subject_ids_to_map = set(s.id for s in subjects_to_map if s.text not in merge_dict.keys()) aliased_subject_ids = set(Subject.objects.filter(bepress_subject__id__in=subject_ids_to_map, provider=custom_provider).values_list('id', flat=True)) | merged_subject_ids aliased_hiers = [s.object_hierarchy for s in Subject.objects.filter(id__in=aliased_subject_ids)] + old_subjects = list(preprint.subjects.values_list('id', flat=True)) preprint.subjects.clear() for hier in aliased_hiers: validate_subject_hierarchy([s._id for s in hier]) for s in hier: preprint.subjects.add(s) - preprint.save() + preprint.save(old_subjects=old_subjects) preprint.reload() new_hier = [s.object_hierarchy for s in preprint.subjects.exclude(children__in=preprint.subjects.all())] logger.info('Successfully migrated preprint {}.\n\tOld hierarchy:{}\n\tNew hierarchy:{}'.format(preprint.id, old_hier, new_hier)) From 03eeb9ffced044ac8b289ef042ac213e0ca2fc94 Mon Sep 17 00:00:00 2001 From: Matt Frazier Date: Tue, 25 Jul 2017 23:24:28 -0400 Subject: [PATCH 56/62] Fix throughsubject undeletion --- website/preprints/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/preprints/tasks.py b/website/preprints/tasks.py index 554b945e712..7eaff8dc5ff 100644 --- a/website/preprints/tasks.py +++ b/website/preprints/tasks.py @@ -89,7 +89,7 @@ def format_preprint(preprint, old_subjects=None): ] current_subjects = [ - GraphNode('throughsubjects', creative_work=preprint_graph, subject=format_subject(s)) + GraphNode('throughsubjects', creative_work=preprint_graph, is_deleted=False, subject=format_subject(s)) for s in preprint.subjects.all() ] deleted_subjects = [ From 90548201ad0cc9d73eaff3834c83dd10e5bf06dd Mon Sep 17 00:00:00 2001 From: Steven Loria Date: Fri, 28 Jul 2017 10:28:06 -0400 Subject: [PATCH 57/62] Update changelog [skip ci] --- CHANGELOG | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 14fd562bf28..fcaff58dbaf 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,11 @@ Changelog ********* +0.118.0 (unreleased) +==================== + +- Support for custom taxonomies. + 0.117.0 (2017-07-13) ==================== - Profile: long Personal Website URLs run over in cause problems in display #5270 From 087e8e18866c3c2462ddc86a48c133966ce61370 Mon Sep 17 00:00:00 2001 From: Matt Frazier Date: Tue, 1 Aug 2017 15:39:37 -0400 Subject: [PATCH 58/62] Add relationship link to highlighted taxs [#EOSF-691] --- api/preprint_providers/serializers.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/api/preprint_providers/serializers.py b/api/preprint_providers/serializers.py index 24c7f51dfe8..3b8fccadcb5 100644 --- a/api/preprint_providers/serializers.py +++ b/api/preprint_providers/serializers.py @@ -37,6 +37,11 @@ class PreprintProviderSerializer(JSONAPISerializer): related_view_kwargs={'provider_id': '<_id>'} ) + highlighted_taxonomies = RelationshipField( + related_view='preprint_providers:highlighted-taxonomy-list', + related_view_kwargs={'provider_id': '<_id>'} + ) + licenses_acceptable = RelationshipField( related_view='preprint_providers:license-list', related_view_kwargs={'provider_id': '<_id>'} From 35890ff4eaf200f6b21121bfd4d03e09a11f77cf Mon Sep 17 00:00:00 2001 From: Matt Frazier Date: Wed, 19 Jul 2017 15:10:31 -0400 Subject: [PATCH 59/62] Add Subject.path property again -For SHARE compat [#OSF-8308] --- api/taxonomies/serializers.py | 1 + .../taxonomies/views/test_taxonomy_list.py | 8 +++++++ osf/models/subject.py | 5 ++++ tests/test_subjects.py | 24 ++++++++++++++----- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/api/taxonomies/serializers.py b/api/taxonomies/serializers.py index e03329125f8..016fe0c1822 100644 --- a/api/taxonomies/serializers.py +++ b/api/taxonomies/serializers.py @@ -32,6 +32,7 @@ class TaxonomySerializer(JSONAPISerializer): parent = TaxonomyField() child_count = ser.IntegerField() share_title = ser.CharField(source='provider.share_title', read_only=True) + path = ser.CharField(read_only=True) links = LinksField({ 'parents': 'get_parent_urls', diff --git a/api_tests/taxonomies/views/test_taxonomy_list.py b/api_tests/taxonomies/views/test_taxonomy_list.py index 890bab52b90..2a993c046d0 100644 --- a/api_tests/taxonomies/views/test_taxonomy_list.py +++ b/api_tests/taxonomies/views/test_taxonomy_list.py @@ -72,3 +72,11 @@ def test_taxonomy_filter_by_parent(self): def test_is_deprecated(self): res = self.app.get('{}?version=2.6'.format(self.url), expect_errors=True) assert res.status_code == 404 + + def test_taxonomy_path(self): + for item in self.data: + subj = Subject.objects.get(_id=item['id']) + path_parts = item['attributes']['path'].split('/') + assert path_parts[0] in ['bepress', subj.provider._id] + for index, text in enumerate([s.text for s in subj.object_hierarchy]): + assert path_parts[index + 1] == text diff --git a/osf/models/subject.py b/osf/models/subject.py index 3fae80cda6c..c53db4a3039 100644 --- a/osf/models/subject.py +++ b/osf/models/subject.py @@ -47,6 +47,11 @@ def child_count(self): def get_absolute_url(self): return self.absolute_api_v2_url + @cached_property + def path(self): + provider_id = self.provider._id if bool(self.bepress_subject) else 'bepress' + return '{}/{}'.format(provider_id, '/'.join([s.text for s in self.object_hierarchy])) + @cached_property def bepress_text(self): if self.bepress_subject: diff --git a/tests/test_subjects.py b/tests/test_subjects.py index c619ce4a090..ef3b76a9180 100644 --- a/tests/test_subjects.py +++ b/tests/test_subjects.py @@ -155,11 +155,23 @@ def test_max_highlighted_count(self): self.subject.save() class TestSubjectProperties(OsfTestCase): + def setUp(self): + super(TestSubjectProperties, self).setUp() + + self.osf_provider = PreprintProviderFactory(_id='osf') + self.asdf_provider = PreprintProviderFactory(_id='asdf') + self.bepress_subj = SubjectFactory(text='BePress Text', provider=self.osf_provider) + self.other_subj = SubjectFactory(text='Other Text', bepress_subject=self.bepress_subj, provider=self.asdf_provider) + def test_bepress_text(self): - osf_provider = PreprintProviderFactory(_id='osf') - asdf_provider = PreprintProviderFactory(_id='asdf') - bepress_subj = SubjectFactory(text='BePress Text', provider=osf_provider) - other_subj = SubjectFactory(text='Other Text', bepress_subject=bepress_subj, provider=asdf_provider) + assert self.other_subj.bepress_text == 'BePress Text' + assert self.bepress_subj.bepress_text == 'BePress Text' + + def test_path(self): + self.bepress_child = SubjectFactory(text='BePress Child', provider=self.osf_provider, parent=self.bepress_subj) + self.other_child = SubjectFactory(text='Other Child', bepress_subject=self.bepress_subj, provider=self.asdf_provider, parent=self.other_subj) - assert other_subj.bepress_text == 'BePress Text' - assert bepress_subj.bepress_text == 'BePress Text' + assert self.bepress_subj.path == 'bepress/BePress Text' + assert self.bepress_child.path == 'bepress/BePress Text/BePress Child' + assert self.other_subj.path == 'asdf/Other Text' + assert self.other_child.path == 'asdf/Other Text/Other Child' From 3eef0010acd39c01d1414e9ab1c739c9e73f94ee Mon Sep 17 00:00:00 2001 From: Matt Frazier Date: Wed, 2 Aug 2017 17:49:52 -0400 Subject: [PATCH 60/62] Use provider.share_title for path --- osf/models/subject.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osf/models/subject.py b/osf/models/subject.py index c53db4a3039..61a26f5aa48 100644 --- a/osf/models/subject.py +++ b/osf/models/subject.py @@ -49,8 +49,7 @@ def get_absolute_url(self): @cached_property def path(self): - provider_id = self.provider._id if bool(self.bepress_subject) else 'bepress' - return '{}/{}'.format(provider_id, '/'.join([s.text for s in self.object_hierarchy])) + return '{}/{}'.format(self.provider.share_title, '/'.join([s.text for s in self.object_hierarchy])) @cached_property def bepress_text(self): From df55f9446776e90fec71c2e372aaeef6655b5d47 Mon Sep 17 00:00:00 2001 From: Matt Frazier Date: Wed, 2 Aug 2017 22:57:24 -0400 Subject: [PATCH 61/62] Prefer pipes to slashes for subject.path -Fix PreprintProviderFactory, tests --- api_tests/taxonomies/views/test_taxonomy_list.py | 4 ++-- osf/models/subject.py | 2 +- osf_tests/factories.py | 15 +++++++++++++++ tests/test_subjects.py | 10 +++++----- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/api_tests/taxonomies/views/test_taxonomy_list.py b/api_tests/taxonomies/views/test_taxonomy_list.py index 2a993c046d0..d1d48751cc1 100644 --- a/api_tests/taxonomies/views/test_taxonomy_list.py +++ b/api_tests/taxonomies/views/test_taxonomy_list.py @@ -76,7 +76,7 @@ def test_is_deprecated(self): def test_taxonomy_path(self): for item in self.data: subj = Subject.objects.get(_id=item['id']) - path_parts = item['attributes']['path'].split('/') - assert path_parts[0] in ['bepress', subj.provider._id] + path_parts = item['attributes']['path'].split('|') + assert path_parts[0] == subj.provider.share_title for index, text in enumerate([s.text for s in subj.object_hierarchy]): assert path_parts[index + 1] == text diff --git a/osf/models/subject.py b/osf/models/subject.py index 61a26f5aa48..28f9777fac5 100644 --- a/osf/models/subject.py +++ b/osf/models/subject.py @@ -49,7 +49,7 @@ def get_absolute_url(self): @cached_property def path(self): - return '{}/{}'.format(self.provider.share_title, '/'.join([s.text for s in self.object_hierarchy])) + return '{}|{}'.format(self.provider.share_title, '|'.join([s.text for s in self.object_hierarchy])) @cached_property def bepress_text(self): diff --git a/osf_tests/factories.py b/osf_tests/factories.py index ee51637c924..b31e206ceb6 100644 --- a/osf_tests/factories.py +++ b/osf_tests/factories.py @@ -524,6 +524,21 @@ class PreprintProviderFactory(DjangoModelFactory): class Meta: model = models.PreprintProvider + @classmethod + def _build(cls, target_class, *args, **kwargs): + instance = super(PreprintProviderFactory, cls)._build(target_class, *args, **kwargs) + if not instance.share_title: + instance.share_title = instance._id + return instance + + @classmethod + def _create(cls, target_class, *args, **kwargs): + instance = super(PreprintProviderFactory, cls)._create(target_class, *args, **kwargs) + if not instance.share_title: + instance.share_title = instance._id + instance.save() + return instance + def sync_set_identifiers(preprint): ezid_return_value ={ diff --git a/tests/test_subjects.py b/tests/test_subjects.py index ef3b76a9180..60c8e31de30 100644 --- a/tests/test_subjects.py +++ b/tests/test_subjects.py @@ -158,7 +158,7 @@ class TestSubjectProperties(OsfTestCase): def setUp(self): super(TestSubjectProperties, self).setUp() - self.osf_provider = PreprintProviderFactory(_id='osf') + self.osf_provider = PreprintProviderFactory(_id='osf', share_title='bepress') self.asdf_provider = PreprintProviderFactory(_id='asdf') self.bepress_subj = SubjectFactory(text='BePress Text', provider=self.osf_provider) self.other_subj = SubjectFactory(text='Other Text', bepress_subject=self.bepress_subj, provider=self.asdf_provider) @@ -171,7 +171,7 @@ def test_path(self): self.bepress_child = SubjectFactory(text='BePress Child', provider=self.osf_provider, parent=self.bepress_subj) self.other_child = SubjectFactory(text='Other Child', bepress_subject=self.bepress_subj, provider=self.asdf_provider, parent=self.other_subj) - assert self.bepress_subj.path == 'bepress/BePress Text' - assert self.bepress_child.path == 'bepress/BePress Text/BePress Child' - assert self.other_subj.path == 'asdf/Other Text' - assert self.other_child.path == 'asdf/Other Text/Other Child' + assert self.bepress_subj.path == 'bepress|BePress Text' + assert self.bepress_child.path == 'bepress|BePress Text|BePress Child' + assert self.other_subj.path == 'asdf|Other Text' + assert self.other_child.path == 'asdf|Other Text|Other Child' From 88d43714f8c173d9496b0aa74f27cba31ccc9dc3 Mon Sep 17 00:00:00 2001 From: Steven Loria Date: Thu, 3 Aug 2017 10:31:15 -0400 Subject: [PATCH 62/62] Update changelog and bump version --- CHANGELOG | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index fcaff58dbaf..a40dd133af5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,7 +2,7 @@ Changelog ********* -0.118.0 (unreleased) +0.118.0 (2017-08-03) ==================== - Support for custom taxonomies. diff --git a/package.json b/package.json index 029b5f510e8..de01695d7fe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "OSF", - "version": "0.117.1", + "version": "0.118.0", "description": "Facilitating Open Science", "repository": "https://github.com/CenterForOpenScience/osf.io", "author": "Center for Open Science",