From patchwork Tue Oct 30 11:31:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Finucane X-Patchwork-Id: 990756 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42kq950s15z9s7W for ; Tue, 30 Oct 2018 22:33:29 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=that.guru Authentication-Results: ozlabs.org; dkim=fail reason="key not found in DNS" (0-bit key; unprotected) header.d=that.guru header.i=@that.guru header.b="h6XzkyCX"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 42kq945zZpzDrSM for ; Tue, 30 Oct 2018 22:33:28 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=that.guru Authentication-Results: lists.ozlabs.org; dkim=fail reason="key not found in DNS" (0-bit key; unprotected) header.d=that.guru header.i=@that.guru header.b="h6XzkyCX"; dkim-atps=neutral X-Original-To: patchwork@lists.ozlabs.org Delivered-To: patchwork@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=none (mailfrom) smtp.mailfrom=that.guru (client-ip=185.234.75.20; helo=relay020.mxrelay.co; envelope-from=stephen@that.guru; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=that.guru Authentication-Results: lists.ozlabs.org; dkim=fail reason="key not found in DNS" (0-bit key; unprotected) header.d=that.guru header.i=@that.guru header.b="h6XzkyCX"; dkim-atps=neutral Received: from relay020.mxrelay.co (relay020.mxrelay.co [185.234.75.20]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 42kq801VVmzF1PT for ; Tue, 30 Oct 2018 22:32:32 +1100 (AEDT) Received: from filter002.mxroute.com (unknown [185.133.192.179]) by relay020.mxrelay.co (Postfix) with ESMTP id 9CCEE42C6B for ; Tue, 30 Oct 2018 11:31:59 +0000 (UTC) Received: from one.mxroute.com (one.mxroute.com [195.201.59.211]) by filter002.mxroute.com (Postfix) with ESMTPS id 7D2D43F546 for ; Tue, 30 Oct 2018 11:31:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=that.guru; s=default; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=4/q370/GNV5PpIgu8cdOT1AHKVsBGRagK/1PUeLUVW8=; b=h6XzkyCXbFjE1/EVsSo4nskqXz IDtsz34vGsKy6apRPAO+hYYUxNSxCrv4LobA6PdrqZDiiQ5Qs9mXr/ODYy1tLzU0fWeXR7sgVzZNk cmGuJJIIY4wKCGiLoDXzzCKh3FxZpDA66m+Fxd1osg9trythRzfz9G1R2SnDKgo7WLRbOubI5M58Y m5jvaGz0niSTJKL7BcpYanDxruR35GAJSwpBLVNW69Kl7HPY7ENgo43KSPuFARrYKaZEX5+lgSMzE qK8gnm7fezG1OTae7OWCjd1vX1MilEArU236bSjsMWKcNgRU6e0RGe/SGdDAhd6dFQH0E6TITekEg Tp/XpEjg==; From: Stephen Finucane To: patchwork@lists.ozlabs.org Subject: [PATCH 03/13] tests: Add 'store_samples' decorator to 'test_project' Date: Tue, 30 Oct 2018 11:31:43 +0000 Message-Id: <20181030113153.7855-4-stephen@that.guru> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20181030113153.7855-1-stephen@that.guru> References: <20181030113153.7855-1-stephen@that.guru> X-AuthUser: stephen@that.guru X-BeenThere: patchwork@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Patchwork development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: patchwork-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Patchwork" Signed-off-by: Stephen Finucane --- patchwork/tests/api/test_project.py | 110 ++++++++++++++++++++-------- 1 file changed, 81 insertions(+), 29 deletions(-) diff --git a/patchwork/tests/api/test_project.py b/patchwork/tests/api/test_project.py index 557c1e07..c1eb3ded 100644 --- a/patchwork/tests/api/test_project.py +++ b/patchwork/tests/api/test_project.py @@ -9,6 +9,7 @@ from django.conf import settings from django.urls import reverse from patchwork.models import Project +from patchwork.tests.api import utils from patchwork.tests.utils import create_maintainer from patchwork.tests.utils import create_project from patchwork.tests.utils import create_user @@ -33,7 +34,8 @@ class TestProjectAPI(APITestCase): if item is None: return reverse('api-project-list', kwargs=kwargs) - return reverse('api-project-detail', args=[item], kwargs=kwargs) + kwargs['pk'] = item + return reverse('api-project-detail', kwargs=kwargs) def assertSerialized(self, project_obj, project_json): self.assertEqual(project_obj.id, project_json['id']) @@ -48,67 +50,93 @@ class TestProjectAPI(APITestCase): self.assertEqual(len(project_json['maintainers']), project_obj.maintainer_project.all().count()) - def test_list(self): - """Validate we can list the default test project.""" + def test_list_empty(self): + """List projects when none are present.""" + resp = self.client.get(self.api_url()) + self.assertEqual(status.HTTP_200_OK, resp.status_code) + self.assertEqual(0, len(resp.data)) + + def test_list_anonymous(self): + """List projects as anonymous user.""" 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 + @utils.store_samples('project-list') + def test_list_authenticated(self): + """List projects as an authenticated user.""" + project = create_project() 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]) - # test old version of API + @utils.store_samples('project-list-1.0') + def test_list_version_1_0(self): + """List projects using API v1.0. + + Validate that newer fields are dropped for older API versions. + """ + create_project() + resp = self.client.get(self.api_url(version='1.0')) self.assertEqual(status.HTTP_200_OK, resp.status_code) self.assertEqual(1, len(resp.data)) self.assertNotIn('subject_match', resp.data[0]) - def test_detail(self): - """Validate we can get a specific project.""" - project = create_project() + @utils.store_samples('project-detail') + def test_detail_by_id(self): + """Show project using ID lookup. - 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.""" + 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.""" + def test_detail_by_linkname(self): + """Show project using linkname lookup. + + 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""" + def test_detail_by_numeric_linkname(self): + """Show project using numeric linkname lookup. + + 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) + @utils.store_samples('project-detail-1.0') + def test_detail_version_1_0(self): + """Show project using API v1.0. + + Validate that newer fields are dropped for older API versions. + """ + project = create_project() + + resp = self.client.get(self.api_url(project.pk, version='1.0')) + self.assertEqual(status.HTTP_200_OK, resp.status_code) + self.assertIn('name', resp.data) + self.assertNotIn('subject_match', resp.data) + def test_create(self): """Ensure creations are rejected.""" project = create_project() @@ -126,8 +154,11 @@ class TestProjectAPI(APITestCase): 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.""" + def test_update_anonymous(self): + """Update project as anonymous user. + + Ensure updates can only be performed by maintainers. + """ project = create_project() data = {'web_url': 'TEST'} @@ -135,20 +166,41 @@ class TestProjectAPI(APITestCase): resp = self.client.patch(self.api_url(project.id), data) self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code) - # a normal user + @utils.store_samples('project-update-error-forbidden') + def test_update_non_maintainer(self): + """Update project as normal user. + + Ensure updates can only be performed by maintainers. + """ + project = create_project() + data = {'web_url': 'TEST'} + 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 + @utils.store_samples('project-update') + def test_update_maintainer(self): + """Update project as maintainer. + + Ensure updates can only be performed by maintainers. + """ + project = create_project() + data = {'web_url': 'TEST'} + 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) self.assertEqual(resp.data['web_url'], 'TEST') - # ...with the exception of some read-only fields + def test_update_readonly_field(self): + """Update read-only fields.""" + project = create_project() + + user = create_maintainer(project) + self.client.force_authenticate(user=user) resp = self.client.patch(self.api_url(project.id), { 'link_name': 'test'}) # NOTE(stephenfin): This actually returns HTTP 200 due to