Skip to content

Commit 4c51690

Browse files
committed
adds first repo tests
1 parent b04a2fd commit 4c51690

File tree

3 files changed

+168
-10
lines changed

3 files changed

+168
-10
lines changed

packages/pytest-simcore/src/pytest_simcore/helpers/faker_factories.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,3 +571,32 @@ def random_itis_vip_available_download_item(
571571

572572
data.update(**overrides)
573573
return data
574+
575+
576+
def random_service_consume_filetype(
577+
*,
578+
service_key: str,
579+
service_version: str,
580+
fake: Faker = DEFAULT_FAKER,
581+
**overrides,
582+
) -> dict[str, Any]:
583+
from simcore_postgres_database.models.services_consume_filetypes import (
584+
services_consume_filetypes,
585+
)
586+
587+
data = {
588+
"service_key": service_key,
589+
"service_version": service_version,
590+
"service_display_name": fake.company(),
591+
"service_input_port": fake.word(),
592+
"filetype": fake.random_element(["CSV", "VTK", "H5", "JSON", "TXT"]),
593+
"preference_order": fake.pyint(min_value=0, max_value=10),
594+
"is_guest_allowed": fake.pybool(),
595+
}
596+
597+
assert set(data.keys()).issubset( # nosec
598+
{c.name for c in services_consume_filetypes.columns}
599+
)
600+
601+
data.update(overrides)
602+
return data

services/web/server/src/simcore_service_webserver/studies_dispatcher/_models.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,10 @@ class ServiceInfo(BaseModel):
88
key: ServiceKey
99
version: ServiceVersion
1010

11-
label: Annotated[str, Field(..., description="Display name")]
11+
label: Annotated[str, Field(description="Display name")]
1212

13-
thumbnail: HttpUrl = Field(
14-
default=TypeAdapter(HttpUrl).validate_python(
15-
"https://via.placeholder.com/170x120.png"
16-
)
13+
thumbnail: Annotated[HttpUrl, Field()] = TypeAdapter(HttpUrl).validate_python(
14+
"https://via.placeholder.com/170x120.png"
1715
)
1816

1917
is_guest_allowed: bool = True
@@ -37,12 +35,12 @@ class ViewerInfo(ServiceInfo):
3735
to visualize a file of that type
3836
"""
3937

40-
filetype: str = Field(..., description="Filetype associated to this viewer")
38+
filetype: Annotated[str, Field(description="Filetype associated to this viewer")]
4139

42-
input_port_key: str = Field(
43-
...,
44-
description="Name of the connection port, since it is service-dependent",
45-
)
40+
input_port_key: Annotated[
41+
str,
42+
Field(description="Name of the connection port, since it is service-dependent"),
43+
]
4644

4745

4846
class ServiceParams(BaseModel):
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# pylint: disable=protected-access
2+
# pylint: disable=redefined-outer-name
3+
# pylint: disable=too-many-arguments
4+
# pylint: disable=unused-argument
5+
# pylint: disable=unused-variable
6+
7+
from collections.abc import AsyncIterator
8+
9+
import pytest
10+
from pytest_simcore.helpers.faker_factories import (
11+
random_service_consume_filetype,
12+
random_service_meta_data,
13+
)
14+
from pytest_simcore.helpers.postgres_tools import insert_and_get_row_lifespan
15+
from simcore_postgres_database.models.services import services_meta_data
16+
from simcore_postgres_database.models.services_consume_filetypes import (
17+
services_consume_filetypes,
18+
)
19+
from simcore_service_webserver.studies_dispatcher._models import ViewerInfo
20+
from simcore_service_webserver.studies_dispatcher._repository import (
21+
StudiesDispatcherRepository,
22+
)
23+
from sqlalchemy.ext.asyncio import AsyncEngine
24+
25+
26+
@pytest.fixture
27+
async def service_metadata_in_db(asyncpg_engine: AsyncEngine) -> AsyncIterator[dict]:
28+
"""Pre-populate services metadata table with test data."""
29+
service_data = random_service_meta_data(
30+
key="simcore/services/dynamic/viewer",
31+
version="1.0.0",
32+
name="Test Viewer Service",
33+
)
34+
# pylint: disable=contextmanager-generator-missing-cleanup
35+
async with insert_and_get_row_lifespan(
36+
asyncpg_engine,
37+
table=services_meta_data,
38+
values=service_data,
39+
pk_col=services_meta_data.c.key,
40+
pk_value=service_data["key"],
41+
) as row:
42+
yield row
43+
# cleanup happens automatically
44+
45+
46+
@pytest.fixture
47+
async def consume_filetypes_in_db(
48+
asyncpg_engine: AsyncEngine, service_metadata_in_db: dict
49+
):
50+
"""Pre-populate services consume filetypes table with test data."""
51+
consume_data = random_service_consume_filetype(
52+
service_key=service_metadata_in_db["key"],
53+
service_version=service_metadata_in_db["version"],
54+
filetype="CSV",
55+
service_display_name="CSV Viewer",
56+
service_input_port="input_1",
57+
preference_order=1,
58+
is_guest_allowed=True,
59+
)
60+
61+
# pylint: disable=contextmanager-generator-missing-cleanup
62+
async with insert_and_get_row_lifespan(
63+
asyncpg_engine,
64+
table=services_consume_filetypes,
65+
values=consume_data,
66+
pk_col=services_consume_filetypes.c.service_key,
67+
pk_value=consume_data["service_key"],
68+
) as row:
69+
yield row
70+
71+
72+
@pytest.fixture
73+
def studies_dispatcher_repository(
74+
asyncpg_engine: AsyncEngine,
75+
) -> StudiesDispatcherRepository:
76+
"""Create StudiesDispatcherRepository instance."""
77+
return StudiesDispatcherRepository(engine=asyncpg_engine)
78+
79+
80+
async def test_list_viewers_info_all(
81+
studies_dispatcher_repository: StudiesDispatcherRepository,
82+
consume_filetypes_in_db: dict,
83+
):
84+
"""Test listing all viewer services."""
85+
# Act
86+
viewers = await studies_dispatcher_repository.list_viewers_info()
87+
88+
# Assert
89+
assert len(viewers) == 1
90+
viewer = viewers[0]
91+
assert isinstance(viewer, ViewerInfo)
92+
assert viewer.key == consume_filetypes_in_db["service_key"]
93+
assert viewer.version == consume_filetypes_in_db["service_version"]
94+
assert viewer.filetype == consume_filetypes_in_db["filetype"]
95+
assert viewer.label == consume_filetypes_in_db["service_display_name"]
96+
assert viewer.input_port_key == consume_filetypes_in_db["service_input_port"]
97+
assert viewer.is_guest_allowed == consume_filetypes_in_db["is_guest_allowed"]
98+
99+
100+
async def test_list_viewers_info_filtered_by_filetype(
101+
studies_dispatcher_repository: StudiesDispatcherRepository,
102+
consume_filetypes_in_db: dict,
103+
):
104+
"""Test listing viewer services filtered by file type."""
105+
# Act
106+
viewers = await studies_dispatcher_repository.list_viewers_info(file_type="CSV")
107+
108+
# Assert
109+
assert len(viewers) == 1
110+
assert viewers[0].filetype == "CSV"
111+
112+
# Test with non-existent filetype
113+
viewers_empty = await studies_dispatcher_repository.list_viewers_info(
114+
file_type="NONEXISTENT"
115+
)
116+
assert len(viewers_empty) == 0
117+
118+
119+
async def test_list_viewers_info_only_default(
120+
studies_dispatcher_repository: StudiesDispatcherRepository,
121+
consume_filetypes_in_db: dict,
122+
):
123+
"""Test listing only default viewer services."""
124+
# Act
125+
viewers = await studies_dispatcher_repository.list_viewers_info(
126+
file_type="CSV", only_default=True
127+
)
128+
129+
# Assert
130+
assert len(viewers) == 1
131+
assert viewers[0].filetype == "CSV"

0 commit comments

Comments
 (0)