1313
1414import pytest
1515from models_library .products import ProductName
16+ from models_library .services_enums import ServiceType # Import ServiceType enum
1617from models_library .users import UserID
1718from packaging import version
1819from pydantic import EmailStr , HttpUrl , TypeAdapter
2122from simcore_postgres_database .models .projects import ProjectType , projects
2223from simcore_service_catalog .models .services_db import (
2324 ServiceAccessRightsAtDB ,
25+ ServiceFiltersDB ,
2426 ServiceMetaDataDBCreate ,
2527 ServiceMetaDataDBGet ,
2628 ServiceMetaDataDBPatch ,
@@ -310,7 +312,7 @@ async def test_get_latest_release(
310312 assert latest .version == fake_catalog_with_jupyterlab .expected_latest
311313
312314
313- async def test_list_all_services_and_history (
315+ async def test_list_latest_services (
314316 target_product : ProductName ,
315317 user_id : UserID ,
316318 services_repo : ServicesRepository ,
@@ -332,7 +334,7 @@ async def test_list_all_services_and_history(
332334 ), "list_latest_service does NOT show history"
333335
334336
335- async def test_listing_with_no_services (
337+ async def test_list_latest_services_with_no_services (
336338 target_product : ProductName ,
337339 services_repo : ServicesRepository ,
338340 user_id : UserID ,
@@ -344,7 +346,7 @@ async def test_listing_with_no_services(
344346 assert total_count == 0
345347
346348
347- async def test_list_all_services_and_history_with_pagination (
349+ async def test_list_latest_services_with_pagination (
348350 target_product : ProductName ,
349351 create_fake_service_data : Callable ,
350352 services_db_tables_injector : Callable ,
@@ -403,6 +405,64 @@ async def test_list_all_services_and_history_with_pagination(
403405 ), f"list of latest versions of services cannot have duplicates, found: { duplicates } "
404406
405407
408+ async def test_list_latest_services_with_filters (
409+ target_product : ProductName ,
410+ create_fake_service_data : Callable ,
411+ services_db_tables_injector : Callable ,
412+ services_repo : ServicesRepository ,
413+ user_id : UserID ,
414+ ):
415+ # Setup: Inject services with different service types
416+ await services_db_tables_injector (
417+ [
418+ create_fake_service_data (
419+ f"simcore/services/dynamic/service-type-a-{ i } " ,
420+ "1.0.0" ,
421+ team_access = None ,
422+ everyone_access = None ,
423+ product = target_product ,
424+ service_type = ServiceType .DYNAMIC .value ,
425+ )
426+ for i in range (3 )
427+ ]
428+ + [
429+ create_fake_service_data (
430+ f"simcore/services/dynamic/service-type-b-{ i } " ,
431+ "1.0.0" ,
432+ team_access = None ,
433+ everyone_access = None ,
434+ product = target_product ,
435+ service_type = ServiceType .COMPUTATIONAL .value ,
436+ )
437+ for i in range (2 )
438+ ]
439+ )
440+
441+ # Test: Apply filter for service_type=ServiceType.DYNAMIC
442+ filters = ServiceFiltersDB (service_type = ServiceType .DYNAMIC )
443+ total_count , services_items = await services_repo .list_latest_services (
444+ product_name = target_product , user_id = user_id , filters = filters
445+ )
446+ assert total_count == 3
447+ assert len (services_items ) == 3
448+ assert all (
449+ service .key .startswith ("simcore/services/dynamic/service-type-a" )
450+ for service in services_items
451+ )
452+
453+ # Test: Apply filter for service_type=ServiceType.COMPUTATIONAL
454+ filters = ServiceFiltersDB (service_type = ServiceType .COMPUTATIONAL )
455+ total_count , services_items = await services_repo .list_latest_services (
456+ product_name = target_product , user_id = user_id , filters = filters
457+ )
458+ assert total_count == 2
459+ assert len (services_items ) == 2
460+ assert all (
461+ service .key .startswith ("simcore/services/dynamic/service-type-b" )
462+ for service in services_items
463+ )
464+
465+
406466async def test_get_and_update_service_meta_data (
407467 target_product : ProductName ,
408468 create_fake_service_data : Callable ,
@@ -566,6 +626,82 @@ async def test_get_service_history_page(
566626 assert paginated_history == history [offset : offset + limit ]
567627
568628
629+ async def test_get_service_history_page_with_filters (
630+ target_product : ProductName ,
631+ create_fake_service_data : Callable ,
632+ services_db_tables_injector : Callable ,
633+ services_repo : ServicesRepository ,
634+ user_id : UserID ,
635+ ):
636+ # Setup: Inject services with multiple versions and types
637+ service_key = "simcore/services/dynamic/test-service"
638+ num_versions = 10
639+
640+ release_versions = set ()
641+ while len (release_versions ) < num_versions :
642+ release_versions .add (
643+ f"{ random .randint (0 , 2 )} .{ random .randint (0 , 9 )} .{ random .randint (0 , 9 )} " # noqa: S311
644+ )
645+
646+ await services_db_tables_injector (
647+ [
648+ create_fake_service_data (
649+ service_key ,
650+ service_version ,
651+ team_access = None ,
652+ everyone_access = None ,
653+ product = target_product ,
654+ service_type = (
655+ ServiceType .DYNAMIC .value
656+ if i % 2 == 0
657+ else ServiceType .COMPUTATIONAL .value
658+ ),
659+ )
660+ for i , service_version in enumerate (release_versions )
661+ ]
662+ )
663+ # Sort versions after injecting
664+ release_versions = sorted (release_versions , key = version .Version , reverse = True )
665+
666+ # Test: Fetch full history with no filters
667+ total_count , history = await services_repo .get_service_history_page (
668+ product_name = target_product ,
669+ user_id = user_id ,
670+ key = service_key ,
671+ )
672+ assert total_count == num_versions
673+ assert len (history ) == num_versions
674+ assert [release .version for release in history ] == release_versions
675+
676+ # Test: Apply filter for service_type=ServiceType.DYNAMIC
677+ filters = ServiceFiltersDB (service_type = ServiceType .DYNAMIC )
678+ total_count , filtered_history = await services_repo .get_service_history_page (
679+ product_name = target_product ,
680+ user_id = user_id ,
681+ key = service_key ,
682+ filters = filters ,
683+ )
684+ assert total_count == num_versions // 2
685+ assert len (filtered_history ) == num_versions // 2
686+ assert all (
687+ int (release .version .split ("." )[0 ]) % 2 == 0 for release in filtered_history
688+ )
689+
690+ # Test: Apply filter for service_type=ServiceType.COMPUTATIONAL
691+ filters = ServiceFiltersDB (service_type = ServiceType .COMPUTATIONAL )
692+ total_count , filtered_history = await services_repo .get_service_history_page (
693+ product_name = target_product ,
694+ user_id = user_id ,
695+ key = service_key ,
696+ filters = filters ,
697+ )
698+ assert total_count == num_versions // 2
699+ assert len (filtered_history ) == num_versions // 2
700+ assert all (
701+ int (release .version .split ("." )[0 ]) % 2 != 0 for release in filtered_history
702+ )
703+
704+
569705async def test_list_services_from_published_templates (
570706 user : dict [str , Any ],
571707 projects_repo : ProjectsRepository ,
0 commit comments