Skip to content

Commit 5a0cd22

Browse files
authored
✅ Fixes tests/unit/with_dbs/02/test_projects_metadata_handlers.py::test_new_project_with_parent_project_node (#8602)
1 parent 92839f2 commit 5a0cd22

File tree

4 files changed

+81
-27
lines changed

4 files changed

+81
-27
lines changed

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
from common_library.dict_tools import remap_keys
1313
from models_library.projects_nodes_io import NodeID
1414
from models_library.services_resources import ServiceResourcesDictHelpers
15+
from simcore_postgres_database import webserver_models
1516
from simcore_postgres_database.utils_projects_nodes import ProjectNodeCreate
17+
from simcore_postgres_database.utils_repos import transaction_context
18+
from simcore_service_webserver.db.plugin import get_asyncpg_engine
1619
from simcore_service_webserver.projects._groups_repository import (
1720
update_or_insert_project_group,
1821
)
@@ -129,11 +132,12 @@ async def create_project(
129132

130133

131134
async def delete_all_projects(app: web.Application):
132-
from simcore_postgres_database.webserver_models import projects
133135

134-
db = app[PROJECT_DBAPI_APPKEY]
135-
async with db.engine.acquire() as conn:
136-
query = projects.delete()
136+
engine = get_asyncpg_engine(app)
137+
assert engine # nosec
138+
139+
async with transaction_context(engine) as conn:
140+
query = webserver_models.projects.delete()
137141
await conn.execute(query)
138142

139143

services/web/server/tests/conftest.py

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import pytest
1717
import simcore_service_webserver
18+
import tenacity
1819
from aiohttp.test_utils import TestClient
1920
from common_library.json_serialization import json_dumps
2021
from faker import Faker
@@ -191,9 +192,9 @@ async def logged_user(
191192
},
192193
check_if_succeeds=user_role != UserRole.ANONYMOUS,
193194
) as user:
194-
print("-----> logged in user", user["name"], user_role)
195+
logging.info("-----> logged in user %s %s", user["name"], user_role)
195196
yield user
196-
print("<----- logged out user", user["name"], user_role)
197+
logging.info("<----- logged out user %s %s", user["name"], user_role)
197198

198199

199200
@pytest.fixture
@@ -206,14 +207,16 @@ def monkeypatch_setenv_from_app_config(
206207
def _patch(app_config: dict) -> EnvVarsDict:
207208
assert isinstance(app_config, dict)
208209

209-
print(" - app_config=\n", json_dumps(app_config, indent=1, sort_keys=True))
210+
logging.info(
211+
" - app_config=\n%s", json_dumps(app_config, indent=1, sort_keys=True)
212+
)
210213
envs: EnvVarsDict = {
211214
env_key: f"{env_value}"
212215
for env_key, env_value in convert_to_environ_vars(app_config).items()
213216
}
214217

215-
print(
216-
" - convert_to_environ_vars(app_cfg)=\n",
218+
logging.info(
219+
" - convert_to_environ_vars(app_cfg)=\n%s",
217220
json_dumps(envs, indent=1, sort_keys=True),
218221
)
219222
return setenvs_from_dict(monkeypatch, envs)
@@ -351,7 +354,7 @@ async def _creator( # noqa: PLR0915
351354
resp = await client.post(
352355
f"{url}", json=project_data, headers=headers
353356
) # NOTE: MD <-- here is project created!
354-
print(f"<-- created project response: {resp=}")
357+
logging.info("<-- created project response: %r", resp)
355358
data, error = await assert_status(resp, expected_accepted_response)
356359
if error:
357360
assert not data
@@ -371,31 +374,32 @@ async def _creator( # noqa: PLR0915
371374
retry=retry_if_exception_type(AssertionError),
372375
):
373376
with attempt:
374-
print(
375-
f"--> waiting for creation {attempt.retry_state.attempt_number}..."
377+
logging.info(
378+
"--> waiting for creation %s...", attempt.retry_state.attempt_number
376379
)
377380
result = await client.get(urlparse(status_url).path)
378381
data, error = await assert_status(result, status.HTTP_200_OK)
379382
assert data
380383
assert not error
381384
task_status = TaskStatus.model_validate(data)
382385
assert task_status
383-
print(f"<-- status: {task_status.model_dump_json(indent=2)}")
386+
logging.info("<-- status: %s", task_status.model_dump_json(indent=2))
384387
assert task_status.done, "task incomplete"
385-
print(
386-
f"-- project creation completed: {json.dumps(attempt.retry_state.retry_object.statistics, indent=2)}"
388+
logging.info(
389+
"-- project creation completed: %s",
390+
json.dumps(attempt.retry_state.retry_object.statistics, indent=2),
387391
)
388392

389393
# get result GET /{task_id}/result
390-
print("--> getting project creation result...")
394+
logging.info("--> getting project creation result...")
391395
result = await client.get(urlparse(result_url).path)
392396
data, error = await assert_status(result, expected_creation_response)
393397
if error:
394398
assert not data
395399
return {}
396400
assert data
397401
assert not error
398-
print(f"<-- result: {data}")
402+
logging.info("<-- result: %r", data)
399403
new_project = data
400404

401405
# Setup access rights to the project
@@ -415,11 +419,11 @@ async def _creator( # noqa: PLR0915
415419
delete=permissions["delete"],
416420
)
417421
# Get project with already added access rights
418-
print("--> getting project groups after access rights change...")
422+
logging.info("--> getting project groups after access rights change...")
419423
url = client.app.router["list_project_groups"].url_for(project_id=data["uuid"])
420424
resp = await client.get(url.path)
421425
data, error = await assert_status(resp, status.HTTP_200_OK)
422-
print(f"<-- result: {data}")
426+
logging.info("<-- result: %r", data)
423427
new_project_access_rights = {}
424428
for item in data:
425429
new_project_access_rights.update(
@@ -493,8 +497,35 @@ async def _creator( # noqa: PLR0915
493497

494498
# cleanup projects
495499
for client, project_uuid in zip(used_clients, created_project_uuids, strict=True):
500+
# NOTE: delete does not wait for completion
496501
url = client.app.router["delete_project"].url_for(project_id=project_uuid)
497-
await client.delete(url.path)
502+
resp = await client.delete(url.path)
503+
504+
if resp.ok:
505+
# NOTE: If deleted OK, then let's wait until project is really gone
506+
url = client.app.router["get_project"].url_for(project_id=project_uuid)
507+
async for attempt in AsyncRetrying(
508+
wait=wait_fixed(0.1),
509+
stop=stop_after_delay(10),
510+
reraise=True,
511+
retry=retry_if_exception_type(tenacity.TryAgain),
512+
):
513+
with attempt:
514+
logging.info(
515+
"--> waiting for deletion %s...",
516+
attempt.retry_state.attempt_number,
517+
)
518+
resp = await client.get(url.path)
519+
if resp.status == status.HTTP_200_OK:
520+
raise tenacity.TryAgain
521+
522+
await assert_status(resp, status.HTTP_404_NOT_FOUND)
523+
logging.info(
524+
"-- project deletion completed: %s",
525+
json.dumps(
526+
attempt.retry_state.retry_object.statistics, indent=2
527+
),
528+
)
498529

499530

500531
@pytest.fixture

services/web/server/tests/unit/with_dbs/02/test_projects_states_handlers.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ async def test_share_project_user_roles(
266266
rabbit_service: RabbitSettings,
267267
mock_dynamic_scheduler: None,
268268
client: TestClient,
269+
other_client: TestClient,
269270
logged_user: dict,
270271
primary_group: dict[str, str],
271272
standard_groups: list[dict[str, str]],
@@ -274,9 +275,10 @@ async def test_share_project_user_roles(
274275
expected: ExpectedResponse,
275276
storage_subsystem_mock,
276277
mocked_dynamic_services_interface: dict[str, mock.Mock],
277-
project_db_cleaner,
278278
request_create_project: Callable[..., Awaitable[ProjectDict]],
279279
exit_stack: contextlib.AsyncExitStack,
280+
project_db_cleaner,
281+
aiohttp_client: Callable,
280282
):
281283
# Use-case: test how different user roles can access shared projects
282284
# Test with full access rights for all roles
@@ -300,23 +302,26 @@ async def test_share_project_user_roles(
300302
# user 1 can always get to his project
301303
await assert_get_same_project(client, new_project, expected.ok)
302304

303-
# get another user logged in now
305+
#
306+
# get another user logged in now. We create a new client to avoid session conflicts with request_create_project
307+
# cleanup
308+
#
304309
await log_client_in(
305-
client,
310+
other_client,
306311
{"role": user_role.name},
307312
enable_check=user_role != UserRole.ANONYMOUS,
308313
exit_stack=exit_stack,
309314
)
310315
if new_project:
311316
# user 2 can get the project if they have proper role permissions
312317
await assert_get_same_project(
313-
client,
318+
other_client,
314319
new_project,
315320
expected.ok,
316321
)
317322

318323
# user 2 can list projects if they have proper role permissions
319-
list_projects = await _list_projects(client, expected.ok)
324+
list_projects = await _list_projects(other_client, expected.ok)
320325
expected_project_count = 1 if user_role != UserRole.ANONYMOUS else 0
321326
assert len(list_projects) == expected_project_count
322327

@@ -325,13 +330,13 @@ async def test_share_project_user_roles(
325330
project_update["name"] = "my super name"
326331
project_update.pop("accessRights")
327332
await _replace_project(
328-
client,
333+
other_client,
329334
project_update,
330335
expected.no_content,
331336
)
332337

333338
# user 2 can delete projects if they have proper role permissions
334-
resp = await _delete_project(client, new_project)
339+
resp = await _delete_project(other_client, new_project)
335340
await assert_status(
336341
resp,
337342
expected_status_code=expected.no_content,

services/web/server/tests/unit/with_dbs/conftest.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,20 @@ async def client(
263263
return await aiohttp_client(web_server)
264264

265265

266+
@pytest.fixture
267+
async def other_client(
268+
client: TestClient, aiohttp_client: Callable, web_server: TestServer
269+
) -> TestClient:
270+
"""Creates another client connected to the same app as 'client' fixture
271+
This is convenient to login with multiple users in the same app instance
272+
without interfering with each other's session cookies
273+
"""
274+
assert client.app
275+
client2 = await aiohttp_client(web_server)
276+
assert client2 != client
277+
return client2
278+
279+
266280
@pytest.fixture
267281
async def webserver_rpc_client(
268282
rabbitmq_rpc_client: Callable[[str], Awaitable[RabbitMQRPCClient]],

0 commit comments

Comments
 (0)