Skip to content

Commit 1e86033

Browse files
committed
split tests
1 parent d23d5e8 commit 1e86033

File tree

4 files changed

+354
-336
lines changed

4 files changed

+354
-336
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
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 models_library.groups import EVERYONE_GROUP_ID
11+
from pytest_simcore.helpers.faker_factories import (
12+
random_service_access_rights,
13+
random_service_consume_filetype,
14+
random_service_meta_data,
15+
)
16+
from pytest_simcore.helpers.postgres_tools import insert_and_get_row_lifespan
17+
from simcore_postgres_database.models.services import (
18+
services_access_rights,
19+
services_meta_data,
20+
)
21+
from simcore_postgres_database.models.services_consume_filetypes import (
22+
services_consume_filetypes,
23+
)
24+
from sqlalchemy.ext.asyncio import AsyncEngine
25+
26+
27+
@pytest.fixture
28+
async def service_metadata_in_db(asyncpg_engine: AsyncEngine) -> AsyncIterator[dict]:
29+
"""Pre-populate services metadata table with test data."""
30+
service_data = random_service_meta_data(
31+
key="simcore/services/dynamic/viewer",
32+
version="1.0.0",
33+
name="Test Viewer Service",
34+
)
35+
# pylint: disable=contextmanager-generator-missing-cleanup
36+
async with insert_and_get_row_lifespan(
37+
asyncpg_engine,
38+
table=services_meta_data,
39+
values=service_data,
40+
pk_col=services_meta_data.c.key,
41+
pk_value=service_data["key"],
42+
) as row:
43+
yield row
44+
# cleanup happens automatically
45+
46+
47+
@pytest.fixture
48+
async def consume_filetypes_in_db(
49+
asyncpg_engine: AsyncEngine, service_metadata_in_db: dict
50+
):
51+
"""Pre-populate services consume filetypes table with test data."""
52+
consume_data = random_service_consume_filetype(
53+
service_key=service_metadata_in_db["key"],
54+
service_version=service_metadata_in_db["version"],
55+
filetype="CSV",
56+
service_display_name="CSV Viewer",
57+
service_input_port="input_1",
58+
preference_order=1,
59+
is_guest_allowed=True,
60+
)
61+
62+
# pylint: disable=contextmanager-generator-missing-cleanup
63+
async with insert_and_get_row_lifespan(
64+
asyncpg_engine,
65+
table=services_consume_filetypes,
66+
values=consume_data,
67+
pk_col=services_consume_filetypes.c.service_key,
68+
pk_value=consume_data["service_key"],
69+
) as row:
70+
yield row
71+
72+
73+
@pytest.fixture
74+
async def service_access_rights_in_db(
75+
asyncpg_engine: AsyncEngine, service_metadata_in_db: dict
76+
):
77+
"""Pre-populate services access rights table with test data."""
78+
access_data = random_service_access_rights(
79+
key=service_metadata_in_db["key"],
80+
version=service_metadata_in_db["version"],
81+
gid=EVERYONE_GROUP_ID,
82+
execute_access=True,
83+
product_name="osparc",
84+
)
85+
86+
# pylint: disable=contextmanager-generator-missing-cleanup
87+
async with insert_and_get_row_lifespan(
88+
asyncpg_engine,
89+
table=services_access_rights,
90+
values=access_data,
91+
pk_col=services_access_rights.c.key,
92+
pk_value=access_data["key"],
93+
) as row:
94+
yield row
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
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+
8+
import pytest
9+
from models_library.services import ServiceKey, ServiceVersion
10+
from simcore_service_webserver.studies_dispatcher._catalog import (
11+
ServiceMetaData,
12+
ValidService,
13+
iter_latest_product_services,
14+
validate_requested_service,
15+
)
16+
from simcore_service_webserver.studies_dispatcher._errors import ServiceNotFoundError
17+
from simcore_service_webserver.studies_dispatcher.settings import (
18+
StudiesDispatcherSettings,
19+
)
20+
from sqlalchemy.ext.asyncio import AsyncEngine
21+
22+
23+
@pytest.fixture
24+
def studies_dispatcher_settings() -> StudiesDispatcherSettings:
25+
return StudiesDispatcherSettings(
26+
STUDIES_DEFAULT_SERVICE_THUMBNAIL="https://example.com/default-thumbnail.png"
27+
)
28+
29+
30+
async def test_iter_latest_product_services(
31+
asyncpg_engine: AsyncEngine,
32+
studies_dispatcher_settings: StudiesDispatcherSettings,
33+
service_metadata_in_db: dict,
34+
service_access_rights_in_db: dict,
35+
consume_filetypes_in_db: dict,
36+
):
37+
"""Test iterating through latest product services."""
38+
# Act
39+
services = []
40+
async for service in iter_latest_product_services(
41+
studies_dispatcher_settings, asyncpg_engine, product_name="osparc"
42+
):
43+
services.append(service)
44+
45+
# Assert
46+
assert len(services) == 1
47+
service = services[0]
48+
assert isinstance(service, ServiceMetaData)
49+
assert service.key == service_metadata_in_db["key"]
50+
assert service.version == service_metadata_in_db["version"]
51+
assert service.title == service_metadata_in_db["name"]
52+
assert service.description == service_metadata_in_db["description"]
53+
assert service.file_extensions == [consume_filetypes_in_db["filetype"]]
54+
55+
56+
async def test_iter_latest_product_services_with_pagination(
57+
asyncpg_engine: AsyncEngine,
58+
studies_dispatcher_settings: StudiesDispatcherSettings,
59+
service_metadata_in_db: dict,
60+
service_access_rights_in_db: dict,
61+
):
62+
"""Test iterating through services with pagination."""
63+
# Act
64+
services = []
65+
async for service in iter_latest_product_services(
66+
studies_dispatcher_settings,
67+
asyncpg_engine,
68+
product_name="osparc",
69+
page_number=1,
70+
page_size=1,
71+
):
72+
services.append(service)
73+
74+
# Assert
75+
assert len(services) == 1
76+
77+
78+
async def test_validate_requested_service_success(
79+
asyncpg_engine: AsyncEngine,
80+
service_metadata_in_db: dict,
81+
consume_filetypes_in_db: dict,
82+
):
83+
"""Test validating a service that exists and is valid."""
84+
# Act
85+
valid_service = await validate_requested_service(
86+
engine=asyncpg_engine,
87+
service_key=ServiceKey(service_metadata_in_db["key"]),
88+
service_version=ServiceVersion(service_metadata_in_db["version"]),
89+
)
90+
91+
# Assert
92+
assert isinstance(valid_service, ValidService)
93+
assert valid_service.key == service_metadata_in_db["key"]
94+
assert valid_service.version == service_metadata_in_db["version"]
95+
assert valid_service.title == service_metadata_in_db["name"]
96+
assert valid_service.is_public == consume_filetypes_in_db["is_guest_allowed"]
97+
assert str(valid_service.thumbnail) == str(service_metadata_in_db["thumbnail"])
98+
99+
100+
async def test_validate_requested_service_not_found(
101+
asyncpg_engine: AsyncEngine,
102+
):
103+
"""Test validating a service that doesn't exist."""
104+
# Act & Assert
105+
with pytest.raises(ServiceNotFoundError) as exc_info:
106+
await validate_requested_service(
107+
asyncpg_engine,
108+
service_key=ServiceKey("simcore/services/dynamic/nonexistent"),
109+
service_version=ServiceVersion("1.0.0"),
110+
)
111+
112+
assert exc_info.value.service_key == "simcore/services/dynamic/nonexistent"
113+
assert exc_info.value.service_version == "1.0.0"
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
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+
8+
import pytest
9+
from simcore_service_webserver.studies_dispatcher._models import ViewerInfo
10+
from simcore_service_webserver.studies_dispatcher._repository import (
11+
StudiesDispatcherRepository,
12+
)
13+
from sqlalchemy.ext.asyncio import AsyncEngine
14+
15+
16+
@pytest.fixture
17+
def studies_dispatcher_repository(
18+
asyncpg_engine: AsyncEngine,
19+
) -> StudiesDispatcherRepository:
20+
"""Create StudiesDispatcherRepository instance."""
21+
return StudiesDispatcherRepository(engine=asyncpg_engine)
22+
23+
24+
async def test_list_viewers_info_all(
25+
studies_dispatcher_repository: StudiesDispatcherRepository,
26+
consume_filetypes_in_db: dict,
27+
):
28+
"""Test listing all viewer services."""
29+
# Act
30+
viewers = await studies_dispatcher_repository.list_viewers_info()
31+
32+
# Assert
33+
assert len(viewers) == 1
34+
viewer = viewers[0]
35+
assert isinstance(viewer, ViewerInfo)
36+
assert viewer.key == consume_filetypes_in_db["service_key"]
37+
assert viewer.version == consume_filetypes_in_db["service_version"]
38+
assert viewer.filetype == consume_filetypes_in_db["filetype"]
39+
assert viewer.label == consume_filetypes_in_db["service_display_name"]
40+
assert viewer.input_port_key == consume_filetypes_in_db["service_input_port"]
41+
assert viewer.is_guest_allowed == consume_filetypes_in_db["is_guest_allowed"]
42+
43+
44+
async def test_list_viewers_info_filtered_by_filetype(
45+
studies_dispatcher_repository: StudiesDispatcherRepository,
46+
consume_filetypes_in_db: dict,
47+
):
48+
"""Test listing viewer services filtered by file type."""
49+
# Act
50+
viewers = await studies_dispatcher_repository.list_viewers_info(file_type="CSV")
51+
52+
# Assert
53+
assert len(viewers) == 1
54+
assert viewers[0].filetype == "CSV"
55+
56+
# Test with non-existent filetype
57+
viewers_empty = await studies_dispatcher_repository.list_viewers_info(
58+
file_type="NONEXISTENT"
59+
)
60+
assert len(viewers_empty) == 0
61+
62+
63+
async def test_list_viewers_info_only_default(
64+
studies_dispatcher_repository: StudiesDispatcherRepository,
65+
consume_filetypes_in_db: dict,
66+
):
67+
"""Test listing only default viewer services."""
68+
# Act
69+
viewers = await studies_dispatcher_repository.list_viewers_info(
70+
file_type="CSV", only_default=True
71+
)
72+
73+
# Assert
74+
assert len(viewers) == 1
75+
assert viewers[0].filetype == "CSV"
76+
77+
78+
async def test_get_default_viewer_for_filetype(
79+
studies_dispatcher_repository: StudiesDispatcherRepository,
80+
consume_filetypes_in_db: dict,
81+
):
82+
"""Test getting the default viewer for a specific file type."""
83+
# Act
84+
viewer = await studies_dispatcher_repository.get_default_viewer_for_filetype(
85+
file_type="CSV"
86+
)
87+
88+
# Assert
89+
assert viewer is not None
90+
assert isinstance(viewer, ViewerInfo)
91+
assert viewer.key == consume_filetypes_in_db["service_key"]
92+
assert viewer.version == consume_filetypes_in_db["service_version"]
93+
assert viewer.filetype == "CSV"
94+
assert viewer.label == consume_filetypes_in_db["service_display_name"]
95+
96+
# Test with non-existent filetype
97+
viewer_none = await studies_dispatcher_repository.get_default_viewer_for_filetype(
98+
file_type="NONEXISTENT"
99+
)
100+
assert viewer_none is None
101+
102+
103+
async def test_find_compatible_viewer_found(
104+
studies_dispatcher_repository: StudiesDispatcherRepository,
105+
consume_filetypes_in_db: dict,
106+
):
107+
"""Test finding a compatible viewer service that exists."""
108+
# Act
109+
viewer = await studies_dispatcher_repository.find_compatible_viewer(
110+
file_type="CSV",
111+
service_key=consume_filetypes_in_db["service_key"],
112+
service_version="1.0.0",
113+
)
114+
115+
# Assert
116+
assert viewer is not None
117+
assert isinstance(viewer, ViewerInfo)
118+
assert viewer.key == consume_filetypes_in_db["service_key"]
119+
assert viewer.version == "1.0.0" # Should use the requested version
120+
assert viewer.filetype == "CSV"
121+
assert viewer.label == consume_filetypes_in_db["service_display_name"]
122+
123+
124+
async def test_find_compatible_viewer_not_found(
125+
studies_dispatcher_repository: StudiesDispatcherRepository,
126+
consume_filetypes_in_db: dict,
127+
):
128+
"""Test finding a compatible viewer service that doesn't exist."""
129+
# Act - test with non-existent service key
130+
viewer = await studies_dispatcher_repository.find_compatible_viewer(
131+
file_type="CSV",
132+
service_key="simcore/services/dynamic/nonexistent",
133+
service_version="1.0.0",
134+
)
135+
136+
# Assert
137+
assert viewer is None
138+
139+
# Act - test with incompatible filetype
140+
viewer_wrong_filetype = await studies_dispatcher_repository.find_compatible_viewer(
141+
file_type="NONEXISTENT",
142+
service_key=consume_filetypes_in_db["service_key"],
143+
service_version="1.0.0",
144+
)
145+
146+
# Assert
147+
assert viewer_wrong_filetype is None

0 commit comments

Comments
 (0)