Files
space-booking/backend/tests/test_notifications.py
Claude Agent df4031d99c feat: Space Booking System - MVP complet
Sistem web pentru rezervarea de birouri și săli de ședință
cu flux de aprobare administrativă.

Stack: FastAPI + Vue.js 3 + SQLite + TypeScript

Features implementate:
- Autentificare JWT + Self-registration cu email verification
- CRUD Spații, Utilizatori, Settings (Admin)
- Calendar interactiv (FullCalendar) cu drag-and-drop
- Creare rezervări cu validare (durată, program, overlap, max/zi)
- Rezervări recurente (săptămânal)
- Admin: aprobare/respingere/anulare cereri
- Admin: creare directă rezervări (bypass approval)
- Admin: editare orice rezervare
- User: editare/anulare rezervări proprii
- Notificări in-app (bell icon + dropdown)
- Notificări email (async SMTP cu BackgroundTasks)
- Jurnal acțiuni administrative (audit log)
- Rapoarte avansate (utilizare, top users, approval rate)
- Șabloane rezervări (booking templates)
- Atașamente fișiere (upload/download)
- Conflict warnings (verificare disponibilitate real-time)
- Integrare Google Calendar (OAuth2)
- Suport timezone (UTC storage + user preference)
- 225+ teste backend

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 17:51:29 +00:00

180 lines
5.0 KiB
Python

"""Tests for notifications API endpoints."""
from datetime import datetime
import pytest
from fastapi.testclient import TestClient
from sqlalchemy.orm import Session
from app.models.notification import Notification
from app.models.user import User
@pytest.fixture
def test_notification(db: Session, test_user: User) -> Notification:
"""Create test notification."""
notification = Notification(
user_id=test_user.id,
type="booking_created",
title="Test Notification",
message="This is a test notification",
is_read=False,
created_at=datetime.utcnow(),
)
db.add(notification)
db.commit()
db.refresh(notification)
return notification
@pytest.fixture
def test_read_notification(db: Session, test_user: User) -> Notification:
"""Create read test notification."""
notification = Notification(
user_id=test_user.id,
type="booking_approved",
title="Read Notification",
message="This notification has been read",
is_read=True,
created_at=datetime.utcnow(),
)
db.add(notification)
db.commit()
db.refresh(notification)
return notification
@pytest.fixture
def other_user_notification(db: Session, test_admin: User) -> Notification:
"""Create notification for another user."""
notification = Notification(
user_id=test_admin.id,
type="booking_created",
title="Admin Notification",
message="This belongs to admin",
is_read=False,
created_at=datetime.utcnow(),
)
db.add(notification)
db.commit()
db.refresh(notification)
return notification
def test_get_notifications_for_user(
client: TestClient,
auth_headers: dict[str, str],
test_notification: Notification,
test_read_notification: Notification,
other_user_notification: Notification,
) -> None:
"""Test getting all notifications for current user."""
response = client.get("/api/notifications", headers=auth_headers)
assert response.status_code == 200
data = response.json()
# Should only return notifications for current user
assert len(data) == 2
# Should be ordered by created_at DESC (most recent first)
notification_ids = [n["id"] for n in data]
assert test_notification.id in notification_ids
assert test_read_notification.id in notification_ids
assert other_user_notification.id not in notification_ids
def test_filter_unread_notifications(
client: TestClient,
auth_headers: dict[str, str],
test_notification: Notification,
test_read_notification: Notification,
) -> None:
"""Test filtering notifications by is_read status."""
# Get only unread notifications
response = client.get(
"/api/notifications",
headers=auth_headers,
params={"is_read": False},
)
assert response.status_code == 200
data = response.json()
assert len(data) == 1
assert data[0]["id"] == test_notification.id
assert data[0]["is_read"] is False
# Get only read notifications
response = client.get(
"/api/notifications",
headers=auth_headers,
params={"is_read": True},
)
assert response.status_code == 200
data = response.json()
assert len(data) == 1
assert data[0]["id"] == test_read_notification.id
assert data[0]["is_read"] is True
def test_mark_notification_as_read(
client: TestClient,
auth_headers: dict[str, str],
test_notification: Notification,
) -> None:
"""Test marking a notification as read."""
response = client.put(
f"/api/notifications/{test_notification.id}/read",
headers=auth_headers,
)
assert response.status_code == 200
data = response.json()
assert data["id"] == test_notification.id
assert data["is_read"] is True
assert data["title"] == "Test Notification"
assert data["message"] == "This is a test notification"
def test_cannot_mark_others_notification(
client: TestClient,
auth_headers: dict[str, str],
other_user_notification: Notification,
) -> None:
"""Test that users cannot mark other users' notifications as read."""
response = client.put(
f"/api/notifications/{other_user_notification.id}/read",
headers=auth_headers,
)
assert response.status_code == 403
data = response.json()
assert "own notifications" in data["detail"].lower()
def test_mark_nonexistent_notification(
client: TestClient,
auth_headers: dict[str, str],
) -> None:
"""Test marking a non-existent notification as read."""
response = client.put(
"/api/notifications/99999/read",
headers=auth_headers,
)
assert response.status_code == 404
data = response.json()
assert "not found" in data["detail"].lower()
def test_get_notifications_without_auth(client: TestClient) -> None:
"""Test that authentication is required for notifications endpoints."""
response = client.get("/api/notifications")
assert response.status_code == 403
response = client.put("/api/notifications/1/read")
assert response.status_code == 403