Files
eryao/backend/tests/integration/test_notification_target_mode.py
T
qzl c79c773d67 feat(notification): add target_mode enum constraint and merge register-notifications script
- Add NotificationTargetMode enum (new_users/exist_users/all_users/user_ids)
- Create Alembic migrations: drop duplicate indexes, add target_mode column
- Merge register-notifications.sh into dev-migrate.sh sync-notifications subcommand
- Shorten notification config path: static/notification/notifications -> static/notifications
- Update registration flow to dispatch notifications by target_mode
- Add is_first_registration to RegisterBonusResult for first-time user detection
- Remove dead code: link_published_notifications_to_user
- Update welcome_points.yaml to target new_users only
- Add 44 unit tests + 1 integration test, all passing
2026-04-16 17:50:57 +08:00

97 lines
2.8 KiB
Python

from __future__ import annotations
import time
from typing import TypedDict
from uuid import UUID
import httpx
import pytest
from sqlalchemy import select
from core.db.session import AsyncSessionLocal
from models.notification import Notification
from models.user_notification import UserNotification
class IdentityData(TypedDict):
email: str
code: str
async def _create_email_session(
client: httpx.AsyncClient,
*,
email: str,
code: str,
) -> dict[str, object]:
resp = await client.post(
"/api/v1/auth/email-session",
json={"email": email, "token": code},
)
resp.raise_for_status()
return resp.json()
async def _delete_user(client: httpx.AsyncClient, *, token: str) -> None:
resp = await client.delete(
"/api/v1/users/me",
headers={"Authorization": f"Bearer {token}"},
)
assert resp.status_code == 204
@pytest.mark.asyncio
async def test_notification_target_mode_first_reg_and_reregister(
api_client: httpx.AsyncClient,
test_identity: IdentityData,
db_cleanup: list[str],
) -> None:
email = str(test_identity["email"]).strip().lower()
db_cleanup.append(email)
first = await _create_email_session(
api_client, email=email, code=str(test_identity["code"])
)
user1 = first.get("user")
assert isinstance(user1, dict)
user1_id = UUID(str(user1["id"]))
token1 = str(first["access_token"])
async with AsyncSessionLocal() as session:
result = await session.execute(
select(Notification.target_mode)
.join(UserNotification, UserNotification.notification_id == Notification.id)
.where(UserNotification.user_id == user1_id)
.order_by(Notification.target_mode)
)
first_target_modes = [str(row[0]) for row in result.all()]
assert "new_users" in first_target_modes
assert "exist_users" not in first_target_modes
await _delete_user(api_client, token=token1)
time.sleep(0.5)
second = await _create_email_session(
api_client, email=email, code=str(test_identity["code"])
)
user2 = second.get("user")
assert isinstance(user2, dict)
user2_id = UUID(str(user2["id"]))
token2 = str(second["access_token"])
async with AsyncSessionLocal() as session:
result = await session.execute(
select(Notification.target_mode)
.join(UserNotification, UserNotification.notification_id == Notification.id)
.where(UserNotification.user_id == user2_id)
.order_by(Notification.target_mode)
)
second_target_modes = [str(row[0]) for row in result.all()]
assert "new_users" not in second_target_modes
assert "all_users" not in second_target_modes
assert "exist_users" not in second_target_modes
await _delete_user(api_client, token=token2)