From patchwork Wed Mar 13 06:56:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: andrepapoti X-Patchwork-Id: 1911544 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=BEezmNps; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=2404:9400:2:0:216:3eff:fee1:b9f1; helo=lists.ozlabs.org; envelope-from=patchwork-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=patchwork.ozlabs.org) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2404:9400:2:0:216:3eff:fee1:b9f1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4TvhDK6vDmz1yWn for ; Wed, 13 Mar 2024 17:58:09 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=BEezmNps; dkim-atps=neutral Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4TvhDK5sKrz3vYW for ; Wed, 13 Mar 2024 17:58:09 +1100 (AEDT) X-Original-To: patchwork@lists.ozlabs.org Delivered-To: patchwork@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=BEezmNps; dkim-atps=neutral Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:4864:20::42a; helo=mail-pf1-x42a.google.com; envelope-from=andrepapoti@gmail.com; receiver=lists.ozlabs.org) Received: from mail-pf1-x42a.google.com (mail-pf1-x42a.google.com [IPv6:2607:f8b0:4864:20::42a]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4TvhCr1t8xz3fNd for ; Wed, 13 Mar 2024 17:57:44 +1100 (AEDT) Received: by mail-pf1-x42a.google.com with SMTP id d2e1a72fcca58-6e6b729669bso311546b3a.3 for ; Tue, 12 Mar 2024 23:57:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710313061; x=1710917861; darn=lists.ozlabs.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=5BYxYjOFJzBtFqd3jGu5GMLS7R33LgrofCXNJ3DfbKs=; b=BEezmNpsJOKRGeyLZyQP600Azq8l1Km0AyzRGPSRnkSfAc/oxDodg299lYqq/D13qS Hl0Bzm/nx8FHlpSVsTd4RwITf/Tc8q12kQvIze/Jkh2wY7z24A6jXUBpifKjGZUP1RgX WzGqWRDajucFf7p6TkrJrDnu7vybYtFUJvYigid2hz2PxvAJri0hHqeR9NJD5e/3p/Uz EoT+F2TbAoCriQrFpgRnVxkQ/F4QPDhBPRa9BgrMyHWeJultqbpEzrAXOW/kCvtA0ICW mzB8RdyvMcNYTxOnmc1I6MCneYqhQWVKoLDXT9EIE6E8VmR/rCma59CqinDsys96GaHX yWYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710313061; x=1710917861; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=5BYxYjOFJzBtFqd3jGu5GMLS7R33LgrofCXNJ3DfbKs=; b=hF0OIW108va9rCYzhuQ19IN8TtMiuGiCJAOrkDuwupmD0znsSs/pdAv0YfRSVF72rz uTbYKU6FTYA5/pGjgZIgvAEx8mxXM34e/0OVdONgiEdmy6dy5Uc6mWpINHNJy3bAheTN 0NystsxLGD+lfgHj9RlCoB14Uoly/JQ1tPFaCZdWdNjUNL1TKHpeS0mIvthhjDYzuejC 9Lk5DePEKC7T67DBMHnsQyeJJQSyOXTcrkWoUHpVUIjyFbCyR7Rl1AQWQTDpk+I6Omjk 3gfnbXhB6lORT/KwWCnzqzr/VVU8KWFuh6C/d+Gjy8a5yrhlUa1+8Q8wRciadKQi3m6d qTBw== X-Gm-Message-State: AOJu0YxobAsFqwiuuwykhin6wBqu1ahF7qebJfZTh7RlxvdTpY/EbgQ9 0jczf0UWKlwFC+qkS6TxJ40LM1QjRDtIrDXa7H1yDZaQY79aSnwjRHUji+pz X-Google-Smtp-Source: AGHT+IGZWUCSYoLAipxHjpD5NGF5kFm5EqPVomE+gB9jDr2lvN2kxm5ujrhwU6X5T5rDTCL5PIjFOA== X-Received: by 2002:a05:6a00:1403:b0:6e6:8964:7fcd with SMTP id l3-20020a056a00140300b006e689647fcdmr1757560pfu.24.1710313060996; Tue, 12 Mar 2024 23:57:40 -0700 (PDT) Received: from localhost.localdomain ([2804:1b3:a4c0:b1de:3ec4:883:9cca:f0a7]) by smtp.gmail.com with ESMTPSA id le21-20020a056a004fd500b006e691787eaesm4843998pfb.34.2024.03.12.23.57.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Mar 2024 23:57:40 -0700 (PDT) From: andrepapoti To: patchwork@lists.ozlabs.org Subject: [PATCH 6/9] tests: Add tests for Note related endpoints Date: Wed, 13 Mar 2024 03:56:38 -0300 Message-ID: <20240313065642.385843-6-andrepapoti@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240313065642.385843-1-andrepapoti@gmail.com> References: <20240313065642.385843-1-andrepapoti@gmail.com> MIME-Version: 1.0 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: , Errors-To: patchwork-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Patchwork" Signed-off-by: andrepapoti --- patchwork/tests/api/test_notes.py | 232 ++++++++++++++++++++++++++++++ patchwork/tests/utils.py | 12 ++ 2 files changed, 244 insertions(+) create mode 100644 patchwork/tests/api/test_notes.py diff --git a/patchwork/tests/api/test_notes.py b/patchwork/tests/api/test_notes.py new file mode 100644 index 0000000..fc2d2e3 --- /dev/null +++ b/patchwork/tests/api/test_notes.py @@ -0,0 +1,232 @@ +# Patchwork - automated patch tracking system +# Copyright (C) 2018 Red Hat +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from django.test import override_settings +from django.urls import reverse +from rest_framework import status + +from patchwork.models import Note +from patchwork.tests.api import utils +from patchwork.tests.utils import create_patch +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_note +from patchwork.tests.utils import create_user + + +@override_settings(ENABLE_REST_API=True) +class TestPatchNotes(utils.APITestCase): + def setUp(self): + super(TestPatchNotes, self).setUp() + self.project = create_project() + self.user = create_maintainer(self.project) + self.patch = create_patch(project=self.project) + + def check_for_expected(self, instance, response_data): + self.assertEqual(instance.id, response_data['id']) + self.assertEqual(instance.patch.id, response_data['patch']['id']) + self.assertEqual( + instance.submitter.id, response_data['submitter']['id'] + ) + + def test_create_note(self): + start_num = Note.objects.count() + url = reverse( + 'api-patch-note-list', kwargs={'patch_id': self.patch.id} + ) + data = {'content': 'New note'} + self.client.authenticate(user=self.user) + resp = self.client.post(url, data=data) + end_num = Note.objects.count() + + self.assertEqual(status.HTTP_201_CREATED, resp.status_code) + self.assertEqual(start_num + 1, end_num) + + def test_get_note_as_maintainer(self): + """Retrieve patch note with an user that is a maintainer.""" + person = create_person(user=self.user) + note = create_note(patch=self.patch, submitter=person) + + self.client.authenticate(user=self.user) + url = reverse( + 'api-patch-note-detail', + kwargs={'patch_id': self.patch.id, 'note_id': note.id}, + ) + resp = self.client.get(url) + + self.assertEqual(status.HTTP_200_OK, resp.status_code) + self.check_for_expected(note, resp.data) + + def test_get_note_as_non_maintainer(self): + """Retrieve patch note with an user that is not a maintainer.""" + person = create_person() + note = create_note(patch=self.patch) + + self.client.authenticate(user=person.user) + url = reverse( + 'api-patch-note-detail', + kwargs={'patch_id': self.patch.id, 'note_id': note.id}, + ) + resp = self.client.get(url) + + self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code) + + def test_get_note_public(self): + """Retrieve public patch note with an user that is not a maintainer.""" + person = create_person(user=self.user) + note = create_note(patch=self.patch, maintainer_only=False) + + self.client.authenticate(user=person.user) + url = reverse( + 'api-patch-note-detail', + kwargs={'patch_id': self.patch.id, 'note_id': note.id}, + ) + resp = self.client.get(url) + + self.assertEqual(status.HTTP_200_OK, resp.status_code) + self.check_for_expected(note, resp.data) + + def test_get_note_list_as_maintainer(self): + """Retrieve notes from a patch note with an user that is a maintainer.""" + person = create_person(user=self.user) + create_note(patch=self.patch, submitter=person) + create_note(patch=self.patch, submitter=person, maintainer_only=False) + + self.client.authenticate(user=self.user) + url = reverse( + 'api-patch-note-list', kwargs={'patch_id': self.patch.id} + ) + resp = self.client.get(url) + + self.assertEqual(status.HTTP_200_OK, resp.status_code) + self.assertEqual(len(resp.data), 2) + + def test_get_note_list_as_non_maintainer(self): + """Retrieve notes from a patch note with an user that is not a maintainer.""" + person = create_person(user=self.user) + create_note(patch=self.patch, submitter=person) + public_note = create_note( + patch=self.patch, submitter=person, maintainer_only=False + ) + not_maintainer = create_user() + + self.client.authenticate(user=not_maintainer) + url = reverse( + 'api-patch-note-list', kwargs={'patch_id': self.patch.id} + ) + resp = self.client.get(url) + + self.assertEqual(status.HTTP_200_OK, resp.status_code) + self.assertEqual(len(resp.data), 1) + self.assertEqual(resp.data[0]['id'], public_note.id) + + def test_edit_note_as_maintainer(self): + """Edit patch note with an user that is a maintainer.""" + person = create_person(user=self.user) + note = create_note(patch=self.patch, submitter=person) + + url = reverse( + 'api-patch-note-detail', + kwargs={'patch_id': self.patch.id, 'note_id': note.id}, + ) + data = {'content': 'New content'} + self.client.authenticate(user=person.user) + resp = self.client.patch(url, data=data) + + self.assertEqual(status.HTTP_200_OK, resp.status_code) + self.check_for_expected(note, resp.data) + self.assertNotEqual(note.content, resp.data['content']) + self.assertNotEqual(note.last_modified, resp.data['last_modified']) + + def test_edit_note_as_non_maintainer(self): + """Edit patch note with an user that is not a maintainer.""" + person = create_person() + note = create_note(patch=self.patch) + + url = reverse( + 'api-patch-note-detail', + kwargs={'patch_id': self.patch.id, 'note_id': note.id}, + ) + data = {'content': 'New content'} + self.client.authenticate(user=person.user) + resp = self.client.patch(url, data=data) + + self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code) + + def test_edit_note_public(self): + """Edit public patch note with an user that is a maintainerwith an user that is not a maintainer.""" + person = create_person() + note = create_note(patch=self.patch, maintainer_only=False) + + url = reverse( + 'api-patch-note-detail', + kwargs={'patch_id': self.patch.id, 'note_id': note.id}, + ) + data = {'content': 'New content'} + self.client.authenticate(user=person.user) + resp = self.client.patch(url, data=data) + + self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code) + + def test_delete_note_as_maintainer(self): + """Delete patch note with an user that is a maintainer.""" + person = create_person(user=self.user) + note = create_note(patch=self.patch, submitter=person) + start_num = Note.objects.count() + + url = reverse( + 'api-patch-note-detail', + kwargs={'patch_id': self.patch.id, 'note_id': note.id}, + ) + + self.client.authenticate(user=person.user) + resp = self.client.delete(url) + end_num = Note.objects.count() + + self.assertEqual(status.HTTP_204_NO_CONTENT, resp.status_code) + self.assertEqual(start_num - 1, end_num) + + def test_delete_note_as_non_maintainer(self): + """Delete patch note with an user that is not a maintainer.""" + person = create_person() + note = create_note(patch=self.patch) + + url = reverse( + 'api-patch-note-detail', + kwargs={'patch_id': self.patch.id, 'note_id': note.id}, + ) + + self.client.authenticate(user=person.user) + resp = self.client.delete(url) + + self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code) + + def test_delete_note_public(self): + """Delete public patch note with an user that is a maintainerwith an user that is not a maintainer.""" + person = create_person() + note = create_note(patch=self.patch, maintainer_only=False) + + url = reverse( + 'api-patch-note-detail', + kwargs={'patch_id': self.patch.id, 'note_id': note.id}, + ) + self.client.authenticate(user=person.user) + resp = self.client.delete(url) + + self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code) + + def test_notes_in_patch(self): + url = reverse('api-patch-detail', kwargs={'pk': self.patch.id}) + self.client.authenticate(user=self.user) + resp = self.client.get(url) + + correct_path = reverse( + 'api-patch-note-list', kwargs={'patch_id': self.patch.id} + ) + self.assertEqual( + resp.data.get('notes'), + f'http://example.com{correct_path}', + ) diff --git a/patchwork/tests/utils.py b/patchwork/tests/utils.py index 4f40489..3fbb689 100644 --- a/patchwork/tests/utils.py +++ b/patchwork/tests/utils.py @@ -15,6 +15,7 @@ from patchwork.models import Bundle from patchwork.models import Check from patchwork.models import Cover from patchwork.models import CoverComment +from patchwork.models import Note from patchwork.models import Patch from patchwork.models import PatchComment from patchwork.models import PatchRelation @@ -270,6 +271,17 @@ def create_patch_comment(**kwargs): return PatchComment.objects.create(**values) +def create_note(**kwargs): + """Create 'Note' object.""" + values = { + 'submitter': create_person() if 'submitter' not in kwargs else None, + 'content': 'Note content', + } + values.update(kwargs) + + return Note.objects.create(**values) + + def create_check(**kwargs): """Create 'Check' object.""" values = {