| 
13 | 13 | from models_library.products import ProductName  | 
14 | 14 | from models_library.projects import ProjectID  | 
15 | 15 | from models_library.rpc.webserver.projects import (  | 
 | 16 | +    ListProjectsMarkedAsJobRpcFilter,  | 
 | 17 | +    MetadataFilterItem,  | 
16 | 18 |     PageRpcProjectJobRpcGet,  | 
17 | 19 |     ProjectJobRpcGet,  | 
18 | 20 | )  | 
@@ -114,7 +116,9 @@ async def test_rpc_client_list_my_projects_marked_as_jobs(  | 
114 | 116 |         rpc_client=rpc_client,  | 
115 | 117 |         product_name=product_name,  | 
116 | 118 |         user_id=user_id,  | 
117 |  | -        filters={"job_parent_resource_name_prefix": "solvers/solver123"},  | 
 | 119 | +        filters=ListProjectsMarkedAsJobRpcFilter(  | 
 | 120 | +            job_parent_resource_name_prefix="solvers/solver123"  | 
 | 121 | +        ),  | 
118 | 122 |     )  | 
119 | 123 | 
 
  | 
120 | 124 |     assert page.meta.total == 1  | 
@@ -191,3 +195,115 @@ async def test_errors_on_rpc_client_mark_project_as_job(  | 
191 | 195 |     assert exc_info.value.error_count() == 1  | 
192 | 196 |     assert exc_info.value.errors()[0]["loc"] == ("job_parent_resource_name",)  | 
193 | 197 |     assert exc_info.value.errors()[0]["type"] == "value_error"  | 
 | 198 | + | 
 | 199 | + | 
 | 200 | +async def test_rpc_client_list_projects_marked_as_jobs_with_metadata_filter(  | 
 | 201 | +    rpc_client: RabbitMQRPCClient,  | 
 | 202 | +    product_name: ProductName,  | 
 | 203 | +    logged_user: UserInfoDict,  | 
 | 204 | +    user_project: ProjectDict,  | 
 | 205 | +    client: TestClient,  | 
 | 206 | +):  | 
 | 207 | +    from simcore_service_webserver.projects import _metadata_service  | 
 | 208 | + | 
 | 209 | +    project_uuid = ProjectID(user_project["uuid"])  | 
 | 210 | +    user_id = logged_user["id"]  | 
 | 211 | + | 
 | 212 | +    # Mark the project as a job  | 
 | 213 | +    await projects_rpc.mark_project_as_job(  | 
 | 214 | +        rpc_client=rpc_client,  | 
 | 215 | +        product_name=product_name,  | 
 | 216 | +        user_id=user_id,  | 
 | 217 | +        project_uuid=project_uuid,  | 
 | 218 | +        job_parent_resource_name="solvers/solver123/version/1.2.3",  | 
 | 219 | +    )  | 
 | 220 | + | 
 | 221 | +    # Set custom metadata on the project  | 
 | 222 | +    custom_metadata = {  | 
 | 223 | +        "solver_type": "FEM",  | 
 | 224 | +        "mesh_cells": "10000",  | 
 | 225 | +        "domain": "biomedical",  | 
 | 226 | +    }  | 
 | 227 | + | 
 | 228 | +    await _metadata_service.set_project_custom_metadata(  | 
 | 229 | +        app=client.app,  | 
 | 230 | +        user_id=user_id,  | 
 | 231 | +        project_uuid=project_uuid,  | 
 | 232 | +        value=custom_metadata,  | 
 | 233 | +    )  | 
 | 234 | + | 
 | 235 | +    # Test with exact match on metadata field  | 
 | 236 | +    page: PageRpcProjectJobRpcGet = await projects_rpc.list_projects_marked_as_jobs(  | 
 | 237 | +        rpc_client=rpc_client,  | 
 | 238 | +        product_name=product_name,  | 
 | 239 | +        user_id=user_id,  | 
 | 240 | +        filters=ListProjectsMarkedAsJobRpcFilter(  | 
 | 241 | +            job_parent_resource_name_prefix="solvers/solver123",  | 
 | 242 | +            any_of_metadata=[MetadataFilterItem(name="solver_type", pattern="FEM")],  | 
 | 243 | +        ),  | 
 | 244 | +    )  | 
 | 245 | + | 
 | 246 | +    assert page.meta.total == 1  | 
 | 247 | +    assert len(page.data) == 1  | 
 | 248 | +    assert page.data[0].uuid == project_uuid  | 
 | 249 | + | 
 | 250 | +    # Test with pattern match on metadata field  | 
 | 251 | +    page = await projects_rpc.list_projects_marked_as_jobs(  | 
 | 252 | +        rpc_client=rpc_client,  | 
 | 253 | +        product_name=product_name,  | 
 | 254 | +        user_id=user_id,  | 
 | 255 | +        filters=ListProjectsMarkedAsJobRpcFilter(  | 
 | 256 | +            any_of_metadata=[MetadataFilterItem(name="mesh_cells", pattern="1*")],  | 
 | 257 | +        ),  | 
 | 258 | +    )  | 
 | 259 | + | 
 | 260 | +    assert page.meta.total == 1  | 
 | 261 | +    assert len(page.data) == 1  | 
 | 262 | +    assert page.data[0].uuid == project_uuid  | 
 | 263 | + | 
 | 264 | +    # Test with multiple metadata fields (any match should return the project)  | 
 | 265 | +    page = await projects_rpc.list_projects_marked_as_jobs(  | 
 | 266 | +        rpc_client=rpc_client,  | 
 | 267 | +        product_name=product_name,  | 
 | 268 | +        user_id=user_id,  | 
 | 269 | +        filters=ListProjectsMarkedAsJobRpcFilter(  | 
 | 270 | +            any_of_metadata=[  | 
 | 271 | +                MetadataFilterItem(name="solver_type", pattern="FEM"),  | 
 | 272 | +                MetadataFilterItem(name="non_existent", pattern="value"),  | 
 | 273 | +            ],  | 
 | 274 | +        ),  | 
 | 275 | +    )  | 
 | 276 | + | 
 | 277 | +    assert page.meta.total == 1  | 
 | 278 | +    assert len(page.data) == 1  | 
 | 279 | + | 
 | 280 | +    # Test with no matches  | 
 | 281 | +    page = await projects_rpc.list_projects_marked_as_jobs(  | 
 | 282 | +        rpc_client=rpc_client,  | 
 | 283 | +        product_name=product_name,  | 
 | 284 | +        user_id=user_id,  | 
 | 285 | +        filters=ListProjectsMarkedAsJobRpcFilter(  | 
 | 286 | +            any_of_metadata=[  | 
 | 287 | +                MetadataFilterItem(name="solver_type", pattern="CFD"),  # No match  | 
 | 288 | +            ],  | 
 | 289 | +        ),  | 
 | 290 | +    )  | 
 | 291 | + | 
 | 292 | +    assert page.meta.total == 0  | 
 | 293 | +    assert len(page.data) == 0  | 
 | 294 | + | 
 | 295 | +    # Test with combination of resource prefix and metadata  | 
 | 296 | +    page = await projects_rpc.list_projects_marked_as_jobs(  | 
 | 297 | +        rpc_client=rpc_client,  | 
 | 298 | +        product_name=product_name,  | 
 | 299 | +        user_id=user_id,  | 
 | 300 | +        filters=ListProjectsMarkedAsJobRpcFilter(  | 
 | 301 | +            job_parent_resource_name_prefix="wrong/prefix",  | 
 | 302 | +            any_of_metadata=[  | 
 | 303 | +                MetadataFilterItem(name="solver_type", pattern="FEM"),  | 
 | 304 | +            ],  | 
 | 305 | +        ),  | 
 | 306 | +    )  | 
 | 307 | + | 
 | 308 | +    assert page.meta.total == 0  | 
 | 309 | +    assert len(page.data) == 0  | 
0 commit comments