{"action":"created","comment":{"url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/comments/46591288","id":46591288,"diff_hunk":"@@ -0,0 +1,1098 @@\n+from nose.tools import *  # flake8: noqa\n+\n+from website.util import permissions\n+\n+from api.base.settings.defaults import API_BASE\n+\n+from tests.base import ApiTestCase\n+\n+from tests.factories import (\n+    ProjectFactory,\n+    RegistrationFactory,\n+    AuthUserFactory,\n+    AlternativeCitationFactory\n+)\n+\n+class TestCreateAlternativeCitations(ApiTestCase):\n+    def setUp(self):\n+        super(TestCreateAlternativeCitations, self).setUp()\n+        self.user = AuthUserFactory()\n+        self.user_two = AuthUserFactory()\n+        self.user_three = AuthUserFactory()\n+\n+        self.public = ProjectFactory(creator=self.user, is_public=True)\n+        self.private = ProjectFactory(creator=self.user, is_public=False)\n+        self.citation = AlternativeCitationFactory(name=\"name\", text=\"text\")\n+        self.public.alternativeCitations.append(self.citation)\n+        self.private.alternativeCitations.append(self.citation)\n+        self.public.add_contributor(self.user_two, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True)\n+        self.private.add_contributor(self.user_two, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True)\n+        self.public.save()\n+        self.private.save()\n+        self.public_url = '/{}nodes/{}/citations/'.format(API_BASE, self.public._id)\n+        self.private_url = '/{}nodes/{}/citations/'.format(API_BASE, self.private._id)\n+        self.citation.public_url = self.public_url + '{}/'.format(self.citation._id)\n+        self.citation.private_url = self.private_url + '{}/'.format(self.citation._id)\n+\n+    def payload(self, name=None, text=None, id=None):\n+        payload = {'data': {\n+            'type': 'citations',\n+            'attributes': {\n+                'name': name,\n+                'text': text\n+                }\n+            }\n+        }\n+        if id is not None:\n+            payload['data']['id'] = id\n+        return payload\n+\n+    def test_add_citation_admin_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(name='Test', text='Citation'), auth=self.user.auth)\n+        assert_equal(res.status_code, 201)\n+        self.public.reload()\n+        assert_equal(len(self.public.alternativeCitations), 2)\n+\n+    def test_add_citation_admin_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(name='Test', text='Citation'), auth=self.user.auth)\n+        assert_equal(res.status_code, 201)\n+        self.private.reload()\n+        assert_equal(len(self.private.alternativeCitations), 2)\n+\n+    def test_add_citation_non_admin_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(name='Test', text='Citation'), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.public.reload()\n+        assert_equal(len(self.public.alternativeCitations), 1)\n+\n+    def test_add_citation_non_admin_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(name='Test', text='Citation'), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.private.reload()\n+        assert_equal(len(self.private.alternativeCitations), 1)\n+\n+    def test_add_citation_non_contrib_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(name='Test', text='Citation'), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.public.reload()\n+        assert_equal(len(self.public.alternativeCitations), 1)\n+\n+    def test_add_citation_non_contrib_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(name='Test', text='Citation'), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.private.reload()\n+        assert_equal(len(self.private.alternativeCitations), 1)\n+\n+    def test_add_repeat_name_admin_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(name='name', text='Citation'), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+        assert_equal(len(res.json['errors']), 1)\n+        assert_equal(res.json['errors'][0]['detail'], \"There is already an alternative citation named 'name'\")\n+        assert_equal(len(self.public.alternativeCitations), 1)\n+\n+    def test_add_repeat_name_admin_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(name='name', text='Citation'), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+        assert_equal(len(res.json['errors']), 1)\n+        assert_equal(res.json['errors'][0]['detail'], \"There is already an alternative citation named 'name'\")\n+        assert_equal(len(self.private.alternativeCitations), 1)\n+\n+    def test_add_repeat_name_non_admin_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(name='name', text='Citation'), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.public.reload()\n+        assert_equal(len(self.public.alternativeCitations), 1)\n+\n+    def test_add_repeat_name_non_admin_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(name='name', text='Citation'), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.private.reload()\n+        assert_equal(len(self.private.alternativeCitations), 1)\n+\n+    def test_add_repeat_name_non_contrib_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(name='name', text='Citation'), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.public.reload()\n+        assert_equal(len(self.public.alternativeCitations), 1)\n+\n+    def test_add_repeat_name_non_contrib_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(name='name', text='Citation'), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.private.reload()\n+        assert_equal(len(self.private.alternativeCitations), 1)\n+\n+    def test_add_repeat_text_admin_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(name='Citation', text='text'), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+        assert_equal(len(res.json['errors']), 1)\n+        assert_equal(res.json['errors'][0]['detail'], \"Citation matches 'name'\")\n+        self.public.reload()\n+        assert_equal(len(self.public.alternativeCitations), 1)\n+\n+    def test_add_repeat_text_admin_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(name='Citation', text='text'), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+        assert_equal(len(res.json['errors']), 1)\n+        assert_equal(res.json['errors'][0]['detail'], \"Citation matches 'name'\")\n+        self.private.reload()\n+        assert_equal(len(self.private.alternativeCitations), 1)\n+\n+    def test_add_repeat_text_non_admin_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(name='Citation', text='text'), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.public.reload()\n+        assert_equal(len(self.public.alternativeCitations), 1)\n+\n+    def test_add_repeat_text_non_admin_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(name='Citation', text='text'), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.private.reload()\n+        assert_equal(len(self.private.alternativeCitations), 1)\n+\n+    def test_add_repeat_text_non_contrib_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(name='Citation', text='text'), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.public.reload()\n+        assert_equal(len(self.public.alternativeCitations), 1)\n+\n+    def test_add_repeat_text_non_contrib_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(name='Citation', text='text'), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.private.reload()\n+        assert_equal(len(self.private.alternativeCitations), 1)\n+\n+    def test_add_repeat_name_and_text_admin_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(name='name', text='text'), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+        assert_equal(len(res.json['errors']), 2)\n+        assert_equal(res.json['errors'][0]['detail'], \"There is already an alternative citation named 'name'\")\n+        assert_equal(res.json['errors'][1]['detail'], \"Citation matches 'name'\")\n+        self.public.reload()\n+        assert_equal(len(self.public.alternativeCitations), 1)\n+\n+    def test_add_repeat_name_and_text_admin_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(name='name', text='text'), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+        assert_equal(len(res.json['errors']), 2)\n+        assert_equal(res.json['errors'][0]['detail'], \"There is already an alternative citation named 'name'\")\n+        assert_equal(res.json['errors'][1]['detail'], \"Citation matches 'name'\")\n+        self.private.reload()\n+        assert_equal(len(self.private.alternativeCitations), 1)\n+\n+    def test_add_repeat_name_and_text_non_admin_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(name='name', text='text'), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.public.reload()\n+        assert_equal(len(self.public.alternativeCitations), 1)\n+\n+    def test_add_repeat_name_and_text_non_admin_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(name='name', text='text'), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.private.reload()\n+        assert_equal(len(self.private.alternativeCitations), 1)\n+\n+    def test_add_repeat_name_and_text_non_contrib_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(name='name', text='text'), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.public.reload()\n+        assert_equal(len(self.public.alternativeCitations), 1)\n+\n+    def test_add_repeat_name_and_text_non_contrib_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(name='name', text='text'), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.private.reload()\n+        assert_equal(len(self.private.alternativeCitations), 1)\n+\n+    def test_add_no_name_admin_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(text='new text'), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+    def test_add_no_name_admin_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(text='new text'), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+    def test_add_no_name_non_admin_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(text='new text'), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+    def test_add_no_name_non_admin_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(text='new text'), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+    def test_add_no_name_non_contrib_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(text='new text'), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+    def test_add_no_name_non_contrib_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(text='new text'), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+    def test_add_no_text_admin_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(name='new name'), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+    def test_add_no_text_admin_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(name='new name'), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+    def test_add_no_text_non_admin_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(name='new name'), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+    def test_add_no_text_non_admin_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(name='new name'), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+    def test_add_no_text_non_contrib_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(name='new name'), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+    def test_add_no_text_non_contrib_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(name='new name'), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+    def test_add_empty_admin_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+    def test_add_empty_admin_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+    def test_add_empty_non_admin_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+    def test_add_empty_non_admin_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+    def test_add_empty_non_contrib_public(self):\n+        res = self.app.post_json_api(self.public_url, self.payload(), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+    def test_add_empty_non_contrib_private(self):\n+        res = self.app.post_json_api(self.private_url, self.payload(), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+\n+class TestUpdateAlternativeCitations(ApiTestCase):\n+    def setUp(self):\n+        super(TestUpdateAlternativeCitations, self).setUp()\n+        self.user = AuthUserFactory()\n+        self.user_two = AuthUserFactory()\n+        self.user_three = AuthUserFactory()\n+\n+        self.public = ProjectFactory(creator=self.user, is_public=True)\n+        self.private = ProjectFactory(creator=self.user, is_public=False)\n+        self.citation = AlternativeCitationFactory(name=\"name\", text=\"text\")\n+        self.citation2 = AlternativeCitationFactory(name=\"name2\", text=\"text2\")\n+        self.public.alternativeCitations.append(self.citation)\n+        self.private.alternativeCitations.append(self.citation)\n+        self.public.alternativeCitations.append(self.citation2)\n+        self.private.alternativeCitations.append(self.citation2)\n+        self.public.add_contributor(self.user_two, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True)\n+        self.private.add_contributor(self.user_two, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True)\n+        self.public.save()\n+        self.private.save()\n+        self.public_url = '/{}nodes/{}/citations/'.format(API_BASE, self.public._id)\n+        self.private_url = '/{}nodes/{}/citations/'.format(API_BASE, self.private._id)\n+        self.citation.public_url = self.public_url + '{}/'.format(self.citation._id)\n+        self.citation.private_url = self.private_url + '{}/'.format(self.citation._id)\n+\n+    def payload(self, name=None, text=None, id=None):\n+        payload = {'data': {\n+            'type': 'citations',\n+            'attributes': {}\n+            }\n+        }\n+        if name is not None:\n+            payload['data']['attributes']['name'] = name\n+        if text is not None:\n+            payload['data']['attributes']['text'] = text\n+        if id is not None:\n+            payload['data']['id'] = id\n+        return payload\n+\n+    def test_update_citation_name_admin_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"Test\", text=\"text\", id=self.citation._id), auth=self.user.auth)\n+        assert_equal(res.status_code, 200)\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"Test\")\n+\n+    def test_update_citation_name_admin_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"Test\", text=\"text\", id=self.citation._id), auth=self.user.auth)\n+        assert_equal(res.status_code, 200)\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"Test\")\n+\n+    def test_update_citation_name_non_admin_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"Test\", text=\"text\", id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_name_non_admin_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"Test\", text=\"text\", id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_name_non_contrib_public(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"Test\", text=\"text\", id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_name_non_contrib_private(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"Test\", text=\"text\", id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_text_admin_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"name\", text=\"Test\", id=self.citation._id), auth=self.user.auth)\n+        assert_equal(res.status_code, 200)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"Test\")\n+\n+    def test_update_citation_text_admin_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"name\", text=\"Test\", id=self.citation._id), auth=self.user.auth)\n+        assert_equal(res.status_code, 200)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"Test\")\n+\n+    def test_update_citation_text_non_admin_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"name\", text=\"Test\", id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+\n+    def test_update_citation_text_non_admin_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"name\", text=\"Test\", id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+\n+    def test_update_citation_text_non_contrib_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"name\", text=\"Test\", id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+\n+    def test_update_citation_text_non_contrib_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"name\", text=\"Test\", id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+\n+    def test_update_citation_admin_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"Test\", text=\"Test\", id=self.citation._id), auth=self.user.auth)\n+        assert_equal(res.status_code, 200)\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"Test\")\n+        assert_equal(self.citation.text, \"Test\")\n+\n+    def test_update_citation_admin_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"Test\", text=\"Test\", id=self.citation._id), auth=self.user.auth)\n+        assert_equal(res.status_code, 200)\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"Test\")\n+        assert_equal(self.citation.text, \"Test\")\n+\n+    def test_update_citation_non_admin_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"Test\", text=\"Test\", id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"name\")\n+        assert_equal(self.citation.text, \"text\")\n+\n+    def test_update_citation_non_admin_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"Test\", text=\"Test\", id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"name\")\n+        assert_equal(self.citation.text, \"text\")\n+\n+    def test_update_citation_non_contrib_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"Test\", text=\"Test\", id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"name\")\n+        assert_equal(self.citation.text, \"text\")\n+\n+    def test_update_citation_non_contrib_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"Test\", text=\"Test\", id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"name\")\n+        assert_equal(self.citation.text, \"text\")\n+\n+    def test_update_citation_repeat_name_admin_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"name2\", text=\"Test\", id=self.citation._id), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+        assert_equal(len(res.json['errors']), 1)\n+        assert_equal(res.json['errors'][0]['detail'], \"There is already an alternative citation named 'name2'\")\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_repeat_name_admin_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"name2\", text=\"Test\", id=self.citation._id), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+        assert_equal(len(res.json['errors']), 1)\n+        assert_equal(res.json['errors'][0]['detail'], \"There is already an alternative citation named 'name2'\")\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_repeat_name_non_admin_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"name2\", text=\"Test\", id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_repeat_name_non_admin_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"name2\", text=\"Test\", id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_repeat_name_non_contrib_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"name2\", text=\"Test\", id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_repeat_name_non_contrib_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"name2\", text=\"Test\", id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_repeat_text_admin_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"name\", text=\"text2\", id=self.citation._id), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+        assert_equal(len(res.json['errors']), 1)\n+        assert_equal(res.json['errors'][0]['detail'], \"Citation matches 'name2'\")\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+\n+    def test_update_citation_repeat_text_admin_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"name\", text=\"text2\", id=self.citation._id), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+        assert_equal(len(res.json['errors']), 1)\n+        assert_equal(res.json['errors'][0]['detail'], \"Citation matches 'name2'\")\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+\n+    def test_update_citation_repeat_text_non_admin_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"name\", text=\"text2\", id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+\n+    def test_update_citation_repeat_text_non_admin_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"name\", text=\"text2\", id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+\n+    def test_update_citation_repeat_text_non_contrib_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"name\", text=\"text2\", id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+\n+    def test_update_citation_repeat_text_non_contrib_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"name\", text=\"text2\", id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+\n+    def test_update_citation_repeat_admin_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"name2\", text=\"text2\", id=self.citation._id), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+        assert_equal(len(res.json['errors']), 2)\n+        assert_equal(res.json['errors'][0]['detail'], \"There is already an alternative citation named 'name2'\")\n+        assert_equal(res.json['errors'][1]['detail'], \"Citation matches 'name2'\")\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_repeat_admin_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"name2\", text=\"text2\", id=self.citation._id), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+        assert_equal(len(res.json['errors']), 2)\n+        assert_equal(res.json['errors'][0]['detail'], \"There is already an alternative citation named 'name2'\")\n+        assert_equal(res.json['errors'][1]['detail'], \"Citation matches 'name2'\")\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_repeat_non_admin_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"name2\", text=\"text2\", id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_repeat_non_admin_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"name2\", text=\"text2\", id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_repeat_non_contrib_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"name2\", text=\"text2\", id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_repeat_non_contrib_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"name2\", text=\"text2\", id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_empty_admin_public(self):\n+        res = self.app.patch_json_api(self.citation.public_url, self.payload(id=self.citation._id), auth=self.user.auth)\n+        assert_equal(res.status_code, 200)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_empty_admin_private(self):\n+        res = self.app.patch_json_api(self.citation.private_url, self.payload(id=self.citation._id), auth=self.user.auth)\n+        assert_equal(res.status_code, 200)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_empty_non_admin_public(self):\n+        res = self.app.patch_json_api(self.citation.public_url, self.payload(id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_empty_non_admin_private(self):\n+        res = self.app.patch_json_api(self.citation.private_url, self.payload(id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_empty_non_contrib_public(self):\n+        res = self.app.patch_json_api(self.citation.public_url, self.payload(id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_empty_non_contrib_private(self):\n+        res = self.app.patch_json_api(self.citation.private_url, self.payload(id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_name_only_admin_public(self):\n+        res = self.app.patch_json_api(self.citation.public_url, self.payload(name='new name', id=self.citation._id), auth=self.user.auth)\n+        assert_equal(res.status_code, 200)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"new name\")\n+\n+    def test_update_citation_name_only_admin_private(self):\n+        res = self.app.patch_json_api(self.citation.private_url, self.payload(name='new name', id=self.citation._id), auth=self.user.auth)\n+        assert_equal(res.status_code, 200)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"new name\")\n+\n+    def test_update_citation_name_only_non_admin_public(self):\n+        res = self.app.patch_json_api(self.citation.public_url, self.payload(name='new name', id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_name_only_non_admin_private(self):\n+        res = self.app.patch_json_api(self.citation.private_url, self.payload(name='new name', id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_name_only_non_contrib_public(self):\n+        res = self.app.patch_json_api(self.citation.public_url, self.payload(name='new name', id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_name_only_non_contrib_private(self):\n+        res = self.app.patch_json_api(self.citation.private_url, self.payload(name='new name', id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_text_only_admin_public(self):\n+        res = self.app.patch_json_api(self.citation.public_url, self.payload(text='new text', id=self.citation._id), auth=self.user.auth)\n+        assert_equal(res.status_code, 200)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"new text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_text_only_admin_private(self):\n+        res = self.app.patch_json_api(self.citation.private_url, self.payload(text='new text', id=self.citation._id), auth=self.user.auth)\n+        assert_equal(res.status_code, 200)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"new text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_text_only_non_admin_public(self):\n+        res = self.app.patch_json_api(self.citation.public_url, self.payload(text='new text', id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_text_only_non_admin_private(self):\n+        res = self.app.patch_json_api(self.citation.private_url, self.payload(text='new text', id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_text_only_non_contrib_public(self):\n+        res = self.app.patch_json_api(self.citation.public_url, self.payload(text='new text', id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_text_only_non_contrib_private(self):\n+        res = self.app.patch_json_api(self.citation.private_url, self.payload(text='new text', id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_name_only_repeat_admin_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"name2\", id=self.citation._id), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_name_only_repeat_admin_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"name2\", id=self.citation._id), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_name_only_repeat_non_admin_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"name2\", id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_name_only_repeat_non_admin_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"name2\", id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_name_only_repeat_non_contrib_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(name=\"name2\", id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_name_only_repeat_non_contrib_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(name=\"name2\", id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_text_only_repeat_admin_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(text=\"text2\", id=self.citation._id), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_text_only_repeat_admin_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(text=\"text2\", id=self.citation._id), auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 400)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_text_only_repeat_non_admin_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(text=\"text2\", id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_text_only_repeat_non_admin_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(text=\"text2\", id=self.citation._id), auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_text_only_repeat_non_contrib_public(self):\n+        res = self.app.put_json_api(self.citation.public_url, self.payload(text=\"text2\", id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+    def test_update_citation_text_only_repeat_non_contrib_private(self):\n+        res = self.app.put_json_api(self.citation.private_url, self.payload(text=\"text2\", id=self.citation._id), auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.citation.reload()\n+        assert_equal(self.citation.text, \"text\")\n+        assert_equal(self.citation.name, \"name\")\n+\n+\n+class TestDeleteAlternativeCitations(ApiTestCase):\n+    def setUp(self):\n+        super(TestDeleteAlternativeCitations, self).setUp()\n+        self.user = AuthUserFactory()\n+        self.user_two = AuthUserFactory()\n+        self.user_three = AuthUserFactory()\n+\n+        self.public = ProjectFactory(creator=self.user, is_public=True)\n+        self.private = ProjectFactory(creator=self.user, is_public=False)\n+        self.citation = AlternativeCitationFactory(name=\"name\", text=\"text\")\n+        self.public.alternativeCitations.append(self.citation)\n+        self.private.alternativeCitations.append(self.citation)\n+        self.public.save()\n+        self.private.save()\n+        self.public.add_contributor(self.user_two, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True)\n+        self.private.add_contributor(self.user_two, permissions=[permissions.READ, permissions.WRITE], visible=True, save=True)\n+        self.public_url = '/{}nodes/{}/citations/'.format(API_BASE, self.public._id)\n+        self.private_url = '/{}nodes/{}/citations/'.format(API_BASE, self.private._id)\n+        self.public_url_bad = self.public_url + '1/'\n+        self.private_url_bad = self.private_url + '1/'\n+        self.citation.public_url = self.public_url + '{}/'.format(self.citation._id)\n+        self.citation.private_url = self.private_url + '{}/'.format(self.citation._id)\n+\n+    def test_delete_citation_admin_public(self):\n+        res = self.app.delete_json_api(self.citation.public_url, auth=self.user.auth)\n+        assert_equal(res.status_code, 204)\n+        self.public.reload()\n+        assert_equal(len(self.public.alternativeCitations), 0)\n+\n+    def test_delete_citation_admin_private(self):\n+        res = self.app.delete_json_api(self.citation.private_url, auth=self.user.auth)\n+        assert_equal(res.status_code, 204)\n+        self.private.reload()\n+        assert_equal(len(self.private.alternativeCitations), 0)\n+\n+    def test_delete_citation_non_admin_public(self):\n+        res = self.app.delete_json_api(self.citation.public_url, auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.public.reload()\n+        assert_equal(len(self.public.alternativeCitations), 1)\n+\n+    def test_delete_citation_non_admin_private(self):\n+        res = self.app.delete_json_api(self.citation.private_url, auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.private.reload()\n+        assert_equal(len(self.private.alternativeCitations), 1)\n+\n+    def test_delete_citation_non_contrib_public(self):\n+        res = self.app.delete_json_api(self.citation.public_url, auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.public.reload()\n+        assert_equal(len(self.public.alternativeCitations), 1)\n+\n+    def test_delete_citation_non_contrib_private(self):\n+        res = self.app.delete_json_api(self.citation.private_url, auth=self.user_three.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)\n+        self.private.reload()\n+        assert_equal(len(self.private.alternativeCitations), 1)\n+\n+    def test_delete_citation_admin_404_public(self):\n+        res = self.app.delete_json_api(self.public_url_bad, auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 404)\n+        self.public.reload()\n+        assert_equal(len(self.public.alternativeCitations), 1)\n+\n+    def test_delete_citation_admin_404_private(self):\n+        res = self.app.delete_json_api(self.private_url_bad, auth=self.user.auth, expect_errors=True)\n+        assert_equal(res.status_code, 404)\n+        self.private.reload()\n+        assert_equal(len(self.private.alternativeCitations), 1)\n+\n+    def test_delete_citation_non_admin_404_public(self):\n+        res = self.app.delete_json_api(self.public_url_bad, auth=self.user_two.auth, expect_errors=True)\n+        assert_equal(res.status_code, 403)","path":"api_tests/nodes/views/test_node_alternative_citations.py","position":842,"original_position":842,"commit_id":"5e20b3208ccda17a594b16574713b958c7204512","original_commit_id":"5e20b3208ccda17a594b16574713b958c7204512","user":{"login":"samanehsan","id":6414394,"avatar_url":"https://avatars.githubusercontent.com/u/6414394?v=3","gravatar_id":"","url":"https://api.github.com/users/samanehsan","html_url":"https://github.com/samanehsan","followers_url":"https://api.github.com/users/samanehsan/followers","following_url":"https://api.github.com/users/samanehsan/following{/other_user}","gists_url":"https://api.github.com/users/samanehsan/gists{/gist_id}","starred_url":"https://api.github.com/users/samanehsan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/samanehsan/subscriptions","organizations_url":"https://api.github.com/users/samanehsan/orgs","repos_url":"https://api.github.com/users/samanehsan/repos","events_url":"https://api.github.com/users/samanehsan/events{/privacy}","received_events_url":"https://api.github.com/users/samanehsan/received_events","type":"User","site_admin":false},"body":"Some of these tests have \"404\" in the test name, but return `403` errors. Can you change the name of these tests? ","created_at":"2015-12-03T18:35:03Z","updated_at":"2015-12-03T18:35:03Z","html_url":"https://github.com/CenterForOpenScience/osf.io/pull/4514#discussion_r46591288","pull_request_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4514","_links":{"self":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/comments/46591288"},"html":{"href":"https://github.com/CenterForOpenScience/osf.io/pull/4514#discussion_r46591288"},"pull_request":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4514"}}},"pull_request":{"url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4514","id":48780769,"html_url":"https://github.com/CenterForOpenScience/osf.io/pull/4514","diff_url":"https://github.com/CenterForOpenScience/osf.io/pull/4514.diff","patch_url":"https://github.com/CenterForOpenScience/osf.io/pull/4514.patch","issue_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/4514","number":4514,"state":"open","locked":false,"title":"[feature] alternative citations","user":{"login":"ticklemepierce","id":8229937,"avatar_url":"https://avatars.githubusercontent.com/u/8229937?v=3","gravatar_id":"","url":"https://api.github.com/users/ticklemepierce","html_url":"https://github.com/ticklemepierce","followers_url":"https://api.github.com/users/ticklemepierce/followers","following_url":"https://api.github.com/users/ticklemepierce/following{/other_user}","gists_url":"https://api.github.com/users/ticklemepierce/gists{/gist_id}","starred_url":"https://api.github.com/users/ticklemepierce/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ticklemepierce/subscriptions","organizations_url":"https://api.github.com/users/ticklemepierce/orgs","repos_url":"https://api.github.com/users/ticklemepierce/repos","events_url":"https://api.github.com/users/ticklemepierce/events{/privacy}","received_events_url":"https://api.github.com/users/ticklemepierce/received_events","type":"User","site_admin":false},"body":"This feature allows for admins on a project to create alternative citations that display underneath of the MLA/APA/Chicago citations that are provided by default.  This feature covers the following use cases:\r\n\r\n * I made an OSF project to include materials as a supplement to my journal article and would like any citations of those materials to contribute to citations of my paper\r\n * I made an OSF project and then was published, giving me a DOI that I want to use as a replacement for the citation provided by the OSF\r\n * I made an OSF project that has components that each represent a study in a paper, and I would like each of those components to have the same citation\r\n * I haven't figured out how to change my name in my profile and want to edit the citation to reflect the name I usually use to publish with. \r\n * I have a publication that I would like visitors on the OSF to be able to find, and correcting the citation for my OSF project to match the citation would increase its relevance in search.","created_at":"2015-10-26T18:47:46Z","updated_at":"2015-12-03T18:35:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2468178d561ae55165a4414344fa8d9214bedb01","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4514/commits","review_comments_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4514/comments","review_comment_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/comments{/number}","comments_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/4514/comments","statuses_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/statuses/5e20b3208ccda17a594b16574713b958c7204512","head":{"label":"ticklemepierce:feature/alternativeCitations","ref":"feature/alternativeCitations","sha":"5e20b3208ccda17a594b16574713b958c7204512","user":{"login":"ticklemepierce","id":8229937,"avatar_url":"https://avatars.githubusercontent.com/u/8229937?v=3","gravatar_id":"","url":"https://api.github.com/users/ticklemepierce","html_url":"https://github.com/ticklemepierce","followers_url":"https://api.github.com/users/ticklemepierce/followers","following_url":"https://api.github.com/users/ticklemepierce/following{/other_user}","gists_url":"https://api.github.com/users/ticklemepierce/gists{/gist_id}","starred_url":"https://api.github.com/users/ticklemepierce/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ticklemepierce/subscriptions","organizations_url":"https://api.github.com/users/ticklemepierce/orgs","repos_url":"https://api.github.com/users/ticklemepierce/repos","events_url":"https://api.github.com/users/ticklemepierce/events{/privacy}","received_events_url":"https://api.github.com/users/ticklemepierce/received_events","type":"User","site_admin":false},"repo":{"id":35901786,"name":"osf.io","full_name":"ticklemepierce/osf.io","owner":{"login":"ticklemepierce","id":8229937,"avatar_url":"https://avatars.githubusercontent.com/u/8229937?v=3","gravatar_id":"","url":"https://api.github.com/users/ticklemepierce","html_url":"https://github.com/ticklemepierce","followers_url":"https://api.github.com/users/ticklemepierce/followers","following_url":"https://api.github.com/users/ticklemepierce/following{/other_user}","gists_url":"https://api.github.com/users/ticklemepierce/gists{/gist_id}","starred_url":"https://api.github.com/users/ticklemepierce/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ticklemepierce/subscriptions","organizations_url":"https://api.github.com/users/ticklemepierce/orgs","repos_url":"https://api.github.com/users/ticklemepierce/repos","events_url":"https://api.github.com/users/ticklemepierce/events{/privacy}","received_events_url":"https://api.github.com/users/ticklemepierce/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ticklemepierce/osf.io","description":"Facilitating Open Science","fork":true,"url":"https://api.github.com/repos/ticklemepierce/osf.io","forks_url":"https://api.github.com/repos/ticklemepierce/osf.io/forks","keys_url":"https://api.github.com/repos/ticklemepierce/osf.io/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ticklemepierce/osf.io/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ticklemepierce/osf.io/teams","hooks_url":"https://api.github.com/repos/ticklemepierce/osf.io/hooks","issue_events_url":"https://api.github.com/repos/ticklemepierce/osf.io/issues/events{/number}","events_url":"https://api.github.com/repos/ticklemepierce/osf.io/events","assignees_url":"https://api.github.com/repos/ticklemepierce/osf.io/assignees{/user}","branches_url":"https://api.github.com/repos/ticklemepierce/osf.io/branches{/branch}","tags_url":"https://api.github.com/repos/ticklemepierce/osf.io/tags","blobs_url":"https://api.github.com/repos/ticklemepierce/osf.io/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ticklemepierce/osf.io/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ticklemepierce/osf.io/git/refs{/sha}","trees_url":"https://api.github.com/repos/ticklemepierce/osf.io/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ticklemepierce/osf.io/statuses/{sha}","languages_url":"https://api.github.com/repos/ticklemepierce/osf.io/languages","stargazers_url":"https://api.github.com/repos/ticklemepierce/osf.io/stargazers","contributors_url":"https://api.github.com/repos/ticklemepierce/osf.io/contributors","subscribers_url":"https://api.github.com/repos/ticklemepierce/osf.io/subscribers","subscription_url":"https://api.github.com/repos/ticklemepierce/osf.io/subscription","commits_url":"https://api.github.com/repos/ticklemepierce/osf.io/commits{/sha}","git_commits_url":"https://api.github.com/repos/ticklemepierce/osf.io/git/commits{/sha}","comments_url":"https://api.github.com/repos/ticklemepierce/osf.io/comments{/number}","issue_comment_url":"https://api.github.com/repos/ticklemepierce/osf.io/issues/comments{/number}","contents_url":"https://api.github.com/repos/ticklemepierce/osf.io/contents/{+path}","compare_url":"https://api.github.com/repos/ticklemepierce/osf.io/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ticklemepierce/osf.io/merges","archive_url":"https://api.github.com/repos/ticklemepierce/osf.io/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ticklemepierce/osf.io/downloads","issues_url":"https://api.github.com/repos/ticklemepierce/osf.io/issues{/number}","pulls_url":"https://api.github.com/repos/ticklemepierce/osf.io/pulls{/number}","milestones_url":"https://api.github.com/repos/ticklemepierce/osf.io/milestones{/number}","notifications_url":"https://api.github.com/repos/ticklemepierce/osf.io/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ticklemepierce/osf.io/labels{/name}","releases_url":"https://api.github.com/repos/ticklemepierce/osf.io/releases{/id}","created_at":"2015-05-19T18:50:57Z","updated_at":"2015-05-19T18:51:00Z","pushed_at":"2015-12-03T15:50:54Z","git_url":"git://github.com/ticklemepierce/osf.io.git","ssh_url":"git@github.com:ticklemepierce/osf.io.git","clone_url":"https://github.com/ticklemepierce/osf.io.git","svn_url":"https://github.com/ticklemepierce/osf.io","homepage":"http://osf.io","size":108023,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"develop"}},"base":{"label":"CenterForOpenScience:develop","ref":"develop","sha":"1019ac80c1263b3f675ebd7c9c2442d4df9faf33","user":{"login":"CenterForOpenScience","id":3344584,"avatar_url":"https://avatars.githubusercontent.com/u/3344584?v=3","gravatar_id":"","url":"https://api.github.com/users/CenterForOpenScience","html_url":"https://github.com/CenterForOpenScience","followers_url":"https://api.github.com/users/CenterForOpenScience/followers","following_url":"https://api.github.com/users/CenterForOpenScience/following{/other_user}","gists_url":"https://api.github.com/users/CenterForOpenScience/gists{/gist_id}","starred_url":"https://api.github.com/users/CenterForOpenScience/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CenterForOpenScience/subscriptions","organizations_url":"https://api.github.com/users/CenterForOpenScience/orgs","repos_url":"https://api.github.com/users/CenterForOpenScience/repos","events_url":"https://api.github.com/users/CenterForOpenScience/events{/privacy}","received_events_url":"https://api.github.com/users/CenterForOpenScience/received_events","type":"Organization","site_admin":false},"repo":{"id":10199599,"name":"osf.io","full_name":"CenterForOpenScience/osf.io","owner":{"login":"CenterForOpenScience","id":3344584,"avatar_url":"https://avatars.githubusercontent.com/u/3344584?v=3","gravatar_id":"","url":"https://api.github.com/users/CenterForOpenScience","html_url":"https://github.com/CenterForOpenScience","followers_url":"https://api.github.com/users/CenterForOpenScience/followers","following_url":"https://api.github.com/users/CenterForOpenScience/following{/other_user}","gists_url":"https://api.github.com/users/CenterForOpenScience/gists{/gist_id}","starred_url":"https://api.github.com/users/CenterForOpenScience/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CenterForOpenScience/subscriptions","organizations_url":"https://api.github.com/users/CenterForOpenScience/orgs","repos_url":"https://api.github.com/users/CenterForOpenScience/repos","events_url":"https://api.github.com/users/CenterForOpenScience/events{/privacy}","received_events_url":"https://api.github.com/users/CenterForOpenScience/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/CenterForOpenScience/osf.io","description":"Facilitating Open Science","fork":false,"url":"https://api.github.com/repos/CenterForOpenScience/osf.io","forks_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/forks","keys_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/keys{/key_id}","collaborators_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/teams","hooks_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/hooks","issue_events_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/events{/number}","events_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/events","assignees_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/assignees{/user}","branches_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/branches{/branch}","tags_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/tags","blobs_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/git/refs{/sha}","trees_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/git/trees{/sha}","statuses_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/statuses/{sha}","languages_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/languages","stargazers_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/stargazers","contributors_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/contributors","subscribers_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/subscribers","subscription_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/subscription","commits_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/commits{/sha}","git_commits_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/git/commits{/sha}","comments_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/comments{/number}","issue_comment_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/comments{/number}","contents_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/contents/{+path}","compare_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/compare/{base}...{head}","merges_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/merges","archive_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/downloads","issues_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues{/number}","pulls_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls{/number}","milestones_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/milestones{/number}","notifications_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/labels{/name}","releases_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/releases{/id}","created_at":"2013-05-21T15:53:37Z","updated_at":"2015-12-03T14:54:47Z","pushed_at":"2015-12-03T17:06:15Z","git_url":"git://github.com/CenterForOpenScience/osf.io.git","ssh_url":"git@github.com:CenterForOpenScience/osf.io.git","clone_url":"https://github.com/CenterForOpenScience/osf.io.git","svn_url":"https://github.com/CenterForOpenScience/osf.io","homepage":"http://osf.io","size":223078,"stargazers_count":167,"watchers_count":167,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":134,"mirror_url":null,"open_issues_count":348,"forks":134,"open_issues":348,"watchers":167,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4514"},"html":{"href":"https://github.com/CenterForOpenScience/osf.io/pull/4514"},"issue":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/4514"},"comments":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/4514/comments"},"review_comments":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4514/comments"},"review_comment":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4514/commits"},"statuses":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/statuses/5e20b3208ccda17a594b16574713b958c7204512"}}}}