mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-06-06 20:15:17 +02:00
test: add notifications integration behavior guard
This commit is contained in:
parent
339ec31cad
commit
3f770203ca
8 changed files with 938 additions and 0 deletions
|
|
@ -0,0 +1,164 @@
|
|||
"""Behavior guard for the shared find/upsert/update logic (BaseNotificationHandler).
|
||||
|
||||
Uses the connector-indexing handler instance to drive the base methods against
|
||||
real Postgres, pinning upsert dedup, search-space scoping, and status stamping.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.db import SearchSpace, User
|
||||
from app.notifications.persistence import Notification
|
||||
from app.notifications.service import NotificationService
|
||||
|
||||
pytestmark = pytest.mark.integration
|
||||
|
||||
handler = NotificationService.connector_indexing
|
||||
|
||||
|
||||
async def test_find_or_create_creates_with_progress_metadata(
|
||||
db_session: AsyncSession,
|
||||
db_user: User,
|
||||
db_search_space: SearchSpace,
|
||||
):
|
||||
"""Creating a notification seeds operation id, in-progress status, and start time."""
|
||||
notification = await handler.find_or_create_notification(
|
||||
session=db_session,
|
||||
user_id=db_user.id,
|
||||
operation_id="op-create",
|
||||
title="Title",
|
||||
message="Message",
|
||||
search_space_id=db_search_space.id,
|
||||
)
|
||||
|
||||
assert notification.notification_metadata["operation_id"] == "op-create"
|
||||
assert notification.notification_metadata["status"] == "in_progress"
|
||||
assert "started_at" in notification.notification_metadata
|
||||
|
||||
|
||||
async def test_find_or_create_upserts_same_operation(
|
||||
db_session: AsyncSession,
|
||||
db_user: User,
|
||||
db_search_space: SearchSpace,
|
||||
):
|
||||
"""Reusing an operation id updates the same row instead of creating a duplicate."""
|
||||
first = await handler.find_or_create_notification(
|
||||
session=db_session,
|
||||
user_id=db_user.id,
|
||||
operation_id="op-upsert",
|
||||
title="First",
|
||||
message="First message",
|
||||
search_space_id=db_search_space.id,
|
||||
)
|
||||
|
||||
second = await handler.find_or_create_notification(
|
||||
session=db_session,
|
||||
user_id=db_user.id,
|
||||
operation_id="op-upsert",
|
||||
title="Second",
|
||||
message="Second message",
|
||||
search_space_id=db_search_space.id,
|
||||
)
|
||||
|
||||
assert second.id == first.id
|
||||
assert second.title == "Second"
|
||||
assert second.message == "Second message"
|
||||
|
||||
count = await db_session.scalar(
|
||||
select(func.count(Notification.id)).where(
|
||||
Notification.user_id == db_user.id,
|
||||
Notification.notification_metadata["operation_id"].astext == "op-upsert",
|
||||
)
|
||||
)
|
||||
assert count == 1
|
||||
|
||||
|
||||
async def test_find_by_operation_is_scoped_to_search_space(
|
||||
db_session: AsyncSession,
|
||||
db_user: User,
|
||||
db_search_space: SearchSpace,
|
||||
):
|
||||
"""Operation-id lookup is scoped per search space, so other spaces don't match."""
|
||||
await handler.find_or_create_notification(
|
||||
session=db_session,
|
||||
user_id=db_user.id,
|
||||
operation_id="op-scoped",
|
||||
title="Title",
|
||||
message="Message",
|
||||
search_space_id=db_search_space.id,
|
||||
)
|
||||
|
||||
other_space = SearchSpace(name="Other Space", user_id=db_user.id)
|
||||
db_session.add(other_space)
|
||||
await db_session.flush()
|
||||
|
||||
found_other = await handler.find_notification_by_operation(
|
||||
session=db_session,
|
||||
user_id=db_user.id,
|
||||
operation_id="op-scoped",
|
||||
search_space_id=other_space.id,
|
||||
)
|
||||
assert found_other is None
|
||||
|
||||
found_same = await handler.find_notification_by_operation(
|
||||
session=db_session,
|
||||
user_id=db_user.id,
|
||||
operation_id="op-scoped",
|
||||
search_space_id=db_search_space.id,
|
||||
)
|
||||
assert found_same is not None
|
||||
|
||||
|
||||
async def test_update_notification_completed_stamps_completed_at(
|
||||
db_session: AsyncSession,
|
||||
db_user: User,
|
||||
db_search_space: SearchSpace,
|
||||
):
|
||||
"""Completing a notification stamps completed_at and merges metadata updates."""
|
||||
notification = await handler.find_or_create_notification(
|
||||
session=db_session,
|
||||
user_id=db_user.id,
|
||||
operation_id="op-complete",
|
||||
title="Title",
|
||||
message="Message",
|
||||
search_space_id=db_search_space.id,
|
||||
)
|
||||
|
||||
updated = await handler.update_notification(
|
||||
session=db_session,
|
||||
notification=notification,
|
||||
status="completed",
|
||||
metadata_updates={"indexed_count": 7},
|
||||
)
|
||||
|
||||
assert updated.notification_metadata["status"] == "completed"
|
||||
assert "completed_at" in updated.notification_metadata
|
||||
assert updated.notification_metadata["indexed_count"] == 7
|
||||
|
||||
|
||||
async def test_update_notification_failed_stamps_completed_at(
|
||||
db_session: AsyncSession,
|
||||
db_user: User,
|
||||
db_search_space: SearchSpace,
|
||||
):
|
||||
"""Failing a notification also stamps completed_at for the terminal state."""
|
||||
notification = await handler.find_or_create_notification(
|
||||
session=db_session,
|
||||
user_id=db_user.id,
|
||||
operation_id="op-fail",
|
||||
title="Title",
|
||||
message="Message",
|
||||
search_space_id=db_search_space.id,
|
||||
)
|
||||
|
||||
updated = await handler.update_notification(
|
||||
session=db_session,
|
||||
notification=notification,
|
||||
status="failed",
|
||||
)
|
||||
|
||||
assert updated.notification_metadata["status"] == "failed"
|
||||
assert "completed_at" in updated.notification_metadata
|
||||
Loading…
Add table
Add a link
Reference in a new issue