Skip to content

Commit d88921c

Browse files
🐛 Fix clone title and description (#7940)
1 parent 11846e3 commit d88921c

File tree

3 files changed

+58
-8
lines changed

3 files changed

+58
-8
lines changed

services/api-server/src/simcore_service_api_server/api/routes/studies.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,9 @@ async def clone_study(
111111
description=description,
112112
)
113113
await webserver_api.patch_project(
114-
project_id=study_id, patch_params=patch_params
114+
project_id=project.uuid, patch_params=patch_params
115115
)
116+
project = await webserver_api.get_project(project_id=project.uuid)
116117
return _create_study_from_project(project)
117118

118119

services/api-server/tests/unit/api_studies/test_api_routes_studies.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# pylint: disable=redefined-outer-name
22
# pylint: disable=unused-argument
33
# pylint: disable=unused-variable
4+
# pylint: disable=too-many-arguments
5+
# pylint: disable=too-many-statements
46

57

68
import json
@@ -13,6 +15,8 @@
1315
import pytest
1416
from faker import Faker
1517
from fastapi import status
18+
from models_library.api_schemas_webserver.projects import ProjectGet
19+
from models_library.generics import Envelope
1620
from pydantic import TypeAdapter
1721
from pytest_mock import MockType
1822
from pytest_simcore.helpers.httpx_calls_capture_models import HttpApiCallCaptureModel
@@ -224,12 +228,8 @@ async def test_clone_study_with_title(
224228
study_id: StudyID,
225229
mocked_webserver_rest_api_base: MockRouter,
226230
patch_webserver_long_running_project_tasks: Callable[[MockRouter], MockRouter],
227-
mock_webserver_patch_project: Callable[
228-
[
229-
MockRouter,
230-
],
231-
MockRouter,
232-
],
231+
mock_webserver_patch_project: Callable[[MockRouter], MockRouter],
232+
mock_webserver_get_project: Callable[[MockRouter], MockRouter],
233233
hidden: bool | None,
234234
title: str | None,
235235
description: str | None,
@@ -238,11 +238,14 @@ async def test_clone_study_with_title(
238238
# Mocks /projects
239239
patch_webserver_long_running_project_tasks(mocked_webserver_rest_api_base)
240240
mock_webserver_patch_project(mocked_webserver_rest_api_base)
241+
mock_webserver_get_project(mocked_webserver_rest_api_base)
241242

242243
create_callback = mocked_webserver_rest_api_base["create_projects"].side_effect
243244
assert create_callback is not None
244245
patch_callback = mocked_webserver_rest_api_base["project_patch"].side_effect
245246
assert patch_callback is not None
247+
get_callback = mocked_webserver_rest_api_base["project_get"].side_effect
248+
assert get_callback is not None
246249

247250
def clone_project_side_effect(request: httpx.Request):
248251
if hidden is not None:
@@ -260,12 +263,28 @@ def patch_project_side_effect(request: httpx.Request, *args, **kwargs):
260263
assert _description is not None and _description in description
261264
return patch_callback(request, *args, **kwargs)
262265

266+
def get_project_side_effect(request: httpx.Request, *args, **kwargs):
267+
# this is needed to return the patched project
268+
_project_id = kwargs.get("project_id")
269+
assert _project_id is not None
270+
result = Envelope[ProjectGet].model_validate(
271+
{"data": ProjectGet.model_json_schema()["examples"][0]}
272+
)
273+
assert result.data is not None
274+
if title is not None:
275+
result.data.name = title
276+
if description is not None:
277+
result.data.description = description
278+
result.data.uuid = UUID(_project_id)
279+
return httpx.Response(status.HTTP_200_OK, content=result.model_dump_json())
280+
263281
mocked_webserver_rest_api_base["create_projects"].side_effect = (
264282
clone_project_side_effect
265283
)
266284
mocked_webserver_rest_api_base["project_patch"].side_effect = (
267285
patch_project_side_effect
268286
)
287+
mocked_webserver_rest_api_base["project_get"].side_effect = get_project_side_effect
269288

270289
query = dict()
271290
if hidden is not None:
@@ -286,8 +305,14 @@ def patch_project_side_effect(request: httpx.Request, *args, **kwargs):
286305
assert mocked_webserver_rest_api_base["create_projects"].called
287306
if title or description:
288307
assert mocked_webserver_rest_api_base["project_patch"].called
308+
assert mocked_webserver_rest_api_base["project_get"].called
289309

290310
assert resp.status_code == expected_status_code
311+
study = Study.model_validate(resp.json())
312+
if title is not None:
313+
assert study.title == title
314+
if description is not None:
315+
assert study.description == description
291316

292317

293318
async def test_clone_study_not_found(

services/api-server/tests/unit/conftest.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ def _mock(webserver_mock_router: MockRouter) -> MockRouter:
717717

718718
@pytest.fixture
719719
def mock_webserver_patch_project(
720-
app: FastAPI, faker: Faker, services_mocks_enabled: bool
720+
app: FastAPI, services_mocks_enabled: bool
721721
) -> Callable[[MockRouter], MockRouter]:
722722
settings: ApplicationSettings = app.state.settings
723723
assert settings.API_SERVER_WEBSERVER is not None
@@ -736,6 +736,30 @@ def _patch_project(request: httpx.Request, *args, **kwargs):
736736
return _mock
737737

738738

739+
@pytest.fixture
740+
def mock_webserver_get_project(
741+
app: FastAPI, services_mocks_enabled: bool
742+
) -> Callable[[MockRouter], MockRouter]:
743+
settings: ApplicationSettings = app.state.settings
744+
assert settings.API_SERVER_WEBSERVER is not None
745+
746+
def _mock(webserver_mock_router: MockRouter) -> MockRouter:
747+
def _get_project(request: httpx.Request, *args, **kwargs):
748+
result = Envelope[ProjectGet].model_validate(
749+
{"data": ProjectGet.model_json_schema()["examples"][0]}
750+
)
751+
return httpx.Response(status.HTTP_200_OK, json=result.model_dump())
752+
753+
if services_mocks_enabled:
754+
webserver_mock_router.get(
755+
path__regex=r"/projects/(?P<project_id>[\w-]+)$",
756+
name="project_get",
757+
).mock(side_effect=_get_project)
758+
return webserver_mock_router
759+
760+
return _mock
761+
762+
739763
@pytest.fixture
740764
def openapi_dev_specs(project_slug_dir: Path) -> dict[str, Any]:
741765
openapi_file = (project_slug_dir / "openapi-dev.json").resolve()

0 commit comments

Comments
 (0)