From 813479fc4de155c3d0ce6f41690bec131bcac91a Mon Sep 17 00:00:00 2001 From: Andreea Fulea Date: Thu, 14 May 2026 10:48:37 +0300 Subject: [PATCH] fix: update release validation to check for None instead of empty list --- sw360/project.py | 4 +- tests/test_sw360_projects.py | 71 +++++++++++++++++++++++++++++++----- 2 files changed, 63 insertions(+), 12 deletions(-) diff --git a/sw360/project.py b/sw360/project.py index 67366e4..6b5d44a 100644 --- a/sw360/project.py +++ b/sw360/project.py @@ -401,8 +401,8 @@ def update_project_releases( if not project_id: raise SW360Error(message="No project id provided!") - if not releases: - raise SW360Error(message="No releases provided!") + if releases is None: + raise SW360Error(message="No releases list provided!") url = self.url + "resource/api/projects/" + project_id + "/releases" if add: diff --git a/tests/test_sw360_projects.py b/tests/test_sw360_projects.py index 0122f76..1262a8e 100644 --- a/tests/test_sw360_projects.py +++ b/tests/test_sw360_projects.py @@ -7,6 +7,7 @@ # SPDX-License-Identifier: MIT # ------------------------------------------------------------------------------- +import json import os import sys import tempfile @@ -999,17 +1000,11 @@ def test_update_project_releases_no_id(self) -> None: def test_update_project_releases_no_releases(self) -> None: lib = self.get_logged_in_lib() - responses.add( - responses.PATCH, - url=self.MYURL + "resource/api/projects/123", - body="4", - status=202, - ) - - with self.assertRaises(SW360Error) as context: - lib.update_project_releases([], "123") + # Passing None should raise an error (parameter not provided) + with self.assertRaises(SW360Error) as sw360er: + lib.update_project_releases(releases=None, project_id="123") # type: ignore - self.assertEqual("No releases provided!", context.exception.message) + self.assertEqual("No releases list provided!", sw360er.message) @responses.activate def test_update_project_releases_fresh_prj(self) -> None: @@ -1061,6 +1056,62 @@ def test_update_project_releases(self) -> None: releases: List[Dict[str, Any]] = [{"releaseId": "123"}] lib.update_project_releases(releases, "123", add=True) + @responses.activate + def test_override_releases_from_project(self) -> None: + """Test unlinking releases from a project by replacing the release list with a subset""" + lib = self.get_logged_in_lib() + + # List of releases to override with add=False to replace the current list of linked releases + releases_to_override = [ + {"releaseId": "111"}, + {"releaseId": "333"} + ] + + # Replace releases with only 111 and 333 (unlinking a possible222) + responses.add( + responses.POST, + url=self.MYURL + "resource/api/projects/123/releases", + body=json.dumps(releases_to_override), + status=202, + ) + + lib.update_project_releases(releases=releases_to_override, project_id="123", add=False) + + # Verify that POST (not PATCH) was called with the correct parameters + self.assertGreaterEqual(len(responses.calls), 2) + last_call = responses.calls[-1] + self.assertEqual("POST", last_call.request.method) + self.assertIn("/resource/api/projects/123/releases", last_call.request.url) + # Verify the request body contains the provided list + request_body = json.loads(last_call.request.body) + self.assertEqual(releases_to_override, request_body) + + @responses.activate + def test_unlink_all_releases_from_project(self) -> None: + """Test unlinking all releases from a project by passing an empty list""" + lib = self.get_logged_in_lib() + + # Unlink all releases by passing empty list (with add=False to use POST, not PATCH) + responses.add( + responses.POST, + url=self.MYURL + "resource/api/projects/123/releases", + body=json.dumps([]), + status=201, + ) + + # Call update_project_releases with empty list to unlink all releases + empty_releases = [] + lib.update_project_releases(empty_releases, "123", add=False) + + # Verify that POST (not PATCH) was called with the correct parameters + self.assertGreaterEqual(len(responses.calls), 2) + last_call = responses.calls[-1] + self.assertEqual("POST", last_call.request.method) + self.assertIn("/resource/api/projects/123/releases", last_call.request.url) + # Verify the request body contains an empty list + request_body = json.loads(last_call.request.body) + self.assertEqual([], request_body) + @responses.activate def test_update_project_releases_failed(self) -> None: lib = self.get_logged_in_lib()