From 231ac61b9111f95141e3be95127673833a5126ff Mon Sep 17 00:00:00 2001 From: andrepapoti Date: Mon, 18 Mar 2024 11:41:59 -0300 Subject: [PATCH] tests: Add tests for linking series feature Closes #506 Signed-off-by: andrepapoti --- patchwork/tests/api/test_series.py | 67 +++++++++++++- patchwork/tests/test_series.py | 143 +++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+), 3 deletions(-) diff --git a/patchwork/tests/api/test_series.py b/patchwork/tests/api/test_series.py index 730678a8..9f8240ee 100644 --- a/patchwork/tests/api/test_series.py +++ b/patchwork/tests/api/test_series.py @@ -2,6 +2,7 @@ # Copyright (C) 2018 Stephen Finucane # # SPDX-License-Identifier: GPL-2.0-or-later +import json from django.test import override_settings from django.urls import NoReverseMatch @@ -16,6 +17,7 @@ from patchwork.tests.utils import create_project from patchwork.tests.utils import create_series from patchwork.tests.utils import create_user +from patchwork.models import Person @override_settings(ENABLE_REST_API=True) @@ -152,7 +154,7 @@ def test_list_bug_335(self): create_cover(series=series_obj) create_patch(series=series_obj) - with self.assertNumQueries(6): + with self.assertNumQueries(10): self.client.get(self.api_url()) @utils.store_samples('series-detail') @@ -187,7 +189,10 @@ def test_detail_invalid(self): self.client.get(self.api_url('foo')) def test_create_update_delete(self): - """Ensure creates, updates and deletes aren't allowed""" + """ + Ensure creates and deletes aren't allowed. + Updates can be done only to specified fields + """ user = create_maintainer() user.is_superuser = True user.save() @@ -199,7 +204,63 @@ def test_create_update_delete(self): series = create_series() resp = self.client.patch(self.api_url(series.id), {'name': 'Test'}) - self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code) + self.assertEqual(status.HTTP_400_BAD_REQUEST, resp.status_code) resp = self.client.delete(self.api_url(series.id)) self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code) + + def test_series_linking(self): + user = create_user() + person = Person.objects.get(user=user) + project_obj = create_project(linkname='myproject') + series_a = create_series(project=project_obj, submitter=person) + create_cover(series=series_a) + create_patch(series=series_a) + + self.client.authenticate(user=user) + url = reverse('api-series-detail', kwargs={'pk': series_a.id}) + + # Link to another series + series_b = create_series( + project=series_a.project, submitter=series_a.submitter + ) + + resp = self.client.patch( + url, + data={'subsequent_series': [series_b.id]}, + ) + subsequent_series = json.loads(resp.content).get('subsequent_series') + self.assertEqual(resp.status_code, status.HTTP_200_OK) + self.assertEqual(len(subsequent_series), 1) + self.assertEqual( + subsequent_series[0]['web_url'], + f'http://example.com/project/myproject/list/?series={series_b.id}', + ) + + # Link to more than one series + series_c = create_series( + project=series_a.project, submitter=series_a.submitter + ) + resp = self.client.patch( + url, + data={'previous_series': [series_b.id, series_c.id]}, + ) + + previous_series = json.loads(resp.content).get('previous_series') + self.assertEqual(resp.status_code, status.HTTP_200_OK) + self.assertEqual(len(previous_series), 2) + self.assertEqual( + previous_series[1]['web_url'], + f'http://example.com/project/myproject/list/?series={series_c.id}', + ) + + # Link to a series from a different project + series_d = create_series(submitter=series_a.submitter) + + resp = self.client.patch( + url, + data={'previous_series': [series_d.id]}, + ) + + previous_series = json.loads(resp.content).get('previous_series') + self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST) diff --git a/patchwork/tests/test_series.py b/patchwork/tests/test_series.py index ce114042..13c67f8f 100644 --- a/patchwork/tests/test_series.py +++ b/patchwork/tests/test_series.py @@ -8,11 +8,14 @@ import unittest from django.test import TestCase +from rest_framework.request import HttpRequest +from rest_framework.exceptions import ValidationError from patchwork import models from patchwork import parser from patchwork.tests import utils from patchwork.views.utils import patch_to_mbox +from patchwork.api.series import SeriesSerializer TEST_SERIES_DIR = os.path.join(os.path.dirname(__file__), 'series') @@ -804,3 +807,143 @@ def test_custom_name(self): self.assertEqual(series.name, series_name) mbox.close() + + +class SeriesModelRelatedSeriesTest(TestCase): + def setUp(self): + self.series_a = utils.create_series() + self.project = self.series_a.project + self.submitter = self.series_a.submitter + self.series_b = utils.create_series(project=self.project) + self.series_c = utils.create_series(project=self.project) + self.series_d = utils.create_series() + + def test_add_previous_and_subsequent_series(self): + self.series_c.add_previous_series(self.series_b) + + self.assertIn(self.series_b, self.series_c.previous_series.all()) + self.assertIn(self.series_c, self.series_b.subsequent_series.all()) + + self.series_a.add_subsequent_series(self.series_b) + + self.assertIn(self.series_a, self.series_b.previous_series.all()) + self.assertIn(self.series_b, self.series_a.subsequent_series.all()) + + self.assertIn(self.series_b, self.series_a.subsequent_series.all()) + self.assertIn(self.series_c, self.series_b.subsequent_series.all()) + + with self.assertRaises(ValueError) as context_1: + self.series_c.add_previous_series(self.series_c) + self.assertIn( + 'A series cannot be linked to itself.', str(context_1.exception) + ) + + with self.assertRaises(ValueError) as context_2: + self.series_c.add_previous_series(self.series_d) + self.assertIn( + 'Previous series must belong to the same project.', + str(context_2.exception), + ) + + +class SeriesSerializerTestCase(TestCase): + def _mock_request(self): + mock_request = HttpRequest() + mock_request.version = '1.4' + mock_request.META['SERVER_NAME'] = 'example.com' + mock_request.META['SERVER_PORT'] = '8000' + + return mock_request + + def setUp(self): + self.request = self._mock_request() + self.series_a = utils.create_series() + self.project = self.series_a.project + self.submitter = self.series_a.submitter + self.series_b = utils.create_series(project=self.project) + self.series_c = utils.create_series() + + def test_serializer_serialization(self): + # Test serialization + serializer = SeriesSerializer( + instance=self.series_a, context={'request': self.request} + ) + + expected_data = { + 'id': self.series_a.id, + 'url': f'http://example.com:8000/api/series/{self.series_a.id}/', + 'web_url': f'http://example.com:8000{self.series_a.get_absolute_url()}', + 'project': { + 'id': self.project.id, + 'url': f'http://example.com:8000/api/projects/{self.project.id}/', + 'name': 'Test Project 0', + 'link_name': 'test-project-0', + 'list_id': 'test0.example.com', + 'list_email': 'test0@example.com', + 'web_url': '', + 'scm_url': '', + 'webscm_url': '', + 'list_archive_url': 'https://lists.example.com/', + 'list_archive_url_format': 'https://lists.example.com/mail/{}', + 'commit_url_format': '', + }, + 'name': self.series_a.name, + 'date': self.series_a.date.isoformat(), + 'submitter': { + 'id': self.submitter.id, + 'url': f'http://example.com:8000/api/people/{self.submitter.id}/', + 'name': 'test_person_0', + 'email': 'test_person_0@example.com', + }, + 'version': 1, + 'previous_series': [], + 'subsequent_series': [], + 'required_series': [], + 'required_by_series': [], + 'total': 1, + 'received_total': 0, + 'received_all': False, + 'mbox': f'http://example.com:8000{self.series_a.get_mbox_url()}', + 'cover_letter': None, + 'patches': [], + } + self.assertEqual(serializer.data, expected_data) + + def test_self_link_validation(self): + serializer = SeriesSerializer( + instance=self.series_a, + context={'request': self.request}, + data={'previous_series': [self.series_a.id]}, + ) + + with self.assertRaises(ValidationError) as context: + serializer.is_valid(raise_exception=True) + self.assertIn( + 'A series cannot be linked to itself.', str(context.exception) + ) + + def test_cross_project_validation(self): + serializer = SeriesSerializer( + instance=self.series_a, + context={'request': self.request}, + data={'previous_series': [self.series_c.id]}, + ) + + with self.assertRaises(ValidationError) as context: + serializer.is_valid(raise_exception=True) + self.assertIn( + 'Series must belong to the same project.', str(context.exception) + ) + + def test_linking(self): + serializer = SeriesSerializer( + instance=self.series_a, + context={'request': self.request}, + data={'previous_series': [self.series_b.id]}, + ) + + serializer.is_valid(raise_exception=True) + serializer.save() + + previous_series_urls = serializer.data['previous_series'] + self.assertEqual(len(previous_series_urls), 1)