]> git.ipfire.org Git - thirdparty/patchwork.git/commitdiff
tests: Split 'test_rest_api'
authorStephen Finucane <stephen@that.guru>
Sun, 25 Mar 2018 18:28:19 +0000 (19:28 +0100)
committerStephen Finucane <stephen@that.guru>
Sat, 7 Apr 2018 16:43:26 +0000 (17:43 +0100)
Lay the tests out per the main code.

Signed-off-by: Stephen Finucane <stephen@that.guru>
patchwork/tests/api/__init__.py [new file with mode: 0644]
patchwork/tests/api/test_bundle.py [new file with mode: 0644]
patchwork/tests/api/test_check.py [new file with mode: 0644]
patchwork/tests/api/test_cover.py [new file with mode: 0644]
patchwork/tests/api/test_patch.py [new file with mode: 0644]
patchwork/tests/api/test_person.py [new file with mode: 0644]
patchwork/tests/api/test_project.py [new file with mode: 0644]
patchwork/tests/api/test_user.py [new file with mode: 0644]
patchwork/tests/test_rest_api.py [deleted file]

diff --git a/patchwork/tests/api/__init__.py b/patchwork/tests/api/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/patchwork/tests/api/test_bundle.py b/patchwork/tests/api/test_bundle.py
new file mode 100644 (file)
index 0000000..0cf5f4b
--- /dev/null
@@ -0,0 +1,134 @@
+# Patchwork - automated patch tracking system
+# Copyright (C) 2016 Linaro Corporation
+#
+# This file is part of the Patchwork package.
+#
+# Patchwork is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Patchwork is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Patchwork; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import unittest
+
+from django.conf import settings
+
+from patchwork.compat import reverse
+from patchwork.tests.utils import create_bundle
+from patchwork.tests.utils import create_maintainer
+from patchwork.tests.utils import create_project
+from patchwork.tests.utils import create_user
+
+if settings.ENABLE_REST_API:
+    from rest_framework import status
+    from rest_framework.test import APITestCase
+else:
+    # stub out APITestCase
+    from django.test import TestCase
+    APITestCase = TestCase  # noqa
+
+
+@unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API')
+class TestBundleAPI(APITestCase):
+    fixtures = ['default_tags']
+
+    @staticmethod
+    def api_url(item=None):
+        if item is None:
+            return reverse('api-bundle-list')
+        return reverse('api-bundle-detail', args=[item])
+
+    def assertSerialized(self, bundle_obj, bundle_json):
+        self.assertEqual(bundle_obj.id, bundle_json['id'])
+        self.assertEqual(bundle_obj.name, bundle_json['name'])
+        self.assertEqual(bundle_obj.public, bundle_json['public'])
+        self.assertIn(bundle_obj.get_mbox_url(), bundle_json['mbox'])
+
+        # nested fields
+
+        self.assertEqual(bundle_obj.patches.count(),
+                         len(bundle_json['patches']))
+        self.assertEqual(bundle_obj.owner.id,
+                         bundle_json['owner']['id'])
+        self.assertEqual(bundle_obj.project.id,
+                         bundle_json['project']['id'])
+
+    def test_list(self):
+        """Validate we can list bundles."""
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(0, len(resp.data))
+
+        user = create_user(username='myuser')
+        project = create_project(linkname='myproject')
+        bundle_public = create_bundle(public=True, owner=user,
+                                      project=project)
+        bundle_private = create_bundle(public=False, owner=user,
+                                       project=project)
+
+        # anonymous users
+        # should only see the public bundle
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(1, len(resp.data))
+        bundle_rsp = resp.data[0]
+        self.assertSerialized(bundle_public, bundle_rsp)
+
+        # authenticated user
+        # should see the public and private bundle
+        self.client.force_authenticate(user=user)
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(2, len(resp.data))
+        for bundle_rsp, bundle_obj in zip(
+                resp.data, [bundle_public, bundle_private]):
+            self.assertSerialized(bundle_obj, bundle_rsp)
+
+        # test filtering by project
+        resp = self.client.get(self.api_url(), {'project': 'myproject'})
+        self.assertEqual([bundle_public.id, bundle_private.id],
+                         [x['id'] for x in resp.data])
+        resp = self.client.get(self.api_url(), {'project': 'invalidproject'})
+        self.assertEqual(0, len(resp.data))
+
+        # test filtering by owner, both ID and username
+        resp = self.client.get(self.api_url(), {'owner': user.id})
+        self.assertEqual([bundle_public.id, bundle_private.id],
+                         [x['id'] for x in resp.data])
+        resp = self.client.get(self.api_url(), {'owner': 'myuser'})
+        self.assertEqual([bundle_public.id, bundle_private.id],
+                         [x['id'] for x in resp.data])
+        resp = self.client.get(self.api_url(), {'owner': 'otheruser'})
+        self.assertEqual(0, len(resp.data))
+
+    def test_detail(self):
+        """Validate we can get a specific bundle."""
+        bundle = create_bundle(public=True)
+
+        resp = self.client.get(self.api_url(bundle.id))
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertSerialized(bundle, resp.data)
+
+    def test_create_update_delete(self):
+        """Ensure creates, updates and deletes aren't allowed"""
+        user = create_maintainer()
+        user.is_superuser = True
+        user.save()
+        self.client.force_authenticate(user=user)
+
+        resp = self.client.post(self.api_url(), {'email': 'foo@f.com'})
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
+
+        resp = self.client.patch(self.api_url(user.id), {'email': 'foo@f.com'})
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
+
+        resp = self.client.delete(self.api_url(1))
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
diff --git a/patchwork/tests/api/test_check.py b/patchwork/tests/api/test_check.py
new file mode 100644 (file)
index 0000000..6e3d68b
--- /dev/null
@@ -0,0 +1,121 @@
+# Patchwork - automated patch tracking system
+# Copyright (C) 2016 Linaro Corporation
+#
+# This file is part of the Patchwork package.
+#
+# Patchwork is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Patchwork is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Patchwork; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import unittest
+
+from django.conf import settings
+
+from patchwork.compat import reverse
+from patchwork.tests.utils import create_cover
+from patchwork.tests.utils import create_maintainer
+from patchwork.tests.utils import create_person
+from patchwork.tests.utils import create_project
+from patchwork.tests.utils import create_user
+
+if settings.ENABLE_REST_API:
+    from rest_framework import status
+    from rest_framework.test import APITestCase
+else:
+    # stub out APITestCase
+    from django.test import TestCase
+    APITestCase = TestCase  # noqa
+
+
+@unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API')
+class TestCoverLetterAPI(APITestCase):
+    fixtures = ['default_tags']
+
+    @staticmethod
+    def api_url(item=None):
+        if item is None:
+            return reverse('api-cover-list')
+        return reverse('api-cover-detail', args=[item])
+
+    def assertSerialized(self, cover_obj, cover_json):
+        self.assertEqual(cover_obj.id, cover_json['id'])
+        self.assertEqual(cover_obj.name, cover_json['name'])
+        self.assertIn(cover_obj.get_mbox_url(), cover_json['mbox'])
+
+        # nested fields
+
+        self.assertEqual(cover_obj.submitter.id,
+                         cover_json['submitter']['id'])
+
+    def test_list(self):
+        """Validate we can list cover letters."""
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(0, len(resp.data))
+
+        person_obj = create_person(email='test@example.com')
+        project_obj = create_project(linkname='myproject')
+        cover_obj = create_cover(project=project_obj, submitter=person_obj)
+
+        # anonymous user
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(1, len(resp.data))
+        self.assertSerialized(cover_obj, resp.data[0])
+
+        # authenticated user
+        user = create_user()
+        self.client.force_authenticate(user=user)
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(1, len(resp.data))
+        self.assertSerialized(cover_obj, resp.data[0])
+
+        # test filtering by project
+        resp = self.client.get(self.api_url(), {'project': 'myproject'})
+        self.assertEqual([cover_obj.id], [x['id'] for x in resp.data])
+        resp = self.client.get(self.api_url(), {'project': 'invalidproject'})
+        self.assertEqual(0, len(resp.data))
+
+        # test filtering by submitter, both ID and email
+        resp = self.client.get(self.api_url(), {'submitter': person_obj.id})
+        self.assertEqual([cover_obj.id], [x['id'] for x in resp.data])
+        resp = self.client.get(self.api_url(), {
+            'submitter': 'test@example.com'})
+        self.assertEqual([cover_obj.id], [x['id'] for x in resp.data])
+        resp = self.client.get(self.api_url(), {
+            'submitter': 'test@example.org'})
+        self.assertEqual(0, len(resp.data))
+
+    def test_detail(self):
+        """Validate we can get a specific cover letter."""
+        cover_obj = create_cover()
+
+        resp = self.client.get(self.api_url(cover_obj.id))
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertSerialized(cover_obj, resp.data)
+
+    def test_create_update_delete(self):
+        user = create_maintainer()
+        user.is_superuser = True
+        user.save()
+        self.client.force_authenticate(user=user)
+
+        resp = self.client.post(self.api_url(), {'name': 'test cover'})
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
+
+        resp = self.client.patch(self.api_url(), {'name': 'test cover'})
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
+
+        resp = self.client.delete(self.api_url())
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
diff --git a/patchwork/tests/api/test_cover.py b/patchwork/tests/api/test_cover.py
new file mode 100644 (file)
index 0000000..6e3d68b
--- /dev/null
@@ -0,0 +1,121 @@
+# Patchwork - automated patch tracking system
+# Copyright (C) 2016 Linaro Corporation
+#
+# This file is part of the Patchwork package.
+#
+# Patchwork is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Patchwork is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Patchwork; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import unittest
+
+from django.conf import settings
+
+from patchwork.compat import reverse
+from patchwork.tests.utils import create_cover
+from patchwork.tests.utils import create_maintainer
+from patchwork.tests.utils import create_person
+from patchwork.tests.utils import create_project
+from patchwork.tests.utils import create_user
+
+if settings.ENABLE_REST_API:
+    from rest_framework import status
+    from rest_framework.test import APITestCase
+else:
+    # stub out APITestCase
+    from django.test import TestCase
+    APITestCase = TestCase  # noqa
+
+
+@unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API')
+class TestCoverLetterAPI(APITestCase):
+    fixtures = ['default_tags']
+
+    @staticmethod
+    def api_url(item=None):
+        if item is None:
+            return reverse('api-cover-list')
+        return reverse('api-cover-detail', args=[item])
+
+    def assertSerialized(self, cover_obj, cover_json):
+        self.assertEqual(cover_obj.id, cover_json['id'])
+        self.assertEqual(cover_obj.name, cover_json['name'])
+        self.assertIn(cover_obj.get_mbox_url(), cover_json['mbox'])
+
+        # nested fields
+
+        self.assertEqual(cover_obj.submitter.id,
+                         cover_json['submitter']['id'])
+
+    def test_list(self):
+        """Validate we can list cover letters."""
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(0, len(resp.data))
+
+        person_obj = create_person(email='test@example.com')
+        project_obj = create_project(linkname='myproject')
+        cover_obj = create_cover(project=project_obj, submitter=person_obj)
+
+        # anonymous user
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(1, len(resp.data))
+        self.assertSerialized(cover_obj, resp.data[0])
+
+        # authenticated user
+        user = create_user()
+        self.client.force_authenticate(user=user)
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(1, len(resp.data))
+        self.assertSerialized(cover_obj, resp.data[0])
+
+        # test filtering by project
+        resp = self.client.get(self.api_url(), {'project': 'myproject'})
+        self.assertEqual([cover_obj.id], [x['id'] for x in resp.data])
+        resp = self.client.get(self.api_url(), {'project': 'invalidproject'})
+        self.assertEqual(0, len(resp.data))
+
+        # test filtering by submitter, both ID and email
+        resp = self.client.get(self.api_url(), {'submitter': person_obj.id})
+        self.assertEqual([cover_obj.id], [x['id'] for x in resp.data])
+        resp = self.client.get(self.api_url(), {
+            'submitter': 'test@example.com'})
+        self.assertEqual([cover_obj.id], [x['id'] for x in resp.data])
+        resp = self.client.get(self.api_url(), {
+            'submitter': 'test@example.org'})
+        self.assertEqual(0, len(resp.data))
+
+    def test_detail(self):
+        """Validate we can get a specific cover letter."""
+        cover_obj = create_cover()
+
+        resp = self.client.get(self.api_url(cover_obj.id))
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertSerialized(cover_obj, resp.data)
+
+    def test_create_update_delete(self):
+        user = create_maintainer()
+        user.is_superuser = True
+        user.save()
+        self.client.force_authenticate(user=user)
+
+        resp = self.client.post(self.api_url(), {'name': 'test cover'})
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
+
+        resp = self.client.patch(self.api_url(), {'name': 'test cover'})
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
+
+        resp = self.client.delete(self.api_url())
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
diff --git a/patchwork/tests/api/test_patch.py b/patchwork/tests/api/test_patch.py
new file mode 100644 (file)
index 0000000..909c1eb
--- /dev/null
@@ -0,0 +1,208 @@
+# Patchwork - automated patch tracking system
+# Copyright (C) 2016 Linaro Corporation
+#
+# This file is part of the Patchwork package.
+#
+# Patchwork is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Patchwork is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Patchwork; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+from email.utils import make_msgid
+import unittest
+
+from django.conf import settings
+
+from patchwork.compat import reverse
+from patchwork.models import Patch
+from patchwork.tests.utils import create_maintainer
+from patchwork.tests.utils import create_patch
+from patchwork.tests.utils import create_person
+from patchwork.tests.utils import create_project
+from patchwork.tests.utils import create_state
+from patchwork.tests.utils import create_user
+
+if settings.ENABLE_REST_API:
+    from rest_framework import status
+    from rest_framework.test import APITestCase
+else:
+    # stub out APITestCase
+    from django.test import TestCase
+    APITestCase = TestCase  # noqa
+
+
+@unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API')
+class TestPatchAPI(APITestCase):
+    fixtures = ['default_tags']
+
+    @staticmethod
+    def api_url(item=None):
+        if item is None:
+            return reverse('api-patch-list')
+        return reverse('api-patch-detail', args=[item])
+
+    def assertSerialized(self, patch_obj, patch_json):
+        self.assertEqual(patch_obj.id, patch_json['id'])
+        self.assertEqual(patch_obj.name, patch_json['name'])
+        self.assertEqual(patch_obj.msgid, patch_json['msgid'])
+        self.assertEqual(patch_obj.state.slug, patch_json['state'])
+        self.assertIn(patch_obj.get_mbox_url(), patch_json['mbox'])
+
+        # nested fields
+
+        self.assertEqual(patch_obj.submitter.id,
+                         patch_json['submitter']['id'])
+        self.assertEqual(patch_obj.project.id,
+                         patch_json['project']['id'])
+
+    def test_list(self):
+        """Validate we can list a patch."""
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(0, len(resp.data))
+
+        person_obj = create_person(email='test@example.com')
+        state_obj = create_state(name='Under Review')
+        project_obj = create_project(linkname='myproject')
+        patch_obj = create_patch(state=state_obj, project=project_obj,
+                                 submitter=person_obj)
+
+        # anonymous user
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(1, len(resp.data))
+        patch_rsp = resp.data[0]
+        self.assertSerialized(patch_obj, patch_rsp)
+        self.assertNotIn('headers', patch_rsp)
+        self.assertNotIn('content', patch_rsp)
+        self.assertNotIn('diff', patch_rsp)
+
+        # authenticated user
+        user = create_user()
+        self.client.force_authenticate(user=user)
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(1, len(resp.data))
+        patch_rsp = resp.data[0]
+        self.assertSerialized(patch_obj, patch_rsp)
+
+        # test filtering by state
+        resp = self.client.get(self.api_url(), {'state': 'under-review'})
+        self.assertEqual([patch_obj.id], [x['id'] for x in resp.data])
+        resp = self.client.get(self.api_url(), {'state': 'missing-state'})
+        self.assertEqual(0, len(resp.data))
+
+        # test filtering by project
+        resp = self.client.get(self.api_url(), {'project': 'myproject'})
+        self.assertEqual([patch_obj.id], [x['id'] for x in resp.data])
+        resp = self.client.get(self.api_url(), {'project': 'invalidproject'})
+        self.assertEqual(0, len(resp.data))
+
+        # test filtering by submitter, both ID and email
+        resp = self.client.get(self.api_url(), {'submitter': person_obj.id})
+        self.assertEqual([patch_obj.id], [x['id'] for x in resp.data])
+        resp = self.client.get(self.api_url(), {
+            'submitter': 'test@example.com'})
+        self.assertEqual([patch_obj.id], [x['id'] for x in resp.data])
+        resp = self.client.get(self.api_url(), {
+            'submitter': 'test@example.org'})
+        self.assertEqual(0, len(resp.data))
+
+    def test_detail(self):
+        """Validate we can get a specific patch."""
+        patch = create_patch(
+            content='Reviewed-by: Test User <test@example.com>\n')
+
+        resp = self.client.get(self.api_url(patch.id))
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertSerialized(patch, resp.data)
+        self.assertEqual(patch.headers, resp.data['headers'] or '')
+        self.assertEqual(patch.content, resp.data['content'])
+        self.assertEqual(patch.diff, resp.data['diff'])
+        self.assertEqual(0, len(resp.data['tags']))
+
+    def test_create(self):
+        """Ensure creations are rejected."""
+        project = create_project()
+        patch = {
+            'project': project,
+            'submitter': create_person().id,
+            'msgid': make_msgid(),
+            'name': 'test-create-patch',
+            'diff': 'patch diff',
+        }
+
+        # anonymous user
+        resp = self.client.post(self.api_url(), patch)
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
+
+        # superuser
+        user = create_maintainer(project)
+        user.is_superuser = True
+        user.save()
+        self.client.force_authenticate(user=user)
+        resp = self.client.post(self.api_url(), patch)
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
+
+    def test_update(self):
+        """Ensure updates can be performed by maintainers."""
+        project = create_project()
+        patch = create_patch(project=project)
+        state = create_state()
+
+        # anonymous user
+        resp = self.client.patch(self.api_url(patch.id), {'state': state.name})
+        self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
+
+        # authenticated user
+        user = create_user()
+        self.client.force_authenticate(user=user)
+        resp = self.client.patch(self.api_url(patch.id), {'state': state.name})
+        self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
+
+        # maintainer
+        user = create_maintainer(project)
+        self.client.force_authenticate(user=user)
+        resp = self.client.patch(self.api_url(patch.id), {'state': state.name})
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(Patch.objects.get(id=patch.id).state, state)
+
+    def test_update_invalid(self):
+        """Ensure we handle invalid Patch states."""
+        project = create_project()
+        state = create_state()
+        patch = create_patch(project=project, state=state)
+        user = create_maintainer(project)
+
+        # invalid state
+        self.client.force_authenticate(user=user)
+        resp = self.client.patch(self.api_url(patch.id), {'state': 'foobar'})
+        self.assertEqual(status.HTTP_400_BAD_REQUEST, resp.status_code)
+        self.assertContains(resp, 'Expected one of: %s.' % state.name,
+                            status_code=status.HTTP_400_BAD_REQUEST)
+
+    def test_delete(self):
+        """Ensure deletions are always rejected."""
+        project = create_project()
+        patch = create_patch(project=project)
+
+        # anonymous user
+        resp = self.client.delete(self.api_url(patch.id))
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
+
+        # superuser
+        user = create_maintainer(project)
+        user.is_superuser = True
+        user.save()
+        self.client.force_authenticate(user=user)
+        resp = self.client.delete(self.api_url(patch.id))
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
diff --git a/patchwork/tests/api/test_person.py b/patchwork/tests/api/test_person.py
new file mode 100644 (file)
index 0000000..22b1281
--- /dev/null
@@ -0,0 +1,114 @@
+# Patchwork - automated patch tracking system
+# Copyright (C) 2016 Linaro Corporation
+#
+# This file is part of the Patchwork package.
+#
+# Patchwork is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Patchwork is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Patchwork; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import unittest
+
+from django.conf import settings
+
+from patchwork.compat import reverse
+from patchwork.tests.utils import create_maintainer
+from patchwork.tests.utils import create_person
+from patchwork.tests.utils import create_user
+
+if settings.ENABLE_REST_API:
+    from rest_framework import status
+    from rest_framework.test import APITestCase
+else:
+    # stub out APITestCase
+    from django.test import TestCase
+    APITestCase = TestCase  # noqa
+
+
+@unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API')
+class TestPersonAPI(APITestCase):
+
+    @staticmethod
+    def api_url(item=None):
+        if item is None:
+            return reverse('api-person-list')
+        return reverse('api-person-detail', args=[item])
+
+    def assertSerialized(self, person_obj, person_json, has_user=False):
+        self.assertEqual(person_obj.id, person_json['id'])
+        if not has_user:
+            self.assertEqual(person_obj.name, person_json['name'])
+            self.assertEqual(person_obj.email, person_json['email'])
+        else:
+            self.assertEqual(person_obj.user.username, person_json['name'])
+            self.assertEqual(person_obj.user.email, person_json['email'])
+            # nested fields
+            self.assertEqual(person_obj.user.id,
+                             person_json['user']['id'])
+
+    def test_list(self):
+        """This API requires authenticated users."""
+        person = create_person()
+
+        # anonymous user
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
+
+        # authenticated user
+        user = create_user(link_person=False)
+        self.client.force_authenticate(user=user)
+
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(1, len(resp.data))
+        self.assertSerialized(person, resp.data[0])
+
+    def test_detail(self):
+        person = create_person()
+
+        # anonymous user
+        resp = self.client.get(self.api_url(person.id))
+        self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
+
+        # authenticated, unlinked user
+        user = create_user(link_person=False)
+        self.client.force_authenticate(user=user)
+
+        resp = self.client.get(self.api_url(person.id))
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertSerialized(person, resp.data, has_user=False)
+
+        # authenticated, linked user
+        user = create_user(link_person=True)
+        person = user.person_set.all().first()
+        self.client.force_authenticate(user=user)
+
+        resp = self.client.get(self.api_url(person.id))
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertSerialized(person, resp.data, has_user=True)
+
+    def test_create_update_delete(self):
+        """Ensure creates, updates and deletes aren't allowed"""
+        user = create_maintainer()
+        user.is_superuser = True
+        user.save()
+        self.client.force_authenticate(user=user)
+
+        resp = self.client.post(self.api_url(), {'email': 'foo@f.com'})
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
+
+        resp = self.client.patch(self.api_url(user.id), {'email': 'foo@f.com'})
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
+
+        resp = self.client.delete(self.api_url(user.id))
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
diff --git a/patchwork/tests/api/test_project.py b/patchwork/tests/api/test_project.py
new file mode 100644 (file)
index 0000000..a9e59aa
--- /dev/null
@@ -0,0 +1,167 @@
+# Patchwork - automated patch tracking system
+# Copyright (C) 2016 Linaro Corporation
+#
+# This file is part of the Patchwork package.
+#
+# Patchwork is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Patchwork is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Patchwork; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import unittest
+
+from django.conf import settings
+
+from patchwork.compat import reverse
+from patchwork.models import Project
+from patchwork.tests.utils import create_maintainer
+from patchwork.tests.utils import create_project
+from patchwork.tests.utils import create_user
+
+if settings.ENABLE_REST_API:
+    from rest_framework import status
+    from rest_framework.test import APITestCase
+else:
+    # stub out APITestCase
+    from django.test import TestCase
+    APITestCase = TestCase  # noqa
+
+
+@unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API')
+class TestProjectAPI(APITestCase):
+
+    @staticmethod
+    def api_url(item=None):
+        if item is None:
+            return reverse('api-project-list')
+        return reverse('api-project-detail', args=[item])
+
+    def assertSerialized(self, project_obj, project_json):
+        self.assertEqual(project_obj.id, project_json['id'])
+        self.assertEqual(project_obj.name, project_json['name'])
+        self.assertEqual(project_obj.linkname, project_json['link_name'])
+        self.assertEqual(project_obj.listid, project_json['list_id'])
+
+        # nested fields
+
+        self.assertEqual(len(project_json['maintainers']),
+                         project_obj.maintainer_project.all().count())
+
+    def test_list(self):
+        """Validate we can list the default test project."""
+        project = create_project()
+
+        # anonymous user
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(1, len(resp.data))
+        self.assertSerialized(project, resp.data[0])
+
+        # maintainer
+        user = create_maintainer(project)
+        self.client.force_authenticate(user=user)
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(1, len(resp.data))
+        self.assertSerialized(project, resp.data[0])
+
+    def test_detail(self):
+        """Validate we can get a specific project."""
+        project = create_project()
+
+        resp = self.client.get(self.api_url(project.id))
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(project.name, resp.data['name'])
+
+        # make sure we can look up by linkname
+        resp = self.client.get(self.api_url(resp.data['link_name']))
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertSerialized(project, resp.data)
+
+    def test_get_by_id(self):
+        """Validate that it's possible to filter by pk."""
+        project = create_project()
+
+        resp = self.client.get(self.api_url(project.pk))
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertSerialized(project, resp.data)
+
+    def test_get_by_linkname(self):
+        """Validate that it's possible to filter by linkname."""
+        project = create_project(linkname='project', name='Sample project')
+
+        resp = self.client.get(self.api_url('project'))
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertSerialized(project, resp.data)
+
+    def test_get_by_numeric_linkname(self):
+        """Validate we try to do the right thing for numeric linkname"""
+        project = create_project(linkname='12345')
+
+        resp = self.client.get(self.api_url('12345'))
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertSerialized(project, resp.data)
+
+    def test_create(self):
+        """Ensure creations are rejected."""
+        project = create_project()
+        data = {'linkname': 'l', 'name': 'n', 'listid': 'l', 'listemail': 'e'}
+
+        # an anonymous user
+        resp = self.client.post(self.api_url(), data)
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
+
+        # a superuser
+        user = create_maintainer(project)
+        user.is_superuser = True
+        user.save()
+        self.client.force_authenticate(user=user)
+        resp = self.client.post(self.api_url(), data)
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
+
+    def test_update(self):
+        """Ensure updates can be performed by maintainers."""
+        project = create_project()
+        data = {'linkname': 'TEST'}
+
+        # an anonymous user
+        resp = self.client.patch(self.api_url(project.id), data)
+        self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
+
+        # a normal user
+        user = create_user()
+        self.client.force_authenticate(user=user)
+        resp = self.client.patch(self.api_url(project.id), data)
+        self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
+
+        # a maintainer
+        user = create_maintainer(project)
+        self.client.force_authenticate(user=user)
+        resp = self.client.patch(self.api_url(project.id), data)
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+
+    def test_delete(self):
+        """Ensure deletions are rejected."""
+        project = create_project()
+
+        # an anonymous user
+        resp = self.client.delete(self.api_url(project.id))
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
+
+        # a super user
+        user = create_maintainer(project)
+        user.is_superuser = True
+        user.save()
+        self.client.force_authenticate(user=user)
+        resp = self.client.delete(self.api_url(project.id))
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
+        self.assertEqual(1, Project.objects.all().count())
diff --git a/patchwork/tests/api/test_user.py b/patchwork/tests/api/test_user.py
new file mode 100644 (file)
index 0000000..873312d
--- /dev/null
@@ -0,0 +1,89 @@
+# Patchwork - automated patch tracking system
+# Copyright (C) 2016 Linaro Corporation
+#
+# This file is part of the Patchwork package.
+#
+# Patchwork is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Patchwork is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Patchwork; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import unittest
+
+from django.conf import settings
+
+from patchwork.compat import reverse
+from patchwork.tests.utils import create_maintainer
+from patchwork.tests.utils import create_user
+
+if settings.ENABLE_REST_API:
+    from rest_framework import status
+    from rest_framework.test import APITestCase
+else:
+    # stub out APITestCase
+    from django.test import TestCase
+    APITestCase = TestCase  # noqa
+
+
+@unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API')
+class TestUserAPI(APITestCase):
+
+    @staticmethod
+    def api_url(item=None):
+        if item is None:
+            return reverse('api-user-list')
+        return reverse('api-user-detail', args=[item])
+
+    def assertSerialized(self, user_obj, user_json):
+        self.assertEqual(user_obj.id, user_json['id'])
+        self.assertEqual(user_obj.username, user_json['username'])
+        self.assertNotIn('password', user_json)
+        self.assertNotIn('is_superuser', user_json)
+
+    def test_list(self):
+        """This API requires authenticated users."""
+        # anonymous users
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
+
+        # authenticated user
+        user = create_user()
+        self.client.force_authenticate(user=user)
+
+        resp = self.client.get(self.api_url())
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertEqual(1, len(resp.data))
+        self.assertSerialized(user, resp.data[0])
+
+    def test_update(self):
+        """Ensure updates are allowed."""
+        user = create_maintainer()
+        user.is_superuser = True
+        user.save()
+        self.client.force_authenticate(user=user)
+
+        resp = self.client.patch(self.api_url(user.id), {'first_name': 'Tan'})
+        self.assertEqual(status.HTTP_200_OK, resp.status_code)
+        self.assertSerialized(user, resp.data)
+
+    def test_create_delete(self):
+        """Ensure creations and deletions and not allowed."""
+        user = create_maintainer()
+        user.is_superuser = True
+        user.save()
+        self.client.force_authenticate(user=user)
+
+        resp = self.client.post(self.api_url(user.id), {'email': 'foo@f.com'})
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
+
+        resp = self.client.delete(self.api_url(user.id))
+        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
diff --git a/patchwork/tests/test_rest_api.py b/patchwork/tests/test_rest_api.py
deleted file mode 100644 (file)
index 3e264e1..0000000
+++ /dev/null
@@ -1,869 +0,0 @@
-# Patchwork - automated patch tracking system
-# Copyright (C) 2016 Linaro Corporation
-#
-# This file is part of the Patchwork package.
-#
-# Patchwork is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# Patchwork is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Patchwork; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-from email.utils import make_msgid
-import unittest
-
-from django.conf import settings
-
-from patchwork.compat import reverse
-from patchwork.models import Check
-from patchwork.models import Patch
-from patchwork.models import Project
-from patchwork.tests.utils import create_bundle
-from patchwork.tests.utils import create_check
-from patchwork.tests.utils import create_cover
-from patchwork.tests.utils import create_maintainer
-from patchwork.tests.utils import create_patch
-from patchwork.tests.utils import create_person
-from patchwork.tests.utils import create_project
-from patchwork.tests.utils import create_state
-from patchwork.tests.utils import create_series
-from patchwork.tests.utils import create_user
-
-if settings.ENABLE_REST_API:
-    from rest_framework import status
-    from rest_framework.test import APITestCase
-else:
-    # stub out APITestCase
-    from django.test import TestCase
-    APITestCase = TestCase  # noqa
-
-
-@unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API')
-class TestProjectAPI(APITestCase):
-
-    @staticmethod
-    def api_url(item=None):
-        if item is None:
-            return reverse('api-project-list')
-        return reverse('api-project-detail', args=[item])
-
-    def assertSerialized(self, project_obj, project_json):
-        self.assertEqual(project_obj.id, project_json['id'])
-        self.assertEqual(project_obj.name, project_json['name'])
-        self.assertEqual(project_obj.linkname, project_json['link_name'])
-        self.assertEqual(project_obj.listid, project_json['list_id'])
-
-        # nested fields
-
-        self.assertEqual(len(project_json['maintainers']),
-                         project_obj.maintainer_project.all().count())
-
-    def test_list(self):
-        """Validate we can list the default test project."""
-        project = create_project()
-
-        # anonymous user
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(1, len(resp.data))
-        self.assertSerialized(project, resp.data[0])
-
-        # maintainer
-        user = create_maintainer(project)
-        self.client.force_authenticate(user=user)
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(1, len(resp.data))
-        self.assertSerialized(project, resp.data[0])
-
-    def test_detail(self):
-        """Validate we can get a specific project."""
-        project = create_project()
-
-        resp = self.client.get(self.api_url(project.id))
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(project.name, resp.data['name'])
-
-        # make sure we can look up by linkname
-        resp = self.client.get(self.api_url(resp.data['link_name']))
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertSerialized(project, resp.data)
-
-    def test_get_by_id(self):
-        """Validate that it's possible to filter by pk."""
-        project = create_project()
-
-        resp = self.client.get(self.api_url(project.pk))
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertSerialized(project, resp.data)
-
-    def test_get_by_linkname(self):
-        """Validate that it's possible to filter by linkname."""
-        project = create_project(linkname='project', name='Sample project')
-
-        resp = self.client.get(self.api_url('project'))
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertSerialized(project, resp.data)
-
-    def test_get_by_numeric_linkname(self):
-        """Validate we try to do the right thing for numeric linkname"""
-        project = create_project(linkname='12345')
-
-        resp = self.client.get(self.api_url('12345'))
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertSerialized(project, resp.data)
-
-    def test_create(self):
-        """Ensure creations are rejected."""
-        project = create_project()
-        data = {'linkname': 'l', 'name': 'n', 'listid': 'l', 'listemail': 'e'}
-
-        # an anonymous user
-        resp = self.client.post(self.api_url(), data)
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-        # a superuser
-        user = create_maintainer(project)
-        user.is_superuser = True
-        user.save()
-        self.client.force_authenticate(user=user)
-        resp = self.client.post(self.api_url(), data)
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-    def test_update(self):
-        """Ensure updates can be performed by maintainers."""
-        project = create_project()
-        data = {'linkname': 'TEST'}
-
-        # an anonymous user
-        resp = self.client.patch(self.api_url(project.id), data)
-        self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
-
-        # a normal user
-        user = create_user()
-        self.client.force_authenticate(user=user)
-        resp = self.client.patch(self.api_url(project.id), data)
-        self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
-
-        # a maintainer
-        user = create_maintainer(project)
-        self.client.force_authenticate(user=user)
-        resp = self.client.patch(self.api_url(project.id), data)
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-
-    def test_delete(self):
-        """Ensure deletions are rejected."""
-        project = create_project()
-
-        # an anonymous user
-        resp = self.client.delete(self.api_url(project.id))
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-        # a super user
-        user = create_maintainer(project)
-        user.is_superuser = True
-        user.save()
-        self.client.force_authenticate(user=user)
-        resp = self.client.delete(self.api_url(project.id))
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-        self.assertEqual(1, Project.objects.all().count())
-
-
-@unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API')
-class TestPersonAPI(APITestCase):
-
-    @staticmethod
-    def api_url(item=None):
-        if item is None:
-            return reverse('api-person-list')
-        return reverse('api-person-detail', args=[item])
-
-    def assertSerialized(self, person_obj, person_json, has_user=False):
-        self.assertEqual(person_obj.id, person_json['id'])
-        if not has_user:
-            self.assertEqual(person_obj.name, person_json['name'])
-            self.assertEqual(person_obj.email, person_json['email'])
-        else:
-            self.assertEqual(person_obj.user.username, person_json['name'])
-            self.assertEqual(person_obj.user.email, person_json['email'])
-            # nested fields
-            self.assertEqual(person_obj.user.id,
-                             person_json['user']['id'])
-
-    def test_list(self):
-        """This API requires authenticated users."""
-        person = create_person()
-
-        # anonymous user
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
-
-        # authenticated user
-        user = create_user(link_person=False)
-        self.client.force_authenticate(user=user)
-
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(1, len(resp.data))
-        self.assertSerialized(person, resp.data[0])
-
-    def test_detail(self):
-        person = create_person()
-
-        # anonymous user
-        resp = self.client.get(self.api_url(person.id))
-        self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
-
-        # authenticated, unlinked user
-        user = create_user(link_person=False)
-        self.client.force_authenticate(user=user)
-
-        resp = self.client.get(self.api_url(person.id))
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertSerialized(person, resp.data, has_user=False)
-
-        # authenticated, linked user
-        user = create_user(link_person=True)
-        person = user.person_set.all().first()
-        self.client.force_authenticate(user=user)
-
-        resp = self.client.get(self.api_url(person.id))
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertSerialized(person, resp.data, has_user=True)
-
-    def test_create_update_delete(self):
-        """Ensure creates, updates and deletes aren't allowed"""
-        user = create_maintainer()
-        user.is_superuser = True
-        user.save()
-        self.client.force_authenticate(user=user)
-
-        resp = self.client.post(self.api_url(), {'email': 'foo@f.com'})
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-        resp = self.client.patch(self.api_url(user.id), {'email': 'foo@f.com'})
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-        resp = self.client.delete(self.api_url(user.id))
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-
-@unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API')
-class TestUserAPI(APITestCase):
-
-    @staticmethod
-    def api_url(item=None):
-        if item is None:
-            return reverse('api-user-list')
-        return reverse('api-user-detail', args=[item])
-
-    def assertSerialized(self, user_obj, user_json):
-        self.assertEqual(user_obj.id, user_json['id'])
-        self.assertEqual(user_obj.username, user_json['username'])
-        self.assertNotIn('password', user_json)
-        self.assertNotIn('is_superuser', user_json)
-
-    def test_list(self):
-        """This API requires authenticated users."""
-        # anonymous users
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
-
-        # authenticated user
-        user = create_user()
-        self.client.force_authenticate(user=user)
-
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(1, len(resp.data))
-        self.assertSerialized(user, resp.data[0])
-
-    def test_update(self):
-        """Ensure updates are allowed."""
-        user = create_maintainer()
-        user.is_superuser = True
-        user.save()
-        self.client.force_authenticate(user=user)
-
-        resp = self.client.patch(self.api_url(user.id), {'first_name': 'Tan'})
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertSerialized(user, resp.data)
-
-    def test_create_delete(self):
-        """Ensure creations and deletions and not allowed."""
-        user = create_maintainer()
-        user.is_superuser = True
-        user.save()
-        self.client.force_authenticate(user=user)
-
-        resp = self.client.post(self.api_url(user.id), {'email': 'foo@f.com'})
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-        resp = self.client.delete(self.api_url(user.id))
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-
-@unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API')
-class TestPatchAPI(APITestCase):
-    fixtures = ['default_tags']
-
-    @staticmethod
-    def api_url(item=None):
-        if item is None:
-            return reverse('api-patch-list')
-        return reverse('api-patch-detail', args=[item])
-
-    def assertSerialized(self, patch_obj, patch_json):
-        self.assertEqual(patch_obj.id, patch_json['id'])
-        self.assertEqual(patch_obj.name, patch_json['name'])
-        self.assertEqual(patch_obj.msgid, patch_json['msgid'])
-        self.assertEqual(patch_obj.state.slug, patch_json['state'])
-        self.assertIn(patch_obj.get_mbox_url(), patch_json['mbox'])
-
-        # nested fields
-
-        self.assertEqual(patch_obj.submitter.id,
-                         patch_json['submitter']['id'])
-        self.assertEqual(patch_obj.project.id,
-                         patch_json['project']['id'])
-
-    def test_list(self):
-        """Validate we can list a patch."""
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(0, len(resp.data))
-
-        person_obj = create_person(email='test@example.com')
-        state_obj = create_state(name='Under Review')
-        project_obj = create_project(linkname='myproject')
-        patch_obj = create_patch(state=state_obj, project=project_obj,
-                                 submitter=person_obj)
-
-        # anonymous user
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(1, len(resp.data))
-        patch_rsp = resp.data[0]
-        self.assertSerialized(patch_obj, patch_rsp)
-        self.assertNotIn('headers', patch_rsp)
-        self.assertNotIn('content', patch_rsp)
-        self.assertNotIn('diff', patch_rsp)
-
-        # authenticated user
-        user = create_user()
-        self.client.force_authenticate(user=user)
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(1, len(resp.data))
-        patch_rsp = resp.data[0]
-        self.assertSerialized(patch_obj, patch_rsp)
-
-        # test filtering by state
-        resp = self.client.get(self.api_url(), {'state': 'under-review'})
-        self.assertEqual([patch_obj.id], [x['id'] for x in resp.data])
-        resp = self.client.get(self.api_url(), {'state': 'missing-state'})
-        self.assertEqual(0, len(resp.data))
-
-        # test filtering by project
-        resp = self.client.get(self.api_url(), {'project': 'myproject'})
-        self.assertEqual([patch_obj.id], [x['id'] for x in resp.data])
-        resp = self.client.get(self.api_url(), {'project': 'invalidproject'})
-        self.assertEqual(0, len(resp.data))
-
-        # test filtering by submitter, both ID and email
-        resp = self.client.get(self.api_url(), {'submitter': person_obj.id})
-        self.assertEqual([patch_obj.id], [x['id'] for x in resp.data])
-        resp = self.client.get(self.api_url(), {
-            'submitter': 'test@example.com'})
-        self.assertEqual([patch_obj.id], [x['id'] for x in resp.data])
-        resp = self.client.get(self.api_url(), {
-            'submitter': 'test@example.org'})
-        self.assertEqual(0, len(resp.data))
-
-    def test_detail(self):
-        """Validate we can get a specific patch."""
-        patch = create_patch(
-            content='Reviewed-by: Test User <test@example.com>\n')
-
-        resp = self.client.get(self.api_url(patch.id))
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertSerialized(patch, resp.data)
-        self.assertEqual(patch.headers, resp.data['headers'] or '')
-        self.assertEqual(patch.content, resp.data['content'])
-        self.assertEqual(patch.diff, resp.data['diff'])
-        self.assertEqual(0, len(resp.data['tags']))
-
-    def test_create(self):
-        """Ensure creations are rejected."""
-        project = create_project()
-        patch = {
-            'project': project,
-            'submitter': create_person().id,
-            'msgid': make_msgid(),
-            'name': 'test-create-patch',
-            'diff': 'patch diff',
-        }
-
-        # anonymous user
-        resp = self.client.post(self.api_url(), patch)
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-        # superuser
-        user = create_maintainer(project)
-        user.is_superuser = True
-        user.save()
-        self.client.force_authenticate(user=user)
-        resp = self.client.post(self.api_url(), patch)
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-    def test_update(self):
-        """Ensure updates can be performed by maintainers."""
-        project = create_project()
-        patch = create_patch(project=project)
-        state = create_state()
-
-        # anonymous user
-        resp = self.client.patch(self.api_url(patch.id), {'state': state.name})
-        self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
-
-        # authenticated user
-        user = create_user()
-        self.client.force_authenticate(user=user)
-        resp = self.client.patch(self.api_url(patch.id), {'state': state.name})
-        self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
-
-        # maintainer
-        user = create_maintainer(project)
-        self.client.force_authenticate(user=user)
-        resp = self.client.patch(self.api_url(patch.id), {'state': state.name})
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(Patch.objects.get(id=patch.id).state, state)
-
-    def test_update_invalid(self):
-        """Ensure we handle invalid Patch states."""
-        project = create_project()
-        state = create_state()
-        patch = create_patch(project=project, state=state)
-        user = create_maintainer(project)
-
-        # invalid state
-        self.client.force_authenticate(user=user)
-        resp = self.client.patch(self.api_url(patch.id), {'state': 'foobar'})
-        self.assertEqual(status.HTTP_400_BAD_REQUEST, resp.status_code)
-        self.assertContains(resp, 'Expected one of: %s.' % state.name,
-                            status_code=status.HTTP_400_BAD_REQUEST)
-
-    def test_delete(self):
-        """Ensure deletions are always rejected."""
-        project = create_project()
-        patch = create_patch(project=project)
-
-        # anonymous user
-        resp = self.client.delete(self.api_url(patch.id))
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-        # superuser
-        user = create_maintainer(project)
-        user.is_superuser = True
-        user.save()
-        self.client.force_authenticate(user=user)
-        resp = self.client.delete(self.api_url(patch.id))
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-
-@unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API')
-class TestCoverLetterAPI(APITestCase):
-    fixtures = ['default_tags']
-
-    @staticmethod
-    def api_url(item=None):
-        if item is None:
-            return reverse('api-cover-list')
-        return reverse('api-cover-detail', args=[item])
-
-    def assertSerialized(self, cover_obj, cover_json):
-        self.assertEqual(cover_obj.id, cover_json['id'])
-        self.assertEqual(cover_obj.name, cover_json['name'])
-        self.assertIn(cover_obj.get_mbox_url(), cover_json['mbox'])
-
-        # nested fields
-
-        self.assertEqual(cover_obj.submitter.id,
-                         cover_json['submitter']['id'])
-
-    def test_list(self):
-        """Validate we can list cover letters."""
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(0, len(resp.data))
-
-        person_obj = create_person(email='test@example.com')
-        project_obj = create_project(linkname='myproject')
-        cover_obj = create_cover(project=project_obj, submitter=person_obj)
-
-        # anonymous user
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(1, len(resp.data))
-        self.assertSerialized(cover_obj, resp.data[0])
-
-        # authenticated user
-        user = create_user()
-        self.client.force_authenticate(user=user)
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(1, len(resp.data))
-        self.assertSerialized(cover_obj, resp.data[0])
-
-        # test filtering by project
-        resp = self.client.get(self.api_url(), {'project': 'myproject'})
-        self.assertEqual([cover_obj.id], [x['id'] for x in resp.data])
-        resp = self.client.get(self.api_url(), {'project': 'invalidproject'})
-        self.assertEqual(0, len(resp.data))
-
-        # test filtering by submitter, both ID and email
-        resp = self.client.get(self.api_url(), {'submitter': person_obj.id})
-        self.assertEqual([cover_obj.id], [x['id'] for x in resp.data])
-        resp = self.client.get(self.api_url(), {
-            'submitter': 'test@example.com'})
-        self.assertEqual([cover_obj.id], [x['id'] for x in resp.data])
-        resp = self.client.get(self.api_url(), {
-            'submitter': 'test@example.org'})
-        self.assertEqual(0, len(resp.data))
-
-    def test_detail(self):
-        """Validate we can get a specific cover letter."""
-        cover_obj = create_cover()
-
-        resp = self.client.get(self.api_url(cover_obj.id))
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertSerialized(cover_obj, resp.data)
-
-    def test_create_update_delete(self):
-        user = create_maintainer()
-        user.is_superuser = True
-        user.save()
-        self.client.force_authenticate(user=user)
-
-        resp = self.client.post(self.api_url(), {'name': 'test cover'})
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-        resp = self.client.patch(self.api_url(), {'name': 'test cover'})
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-        resp = self.client.delete(self.api_url())
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-
-@unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API')
-class TestSeriesAPI(APITestCase):
-    fixtures = ['default_tags']
-
-    def api_url(self, item=None):
-        if item is None:
-            return reverse('api-series-list')
-        return reverse('api-series-detail', args=[item])
-
-    def assertSerialized(self, series_obj, series_json):
-        self.assertEqual(series_obj.id, series_json['id'])
-        self.assertEqual(series_obj.name, series_json['name'])
-        self.assertIn(series_obj.get_mbox_url(), series_json['mbox'])
-
-        # nested fields
-
-        self.assertEqual(series_obj.project.id,
-                         series_json['project']['id'])
-        self.assertEqual(series_obj.submitter.id,
-                         series_json['submitter']['id'])
-        self.assertEqual(series_obj.patches.count(),
-                         len(series_json['patches']))
-
-        if series_obj.cover_letter:
-            self.assertEqual(
-                series_obj.cover_letter.id,
-                series_json['cover_letter']['id'])
-
-    def test_list(self):
-        """Validate we can list series."""
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(0, len(resp.data))
-
-        person_obj = create_person(email='test@example.com')
-        project_obj = create_project(linkname='myproject')
-        series_obj = create_series(project=project_obj, submitter=person_obj)
-
-        # anonymous user
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(1, len(resp.data))
-        self.assertSerialized(series_obj, resp.data[0])
-
-        # authenticated user
-        user = create_user()
-        self.client.force_authenticate(user=user)
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(1, len(resp.data))
-        self.assertSerialized(series_obj, resp.data[0])
-
-        # test filtering by project
-        resp = self.client.get(self.api_url(), {'project': 'myproject'})
-        self.assertEqual([series_obj.id], [x['id'] for x in resp.data])
-        resp = self.client.get(self.api_url(), {'project': 'invalidproject'})
-        self.assertEqual(0, len(resp.data))
-
-        # test filtering by submitter, both ID and email
-        resp = self.client.get(self.api_url(), {'submitter': person_obj.id})
-        self.assertEqual([series_obj.id], [x['id'] for x in resp.data])
-        resp = self.client.get(self.api_url(), {
-            'submitter': 'test@example.com'})
-        self.assertEqual([series_obj.id], [x['id'] for x in resp.data])
-        resp = self.client.get(self.api_url(), {
-            'submitter': 'test@example.org'})
-        self.assertEqual(0, len(resp.data))
-
-    def test_detail(self):
-        """Validate we can get a specific series."""
-        series = create_series()
-
-        resp = self.client.get(self.api_url(series.id))
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertSerialized(series, resp.data)
-
-        patch = create_patch(project=series.project)
-        series.add_patch(patch, 1)
-        resp = self.client.get(self.api_url(series.id))
-        self.assertSerialized(series, resp.data)
-
-        cover_letter = create_cover(project=series.project)
-        series.add_cover_letter(cover_letter)
-        resp = self.client.get(self.api_url(series.id))
-        self.assertSerialized(series, resp.data)
-
-    def test_create_update_delete(self):
-        user = create_maintainer()
-        user.is_superuser = True
-        user.save()
-        self.client.force_authenticate(user=user)
-
-        resp = self.client.post(self.api_url(), {'name': 'test series'})
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-        resp = self.client.patch(self.api_url(), {'name': 'test series'})
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-        resp = self.client.delete(self.api_url())
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-
-@unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API')
-class TestCheckAPI(APITestCase):
-    fixtures = ['default_tags']
-
-    def api_url(self, item=None):
-        if item is None:
-            return reverse('api-check-list', args=[self.patch.id])
-        return reverse('api-check-detail', kwargs={
-            'patch_id': self.patch.id, 'check_id': item.id})
-
-    def setUp(self):
-        super(TestCheckAPI, self).setUp()
-        project = create_project()
-        self.user = create_maintainer(project)
-        self.patch = create_patch(project=project)
-
-    def _create_check(self):
-        values = {
-            'patch': self.patch,
-            'user': self.user,
-        }
-        return create_check(**values)
-
-    def assertSerialized(self, check_obj, check_json):
-        self.assertEqual(check_obj.id, check_json['id'])
-        self.assertEqual(check_obj.get_state_display(), check_json['state'])
-        self.assertEqual(check_obj.target_url, check_json['target_url'])
-        self.assertEqual(check_obj.context, check_json['context'])
-        self.assertEqual(check_obj.description, check_json['description'])
-
-    def test_list(self):
-        """Validate we can list checks on a patch."""
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(0, len(resp.data))
-
-        check_obj = self._create_check()
-
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(1, len(resp.data))
-        self.assertSerialized(check_obj, resp.data[0])
-
-        # test filtering by owner, both ID and username
-        resp = self.client.get(self.api_url(), {'user': self.user.id})
-        self.assertEqual([check_obj.id], [x['id'] for x in resp.data])
-        resp = self.client.get(self.api_url(), {'user': self.user.username})
-        self.assertEqual([check_obj.id], [x['id'] for x in resp.data])
-        resp = self.client.get(self.api_url(), {'user': 'otheruser'})
-        self.assertEqual(0, len(resp.data))
-
-    def test_detail(self):
-        """Validate we can get a specific check."""
-        check = self._create_check()
-        resp = self.client.get(self.api_url(check))
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertSerialized(check, resp.data)
-
-    def test_create(self):
-        """Ensure creations can be performed by user of patch."""
-        check = {
-            'state': 'success',
-            'target_url': 'http://t.co',
-            'description': 'description',
-            'context': 'context',
-        }
-
-        self.client.force_authenticate(user=self.user)
-        resp = self.client.post(self.api_url(), check)
-        self.assertEqual(status.HTTP_201_CREATED, resp.status_code)
-        self.assertEqual(1, Check.objects.all().count())
-        self.assertSerialized(Check.objects.first(), resp.data)
-
-        user = create_user()
-        self.client.force_authenticate(user=user)
-        resp = self.client.post(self.api_url(), check)
-        self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code)
-
-    def test_create_invalid(self):
-        """Ensure we handle invalid check states."""
-        check = {
-            'state': 'this-is-not-a-valid-state',
-            'target_url': 'http://t.co',
-            'description': 'description',
-            'context': 'context',
-        }
-
-        self.client.force_authenticate(user=self.user)
-        resp = self.client.post(self.api_url(), check)
-        self.assertEqual(status.HTTP_400_BAD_REQUEST, resp.status_code)
-        self.assertEqual(0, Check.objects.all().count())
-
-    def test_update_delete(self):
-        """Ensure updates and deletes aren't allowed"""
-        check = self._create_check()
-        self.user.is_superuser = True
-        self.user.save()
-        self.client.force_authenticate(user=self.user)
-
-        resp = self.client.patch(self.api_url(check), {'target_url': 'fail'})
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-        resp = self.client.delete(self.api_url(check))
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-
-@unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API')
-class TestBundleAPI(APITestCase):
-    fixtures = ['default_tags']
-
-    @staticmethod
-    def api_url(item=None):
-        if item is None:
-            return reverse('api-bundle-list')
-        return reverse('api-bundle-detail', args=[item])
-
-    def assertSerialized(self, bundle_obj, bundle_json):
-        self.assertEqual(bundle_obj.id, bundle_json['id'])
-        self.assertEqual(bundle_obj.name, bundle_json['name'])
-        self.assertEqual(bundle_obj.public, bundle_json['public'])
-        self.assertIn(bundle_obj.get_mbox_url(), bundle_json['mbox'])
-
-        # nested fields
-
-        self.assertEqual(bundle_obj.patches.count(),
-                         len(bundle_json['patches']))
-        self.assertEqual(bundle_obj.owner.id,
-                         bundle_json['owner']['id'])
-        self.assertEqual(bundle_obj.project.id,
-                         bundle_json['project']['id'])
-
-    def test_list(self):
-        """Validate we can list bundles."""
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(0, len(resp.data))
-
-        user = create_user(username='myuser')
-        project = create_project(linkname='myproject')
-        bundle_public = create_bundle(public=True, owner=user,
-                                      project=project)
-        bundle_private = create_bundle(public=False, owner=user,
-                                       project=project)
-
-        # anonymous users
-        # should only see the public bundle
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(1, len(resp.data))
-        bundle_rsp = resp.data[0]
-        self.assertSerialized(bundle_public, bundle_rsp)
-
-        # authenticated user
-        # should see the public and private bundle
-        self.client.force_authenticate(user=user)
-        resp = self.client.get(self.api_url())
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertEqual(2, len(resp.data))
-        for bundle_rsp, bundle_obj in zip(
-                resp.data, [bundle_public, bundle_private]):
-            self.assertSerialized(bundle_obj, bundle_rsp)
-
-        # test filtering by project
-        resp = self.client.get(self.api_url(), {'project': 'myproject'})
-        self.assertEqual([bundle_public.id, bundle_private.id],
-                         [x['id'] for x in resp.data])
-        resp = self.client.get(self.api_url(), {'project': 'invalidproject'})
-        self.assertEqual(0, len(resp.data))
-
-        # test filtering by owner, both ID and username
-        resp = self.client.get(self.api_url(), {'owner': user.id})
-        self.assertEqual([bundle_public.id, bundle_private.id],
-                         [x['id'] for x in resp.data])
-        resp = self.client.get(self.api_url(), {'owner': 'myuser'})
-        self.assertEqual([bundle_public.id, bundle_private.id],
-                         [x['id'] for x in resp.data])
-        resp = self.client.get(self.api_url(), {'owner': 'otheruser'})
-        self.assertEqual(0, len(resp.data))
-
-    def test_detail(self):
-        """Validate we can get a specific bundle."""
-        bundle = create_bundle(public=True)
-
-        resp = self.client.get(self.api_url(bundle.id))
-        self.assertEqual(status.HTTP_200_OK, resp.status_code)
-        self.assertSerialized(bundle, resp.data)
-
-    def test_create_update_delete(self):
-        """Ensure creates, updates and deletes aren't allowed"""
-        user = create_maintainer()
-        user.is_superuser = True
-        user.save()
-        self.client.force_authenticate(user=user)
-
-        resp = self.client.post(self.api_url(), {'email': 'foo@f.com'})
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-        resp = self.client.patch(self.api_url(user.id), {'email': 'foo@f.com'})
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
-
-        resp = self.client.delete(self.api_url(1))
-        self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)