1111from twyn .trusted_packages .exceptions import (
1212 EmptyPackagesListError ,
1313 InvalidJSONError ,
14- InvalidReferenceFormatError ,
14+ PackageNormalizingError ,
1515)
1616from twyn .trusted_packages .references .base import AbstractPackageReference
1717
@@ -140,6 +140,24 @@ def test__download_json_exception(self, mock_get: Mock) -> None:
140140 ):
141141 top_pypi ._download ()
142142
143+ def test_get_packages_no_packages_key (self ) -> None :
144+ top_pypi = TopPyPiReference (source = "foo" , cache_handler = CacheHandler ())
145+
146+ with patch ("twyn.trusted_packages.TopPyPiReference._download" ) as mock_download :
147+ mock_download .return_value = {}
148+ with pytest .raises (InvalidJSONError , match = "`packages` key not in JSON." ):
149+ top_pypi .get_packages ()
150+
151+ def test_empty_packages_list_exception (self ) -> None :
152+ with (
153+ pytest .raises (
154+ EmptyPackagesListError ,
155+ match = "Downloaded packages list is empty" ,
156+ ),
157+ patch_pypi_packages_download ([]),
158+ ):
159+ TopPyPiReference ().get_packages ()
160+
143161
144162class TestTopPyPiReference :
145163 def test_get_trusted_packages (self , tmp_path : Path ) -> None :
@@ -152,29 +170,60 @@ def test_get_trusted_packages(self, tmp_path: Path) -> None:
152170 assert packages == {"foo" , "bar" , "django" , "requests" , "sqlalchemy" }
153171 assert m_pypi .call_count == 1
154172
155- def test__parse_no_rows (self ) -> None :
156- data = {"bananas" : 5 }
157- top_pypi = TopPyPiReference (source = "foo" , cache_handler = CacheHandler ())
158-
159- with pytest .raises (InvalidReferenceFormatError , match = "Invalid JSON format." ):
160- top_pypi ._parse (data )
173+ @pytest .mark .parametrize (
174+ "package_name" ,
175+ [
176+ "my.package" ,
177+ "my-package" ,
178+ "my_package" ,
179+ "My.Package" ,
180+ ],
181+ )
182+ @patch ("twyn.trusted_packages.TopPyPiReference._get_packages_from_cache_if_enabled" )
183+ def test_normalize_package_when_loaded_from_cache (
184+ self , mock_get_packages_from_cache : Mock , package_name : Mock , tmp_path : Path
185+ ) -> None :
186+ mock_get_packages_from_cache .return_value = {package_name }
187+
188+ with patch_pypi_packages_download ([]) as m_pypi :
189+ ref = TopPyPiReference (cache_handler = CacheHandler (str (tmp_path / "cache" )))
190+ packages = ref .get_packages ()
161191
162- def test_empty_packages_list_exception (self ) -> None :
163- with pytest .raises (
164- EmptyPackagesListError ,
165- match = "Downloaded packages list is empty" ,
166- ):
167- TopPyPiReference ._parse ({"rows" : []})
192+ assert packages == {"my-package" }
193+ assert m_pypi .call_count == 0
194+ assert mock_get_packages_from_cache .call_count == 1
195+
196+ @pytest .mark .parametrize (
197+ "package_name" ,
198+ [
199+ "my.package" ,
200+ "my-package" ,
201+ "my_package" ,
202+ "My.Package" ,
203+ ],
204+ )
205+ @patch ("twyn.trusted_packages.TopPyPiReference._get_packages_from_cache_if_enabled" )
206+ def test_normalize_package_when_downloaded (
207+ self , mock_get_packages_from_cache : Mock , package_name : Mock , tmp_path : Path
208+ ) -> None :
209+ mock_get_packages_from_cache .return_value = {}
210+
211+ with patch_pypi_packages_download ([package_name ]) as m_pypi :
212+ ref = TopPyPiReference ()
213+ packages = ref .get_packages ()
168214
169- def test__parse_retrieves_package_names ( self ) -> None :
170- data = { "rows" : [{ "project" : "boto3" }, { "project" : "requests" }]}
171- top_pypi = TopPyPiReference ( source = "foo" , cache_handler = CacheHandler ())
215+ assert packages == { "my-package" }
216+ assert m_pypi . call_count == 1
217+ assert mock_get_packages_from_cache . call_count == 1
172218
173- assert top_pypi ._parse (data ) == {"boto3" , "requests" }
219+ def test_normalize_package_invalid_name_raises (self ):
220+ ref = TopPyPiReference ()
221+ with pytest .raises (PackageNormalizingError ):
222+ ref .normalize_packages ({"INVALID PACKAGE NAME!" })
174223
175224
176225class TestTopNpmReference :
177- def test_get_trusted_packages_v2 (self , tmp_path : Path ) -> None :
226+ def test_get_trusted_packages (self , tmp_path : Path ) -> None :
178227 test_packages = ["foo" , "bar" , "react" , "express" , "lodash" ]
179228
180229 with patch_npm_packages_download (test_packages ) as m_npm :
@@ -184,22 +233,7 @@ def test_get_trusted_packages_v2(self, tmp_path: Path) -> None:
184233 assert packages == {"foo" , "bar" , "react" , "express" , "lodash" }
185234 assert m_npm .call_count == 1
186235
187- def test__parse_no_rows (self ) -> None :
188- data = {"bananas" : 5 }
189- npm_ref = TopNpmReference (source = "foo" , cache_handler = CacheHandler ())
190-
191- with pytest .raises (InvalidReferenceFormatError , match = "Invalid JSON format." ):
192- npm_ref ._parse (data )
193-
194- def test_empty_packages_list_exception (self ) -> None :
195- with pytest .raises (
196- EmptyPackagesListError ,
197- match = "Downloaded packages list is empty" ,
198- ):
199- TopNpmReference ._parse ({"packages" : []})
200-
201- def test__parse_retrieves_package_names (self ) -> None :
202- data = {"packages" : [{"name" : "react" }, {"name" : "express" }]}
203- npm_ref = TopNpmReference (source = "foo" , cache_handler = CacheHandler ())
204-
205- assert npm_ref ._parse (data ) == {"react" , "express" }
236+ def test_normalize_package_invalid_name_raises (self ):
237+ ref = TopNpmReference ()
238+ with pytest .raises (PackageNormalizingError ):
239+ ref .normalize_packages ({"INVALID PACKAGE NAME!" })
0 commit comments