feat: add calendar subscription token functionality and ICS generation
- Introduced a new database model for calendar subscription tokens, allowing users to generate unique tokens for accessing their personal calendar. - Implemented API endpoint to return ICS files containing only the subscribing user's duties, enhancing user experience with personalized calendar access. - Added utility functions for generating ICS files from user duties, ensuring proper formatting and timezone handling. - Updated command handlers to support the new calendar link feature, providing users with easy access to their personal calendar subscriptions. - Included unit tests for the new functionality, ensuring reliability and correctness of token generation and ICS file creation.
This commit is contained in:
67
tests/test_calendar_token_repository.py
Normal file
67
tests/test_calendar_token_repository.py
Normal file
@@ -0,0 +1,67 @@
|
||||
"""Unit tests for calendar subscription token repository functions."""
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from duty_teller.db.models import Base
|
||||
from duty_teller.db.repository import (
|
||||
create_calendar_token,
|
||||
get_user_by_calendar_token,
|
||||
get_or_create_user_by_full_name,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def session():
|
||||
"""In-memory SQLite session with all tables (including calendar_subscription_tokens)."""
|
||||
engine = create_engine(
|
||||
"sqlite:///:memory:", connect_args={"check_same_thread": False}
|
||||
)
|
||||
Base.metadata.create_all(engine)
|
||||
Session = sessionmaker(bind=engine, autocommit=False, autoflush=False)
|
||||
s = Session()
|
||||
try:
|
||||
yield s
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def user_a(session):
|
||||
"""Create one user."""
|
||||
u = get_or_create_user_by_full_name(session, "User A")
|
||||
return u
|
||||
|
||||
|
||||
def test_create_calendar_token_returns_token_string(session, user_a):
|
||||
"""create_calendar_token returns a non-empty URL-safe string."""
|
||||
token = create_calendar_token(session, user_a.id)
|
||||
assert isinstance(token, str)
|
||||
assert len(token) > 0
|
||||
assert " " not in token
|
||||
|
||||
|
||||
def test_get_user_by_calendar_token_valid_returns_user(session, user_a):
|
||||
"""Valid token returns the correct user."""
|
||||
token = create_calendar_token(session, user_a.id)
|
||||
user = get_user_by_calendar_token(session, token)
|
||||
assert user is not None
|
||||
assert user.id == user_a.id
|
||||
assert user.full_name == "User A"
|
||||
|
||||
|
||||
def test_get_user_by_calendar_token_invalid_returns_none(session, user_a):
|
||||
"""Invalid or unknown token returns None."""
|
||||
create_calendar_token(session, user_a.id)
|
||||
assert get_user_by_calendar_token(session, "wrong-token") is None
|
||||
assert get_user_by_calendar_token(session, "") is None
|
||||
|
||||
|
||||
def test_create_calendar_token_one_active_per_user(session, user_a):
|
||||
"""Creating a new token removes the previous one for the same user."""
|
||||
token1 = create_calendar_token(session, user_a.id)
|
||||
token2 = create_calendar_token(session, user_a.id)
|
||||
assert token1 != token2
|
||||
assert get_user_by_calendar_token(session, token1) is None
|
||||
assert get_user_by_calendar_token(session, token2).id == user_a.id
|
||||
Reference in New Issue
Block a user