mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-01-06 03:30:25 -06:00
676 lines
20 KiB
Python
676 lines
20 KiB
Python
"""
|
|
Test suite for CalendarEvent model.
|
|
Tests model creation, relationships, properties, and business logic.
|
|
"""
|
|
|
|
import pytest
|
|
from datetime import datetime, timedelta
|
|
from app.models import CalendarEvent, User, Project, Task, Client, TimeEntry
|
|
from app import db
|
|
|
|
|
|
# ============================================================================
|
|
# CalendarEvent Model Tests
|
|
# ============================================================================
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
@pytest.mark.smoke
|
|
def test_calendar_event_creation(app, user, project):
|
|
"""Test basic calendar event creation."""
|
|
with app.app_context():
|
|
start_time = datetime.now()
|
|
end_time = start_time + timedelta(hours=2)
|
|
|
|
event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Team Meeting",
|
|
start_time=start_time,
|
|
end_time=end_time,
|
|
description="Weekly team sync",
|
|
location="Conference Room A",
|
|
event_type="meeting"
|
|
)
|
|
db.session.add(event)
|
|
db.session.commit()
|
|
|
|
assert event.id is not None
|
|
assert event.title == "Team Meeting"
|
|
assert event.user_id == user.id
|
|
assert event.start_time == start_time
|
|
assert event.end_time == end_time
|
|
assert event.description == "Weekly team sync"
|
|
assert event.location == "Conference Room A"
|
|
assert event.event_type == "meeting"
|
|
assert event.all_day is False
|
|
assert event.is_private is False
|
|
assert event.is_recurring is False
|
|
assert event.created_at is not None
|
|
assert event.updated_at is not None
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_calendar_event_all_day(app, user):
|
|
"""Test all-day calendar event."""
|
|
with app.app_context():
|
|
start_time = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
|
|
end_time = start_time.replace(hour=23, minute=59, second=59)
|
|
|
|
event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Holiday",
|
|
start_time=start_time,
|
|
end_time=end_time,
|
|
all_day=True,
|
|
event_type="event"
|
|
)
|
|
db.session.add(event)
|
|
db.session.commit()
|
|
|
|
assert event.all_day is True
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_calendar_event_with_project(app, user, project):
|
|
"""Test calendar event associated with a project."""
|
|
with app.app_context():
|
|
start_time = datetime.now()
|
|
end_time = start_time + timedelta(hours=1)
|
|
|
|
event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Project Review",
|
|
start_time=start_time,
|
|
end_time=end_time,
|
|
project_id=project.id,
|
|
event_type="meeting"
|
|
)
|
|
db.session.add(event)
|
|
db.session.commit()
|
|
|
|
db.session.refresh(event)
|
|
assert event.project is not None
|
|
assert event.project.id == project.id
|
|
assert event.project.name == project.name
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_calendar_event_with_task(app, user, project):
|
|
"""Test calendar event associated with a task."""
|
|
with app.app_context():
|
|
# Create a task
|
|
task = Task(
|
|
project_id=project.id,
|
|
name="Complete documentation",
|
|
created_by=user.id,
|
|
assigned_to=user.id
|
|
)
|
|
db.session.add(task)
|
|
db.session.commit()
|
|
|
|
start_time = datetime.now()
|
|
end_time = start_time + timedelta(hours=3)
|
|
|
|
event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Work on documentation",
|
|
start_time=start_time,
|
|
end_time=end_time,
|
|
task_id=task.id,
|
|
event_type="deadline"
|
|
)
|
|
db.session.add(event)
|
|
db.session.commit()
|
|
|
|
db.session.refresh(event)
|
|
assert event.task is not None
|
|
assert event.task.id == task.id
|
|
assert event.task.name == "Complete documentation"
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_calendar_event_with_client(app, user, test_client):
|
|
"""Test calendar event associated with a client."""
|
|
with app.app_context():
|
|
start_time = datetime.now()
|
|
end_time = start_time + timedelta(hours=1)
|
|
|
|
event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Client Meeting",
|
|
start_time=start_time,
|
|
end_time=end_time,
|
|
client_id=test_client.id,
|
|
event_type="appointment"
|
|
)
|
|
db.session.add(event)
|
|
db.session.commit()
|
|
|
|
db.session.refresh(event)
|
|
assert event.client is not None
|
|
assert event.client.id == test_client.id
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_calendar_event_recurring(app, user):
|
|
"""Test recurring calendar event."""
|
|
with app.app_context():
|
|
start_time = datetime.now()
|
|
end_time = start_time + timedelta(hours=1)
|
|
recurrence_end = start_time + timedelta(days=90)
|
|
|
|
event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Weekly Standup",
|
|
start_time=start_time,
|
|
end_time=end_time,
|
|
is_recurring=True,
|
|
recurrence_rule="FREQ=WEEKLY;BYDAY=MO,WE,FR",
|
|
recurrence_end_date=recurrence_end,
|
|
event_type="meeting"
|
|
)
|
|
db.session.add(event)
|
|
db.session.commit()
|
|
|
|
assert event.is_recurring is True
|
|
assert event.recurrence_rule == "FREQ=WEEKLY;BYDAY=MO,WE,FR"
|
|
assert event.recurrence_end_date == recurrence_end
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_calendar_event_with_reminder(app, user):
|
|
"""Test calendar event with reminder."""
|
|
with app.app_context():
|
|
start_time = datetime.now()
|
|
end_time = start_time + timedelta(hours=1)
|
|
|
|
event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Important Meeting",
|
|
start_time=start_time,
|
|
end_time=end_time,
|
|
reminder_minutes=30,
|
|
event_type="meeting"
|
|
)
|
|
db.session.add(event)
|
|
db.session.commit()
|
|
|
|
assert event.reminder_minutes == 30
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_calendar_event_with_color(app, user):
|
|
"""Test calendar event with custom color."""
|
|
with app.app_context():
|
|
start_time = datetime.now()
|
|
end_time = start_time + timedelta(hours=1)
|
|
|
|
event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Colored Event",
|
|
start_time=start_time,
|
|
end_time=end_time,
|
|
color="#FF5733",
|
|
event_type="event"
|
|
)
|
|
db.session.add(event)
|
|
db.session.commit()
|
|
|
|
assert event.color == "#FF5733"
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_calendar_event_private(app, user):
|
|
"""Test private calendar event."""
|
|
with app.app_context():
|
|
start_time = datetime.now()
|
|
end_time = start_time + timedelta(hours=1)
|
|
|
|
event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Private Event",
|
|
start_time=start_time,
|
|
end_time=end_time,
|
|
is_private=True,
|
|
event_type="event"
|
|
)
|
|
db.session.add(event)
|
|
db.session.commit()
|
|
|
|
assert event.is_private is True
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_calendar_event_duration_hours(app, user):
|
|
"""Test calendar event duration calculation."""
|
|
with app.app_context():
|
|
start_time = datetime.now()
|
|
end_time = start_time + timedelta(hours=2, minutes=30)
|
|
|
|
event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Test Event",
|
|
start_time=start_time,
|
|
end_time=end_time,
|
|
event_type="event"
|
|
)
|
|
db.session.add(event)
|
|
db.session.commit()
|
|
|
|
assert event.duration_hours() == 2.5
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_calendar_event_to_dict(app, user, project):
|
|
"""Test calendar event serialization to dictionary."""
|
|
with app.app_context():
|
|
start_time = datetime.now()
|
|
end_time = start_time + timedelta(hours=1)
|
|
|
|
event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Test Event",
|
|
start_time=start_time,
|
|
end_time=end_time,
|
|
description="Test description",
|
|
location="Office",
|
|
event_type="meeting",
|
|
project_id=project.id,
|
|
all_day=False,
|
|
is_private=False,
|
|
color="#3b82f6",
|
|
reminder_minutes=15
|
|
)
|
|
db.session.add(event)
|
|
db.session.commit()
|
|
|
|
event_dict = event.to_dict()
|
|
|
|
assert 'id' in event_dict
|
|
assert 'title' in event_dict
|
|
assert 'description' in event_dict
|
|
assert 'start' in event_dict
|
|
assert 'end' in event_dict
|
|
assert 'allDay' in event_dict
|
|
assert 'location' in event_dict
|
|
assert 'eventType' in event_dict
|
|
assert 'projectId' in event_dict
|
|
assert 'color' in event_dict
|
|
assert 'isPrivate' in event_dict
|
|
assert 'reminderMinutes' in event_dict
|
|
|
|
assert event_dict['title'] == "Test Event"
|
|
assert event_dict['description'] == "Test description"
|
|
assert event_dict['location'] == "Office"
|
|
assert event_dict['eventType'] == "meeting"
|
|
assert event_dict['projectId'] == project.id
|
|
assert event_dict['color'] == "#3b82f6"
|
|
assert event_dict['reminderMinutes'] == 15
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_calendar_event_user_relationship(app, user):
|
|
"""Test calendar event user relationship."""
|
|
with app.app_context():
|
|
start_time = datetime.now()
|
|
end_time = start_time + timedelta(hours=1)
|
|
|
|
event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Test Event",
|
|
start_time=start_time,
|
|
end_time=end_time,
|
|
event_type="event"
|
|
)
|
|
db.session.add(event)
|
|
db.session.commit()
|
|
|
|
db.session.refresh(event)
|
|
assert event.user is not None
|
|
assert event.user.id == user.id
|
|
assert event.user.username == user.username
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_calendar_event_parent_child_relationship(app, user):
|
|
"""Test recurring calendar event parent-child relationship."""
|
|
with app.app_context():
|
|
start_time = datetime.now()
|
|
end_time = start_time + timedelta(hours=1)
|
|
|
|
# Create parent event
|
|
parent_event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Recurring Meeting",
|
|
start_time=start_time,
|
|
end_time=end_time,
|
|
is_recurring=True,
|
|
recurrence_rule="FREQ=WEEKLY",
|
|
event_type="meeting"
|
|
)
|
|
db.session.add(parent_event)
|
|
db.session.commit()
|
|
|
|
# Create child event (instance of recurring event)
|
|
child_start = start_time + timedelta(days=7)
|
|
child_end = child_start + timedelta(hours=1)
|
|
child_event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Recurring Meeting",
|
|
start_time=child_start,
|
|
end_time=child_end,
|
|
parent_event_id=parent_event.id,
|
|
event_type="meeting"
|
|
)
|
|
db.session.add(child_event)
|
|
db.session.commit()
|
|
|
|
db.session.refresh(parent_event)
|
|
db.session.refresh(child_event)
|
|
|
|
assert child_event.parent_event is not None
|
|
assert child_event.parent_event.id == parent_event.id
|
|
assert parent_event.child_events.count() == 1
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_get_events_in_range(app, user):
|
|
"""Test getting events in a date range."""
|
|
with app.app_context():
|
|
# Create events
|
|
now = datetime.now()
|
|
|
|
# Event within range
|
|
event1 = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Event 1",
|
|
start_time=now,
|
|
end_time=now + timedelta(hours=1),
|
|
event_type="event"
|
|
)
|
|
|
|
# Event outside range
|
|
event2 = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Event 2",
|
|
start_time=now + timedelta(days=30),
|
|
end_time=now + timedelta(days=30, hours=1),
|
|
event_type="event"
|
|
)
|
|
|
|
db.session.add_all([event1, event2])
|
|
db.session.commit()
|
|
|
|
# Get events in range
|
|
start_date = now - timedelta(days=1)
|
|
end_date = now + timedelta(days=7)
|
|
result = CalendarEvent.get_events_in_range(
|
|
user_id=user.id,
|
|
start_date=start_date,
|
|
end_date=end_date,
|
|
include_tasks=False,
|
|
include_time_entries=False
|
|
)
|
|
|
|
assert len(result['events']) == 1
|
|
assert result['events'][0]['title'] == "Event 1"
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_get_events_in_range_with_tasks(app, user, project):
|
|
"""Test getting events with tasks in date range."""
|
|
with app.app_context():
|
|
# Create event
|
|
now = datetime.now()
|
|
event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Event",
|
|
start_time=now,
|
|
end_time=now + timedelta(hours=1),
|
|
event_type="event"
|
|
)
|
|
db.session.add(event)
|
|
|
|
# Create task with due date
|
|
task = Task(
|
|
project_id=project.id,
|
|
name="Task with due date",
|
|
created_by=user.id,
|
|
assigned_to=user.id,
|
|
due_date=now.date() + timedelta(days=3),
|
|
status='todo'
|
|
)
|
|
db.session.add(task)
|
|
db.session.commit()
|
|
|
|
# Get events including tasks
|
|
start_date = now - timedelta(days=1)
|
|
end_date = now + timedelta(days=7)
|
|
result = CalendarEvent.get_events_in_range(
|
|
user_id=user.id,
|
|
start_date=start_date,
|
|
end_date=end_date,
|
|
include_tasks=True,
|
|
include_time_entries=False
|
|
)
|
|
|
|
assert len(result['events']) == 1
|
|
assert len(result['tasks']) == 1
|
|
assert result['tasks'][0]['title'] == "Task with due date"
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_get_events_in_range_with_time_entries(app, user, project):
|
|
"""Test getting events with time entries in date range."""
|
|
with app.app_context():
|
|
# Create event
|
|
now = datetime.now()
|
|
event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Event",
|
|
start_time=now,
|
|
end_time=now + timedelta(hours=1),
|
|
event_type="event"
|
|
)
|
|
db.session.add(event)
|
|
|
|
# Create time entry
|
|
time_entry = TimeEntry(
|
|
user_id=user.id,
|
|
project_id=project.id,
|
|
start_time=now + timedelta(hours=2),
|
|
end_time=now + timedelta(hours=4),
|
|
notes="Working on feature"
|
|
)
|
|
db.session.add(time_entry)
|
|
db.session.commit()
|
|
|
|
# Get events including time entries
|
|
start_date = now - timedelta(days=1)
|
|
end_date = now + timedelta(days=1)
|
|
result = CalendarEvent.get_events_in_range(
|
|
user_id=user.id,
|
|
start_date=start_date,
|
|
end_date=end_date,
|
|
include_tasks=False,
|
|
include_time_entries=True
|
|
)
|
|
|
|
assert len(result['events']) == 1
|
|
assert len(result['time_entries']) == 1
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_calendar_event_repr(app, user):
|
|
"""Test calendar event string representation."""
|
|
with app.app_context():
|
|
start_time = datetime.now()
|
|
end_time = start_time + timedelta(hours=1)
|
|
|
|
event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Test Event",
|
|
start_time=start_time,
|
|
end_time=end_time,
|
|
event_type="event"
|
|
)
|
|
db.session.add(event)
|
|
db.session.commit()
|
|
|
|
repr_str = repr(event)
|
|
assert 'CalendarEvent' in repr_str
|
|
assert 'Test Event' in repr_str
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_calendar_event_cascade_delete_with_user(app, user):
|
|
"""Test that events are deleted when user is deleted."""
|
|
with app.app_context():
|
|
start_time = datetime.now()
|
|
end_time = start_time + timedelta(hours=1)
|
|
|
|
# Re-query the user to attach to current session
|
|
from app.models.user import User
|
|
user_in_session = User.query.get(user.id)
|
|
|
|
event = CalendarEvent(
|
|
user_id=user_in_session.id,
|
|
title="Test Event",
|
|
start_time=start_time,
|
|
end_time=end_time,
|
|
event_type="event"
|
|
)
|
|
db.session.add(event)
|
|
db.session.commit()
|
|
|
|
event_id = event.id
|
|
|
|
# Delete user
|
|
db.session.delete(user_in_session)
|
|
db.session.commit()
|
|
|
|
# Event should be deleted
|
|
deleted_event = CalendarEvent.query.get(event_id)
|
|
assert deleted_event is None
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_calendar_event_cascade_delete_with_parent(app, user):
|
|
"""Test that child events are deleted when parent is deleted."""
|
|
with app.app_context():
|
|
start_time = datetime.now()
|
|
end_time = start_time + timedelta(hours=1)
|
|
|
|
# Create parent event
|
|
parent_event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Parent Event",
|
|
start_time=start_time,
|
|
end_time=end_time,
|
|
is_recurring=True,
|
|
event_type="meeting"
|
|
)
|
|
db.session.add(parent_event)
|
|
db.session.commit()
|
|
|
|
# Create child event
|
|
child_start = start_time + timedelta(days=7)
|
|
child_end = child_start + timedelta(hours=1)
|
|
child_event = CalendarEvent(
|
|
user_id=user.id,
|
|
title="Child Event",
|
|
start_time=child_start,
|
|
end_time=child_end,
|
|
parent_event_id=parent_event.id,
|
|
event_type="meeting"
|
|
)
|
|
db.session.add(child_event)
|
|
db.session.commit()
|
|
|
|
child_id = child_event.id
|
|
|
|
# Delete parent
|
|
db.session.delete(parent_event)
|
|
db.session.commit()
|
|
|
|
# Child should be deleted
|
|
deleted_child = CalendarEvent.query.get(child_id)
|
|
assert deleted_child is None
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_calendar_event_different_types(app, user):
|
|
"""Test calendar events with different types."""
|
|
with app.app_context():
|
|
now = datetime.now()
|
|
event_types = ['event', 'meeting', 'appointment', 'reminder', 'deadline']
|
|
|
|
events = []
|
|
for event_type in event_types:
|
|
event = CalendarEvent(
|
|
user_id=user.id,
|
|
title=f"Test {event_type}",
|
|
start_time=now,
|
|
end_time=now + timedelta(hours=1),
|
|
event_type=event_type
|
|
)
|
|
events.append(event)
|
|
|
|
db.session.add_all(events)
|
|
db.session.commit()
|
|
|
|
for idx, event_type in enumerate(event_types):
|
|
assert events[idx].event_type == event_type
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.models
|
|
def test_calendar_event_user_has_events_relationship(app, user):
|
|
"""Test that user has calendar_events relationship."""
|
|
with app.app_context():
|
|
now = datetime.now()
|
|
|
|
# Re-query the user to attach to current session
|
|
from app.models.user import User
|
|
user_in_session = User.query.get(user.id)
|
|
|
|
event1 = CalendarEvent(
|
|
user_id=user_in_session.id,
|
|
title="Event 1",
|
|
start_time=now,
|
|
end_time=now + timedelta(hours=1),
|
|
event_type="event"
|
|
)
|
|
event2 = CalendarEvent(
|
|
user_id=user_in_session.id,
|
|
title="Event 2",
|
|
start_time=now + timedelta(days=1),
|
|
end_time=now + timedelta(days=1, hours=1),
|
|
event_type="meeting"
|
|
)
|
|
db.session.add_all([event1, event2])
|
|
db.session.commit()
|
|
|
|
db.session.refresh(user_in_session)
|
|
assert user_in_session.calendar_events.count() == 2
|
|
|