Skip to content

Commit ca9106d

Browse files
committed
tests
1 parent 3c2c665 commit ca9106d

File tree

1 file changed

+64
-5
lines changed

1 file changed

+64
-5
lines changed

services/web/server/tests/unit/with_dbs/03/invitations/test_users_rest_registration.py

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from collections.abc import AsyncGenerator
1010
from http import HTTPStatus
1111
from typing import Any
12+
from unittest.mock import AsyncMock
1213

1314
import pytest
1415
import simcore_service_webserver.login._auth_service
@@ -23,6 +24,7 @@
2324
)
2425
from models_library.products import ProductName
2526
from models_library.rest_pagination import Page
27+
from pytest_mock import MockerFixture
2628
from pytest_simcore.aioresponses_mocker import AioResponsesMock
2729
from pytest_simcore.helpers.assert_checks import assert_status
2830
from pytest_simcore.helpers.faker_factories import (
@@ -55,6 +57,35 @@ def app_environment(
5557
)
5658

5759

60+
@pytest.fixture
61+
def mock_email_session(mocker: MockerFixture) -> AsyncMock:
62+
"""Mock the email session and capture sent messages"""
63+
# Create a mock email session
64+
mock_session = AsyncMock()
65+
66+
# List to store sent messages
67+
sent_messages = []
68+
69+
async def mock_send_message(msg):
70+
"""Mock send_message method to capture messages"""
71+
sent_messages.append(msg)
72+
73+
mock_session.send_message = mock_send_message
74+
mock_session.sent_messages = sent_messages
75+
76+
# Mock the context manager behavior
77+
mock_session.__aenter__ = AsyncMock(return_value=mock_session)
78+
mock_session.__aexit__ = AsyncMock(return_value=None)
79+
80+
# Use mocker to patch the create_email_session function
81+
mocker.patch(
82+
"simcore_service_webserver.users._accounts_service.create_email_session",
83+
return_value=mock_session,
84+
)
85+
86+
return mock_session
87+
88+
5889
@pytest.mark.parametrize(
5990
"user_role,expected",
6091
[
@@ -388,6 +419,7 @@ async def test_reject_user_account(
388419
faker: Faker,
389420
product_name: ProductName,
390421
pre_registration_details_db_cleanup: None,
422+
mock_email_session: AsyncMock,
391423
):
392424
assert client.app
393425

@@ -424,7 +456,20 @@ async def test_reject_user_account(
424456
)
425457
await assert_status(resp, status.HTTP_204_NO_CONTENT)
426458

427-
# 4. Verify the user is no longer in PENDING status
459+
# 4. Verify rejection email was sent
460+
# Wait a bit for fire-and-forget task to complete
461+
import asyncio
462+
463+
await asyncio.sleep(0.1)
464+
465+
assert len(mock_email_session.sent_messages) == 1
466+
rejection_msg = mock_email_session.sent_messages[0]
467+
468+
# Verify email recipients and content
469+
assert rejection_msg["To"] == pre_registered_email
470+
assert "rejected" in rejection_msg["Subject"].lower()
471+
472+
# 5. Verify the user is no longer in PENDING status
428473
url = client.app.router["list_users_accounts"].url_for()
429474
resp = await client.get(
430475
f"{url}?review_status=PENDING", headers={X_PRODUCT_NAME_HEADER: product_name}
@@ -433,7 +478,7 @@ async def test_reject_user_account(
433478
pending_emails = [user["email"] for user in pending_data]
434479
assert pre_registered_email not in pending_emails
435480

436-
# 5. Verify the user is now in REJECTED status
481+
# 6. Verify the user is now in REJECTED status
437482
# First get user details to check status
438483
resp = await client.get(
439484
"/v0/admin/user-accounts:search",
@@ -449,7 +494,7 @@ async def test_reject_user_account(
449494
assert user_data["accountRequestReviewedBy"] == logged_user["id"]
450495
assert user_data["accountRequestReviewedAt"] is not None
451496

452-
# 6. Verify that a rejected user cannot be approved
497+
# 7. Verify that a rejected user cannot be approved
453498
url = client.app.router["approve_user_account"].url_for()
454499
resp = await client.post(
455500
f"{url}",
@@ -474,6 +519,7 @@ async def test_approve_user_account_with_full_invitation_details(
474519
product_name: ProductName,
475520
pre_registration_details_db_cleanup: None,
476521
mock_invitations_service_http_api: AioResponsesMock,
522+
mock_email_session: AsyncMock,
477523
):
478524
"""Test approving user account with complete invitation details (trial days + credits)"""
479525
assert client.app
@@ -510,7 +556,20 @@ async def test_approve_user_account_with_full_invitation_details(
510556
)
511557
await assert_status(resp, status.HTTP_204_NO_CONTENT)
512558

513-
# 3. Verify the user account status and invitation data in extras
559+
# 3. Verify approval email was sent
560+
# Wait a bit for fire-and-forget task to complete
561+
import asyncio
562+
563+
await asyncio.sleep(0.1)
564+
565+
assert len(mock_email_session.sent_messages) == 1
566+
approval_msg = mock_email_session.sent_messages[0]
567+
568+
# Verify email recipients and content
569+
assert approval_msg["To"] == test_email
570+
assert "approved" in approval_msg["Subject"].lower()
571+
572+
# 4. Verify the user account status and invitation data in extras
514573
resp = await client.get(
515574
"/v0/admin/user-accounts:search",
516575
params={"email": test_email},
@@ -524,7 +583,7 @@ async def test_approve_user_account_with_full_invitation_details(
524583
assert user_data["accountRequestReviewedBy"] == logged_user["id"]
525584
assert user_data["accountRequestReviewedAt"] is not None
526585

527-
# 4. Verify invitation data is stored in extras
586+
# 5. Verify invitation data is stored in extras
528587
assert "invitation" in user_data["extras"]
529588
invitation_data = user_data["extras"]["invitation"]
530589
assert invitation_data["guest"] == test_email

0 commit comments

Comments
 (0)