"""Tests for scheduled task model.""" import uuid from datetime import UTC, datetime, timedelta from app.models.scheduled_task import ( RecurrenceType, ScheduledTask, TaskStatus, TaskType, ) class TestScheduledTaskModel: """Test cases for scheduled task model.""" def test_task_creation(self): """Test basic task creation.""" task = ScheduledTask( name="Test Task", task_type=TaskType.CREDIT_RECHARGE, scheduled_at=datetime.now(tz=UTC) + timedelta(hours=1), ) assert task.name == "Test Task" assert task.task_type == TaskType.CREDIT_RECHARGE assert task.status == TaskStatus.PENDING assert task.timezone == "UTC" assert task.recurrence_type == RecurrenceType.NONE assert task.parameters == {} assert task.user_id is None assert task.executions_count == 0 assert task.is_active is True def test_task_with_user(self): """Test task creation with user association.""" user_id = uuid.uuid4() task = ScheduledTask( name="User Task", task_type=TaskType.PLAY_SOUND, scheduled_at=datetime.now(tz=UTC) + timedelta(hours=1), user_id=user_id, ) assert task.user_id == user_id assert not task.is_system_task() def test_system_task(self): """Test system task (no user association).""" task = ScheduledTask( name="System Task", task_type=TaskType.CREDIT_RECHARGE, scheduled_at=datetime.now(tz=UTC) + timedelta(hours=1), ) assert task.user_id is None assert task.is_system_task() def test_recurring_task(self): """Test recurring task properties.""" task = ScheduledTask( name="Recurring Task", task_type=TaskType.CREDIT_RECHARGE, scheduled_at=datetime.now(tz=UTC) + timedelta(hours=1), recurrence_type=RecurrenceType.DAILY, recurrence_count=5, ) assert task.is_recurring() assert task.should_repeat() def test_non_recurring_task(self): """Test non-recurring task properties.""" task = ScheduledTask( name="One-shot Task", task_type=TaskType.PLAY_SOUND, scheduled_at=datetime.now(tz=UTC) + timedelta(hours=1), recurrence_type=RecurrenceType.NONE, ) assert not task.is_recurring() assert not task.should_repeat() def test_infinite_recurring_task(self): """Test infinitely recurring task.""" task = ScheduledTask( name="Infinite Task", task_type=TaskType.CREDIT_RECHARGE, scheduled_at=datetime.now(tz=UTC) + timedelta(hours=1), recurrence_type=RecurrenceType.DAILY, recurrence_count=None, # Infinite ) assert task.is_recurring() assert task.should_repeat() # Even after many executions task.executions_count = 100 assert task.should_repeat() def test_recurring_task_execution_limit(self): """Test recurring task with execution limit.""" task = ScheduledTask( name="Limited Task", task_type=TaskType.CREDIT_RECHARGE, scheduled_at=datetime.now(tz=UTC) + timedelta(hours=1), recurrence_type=RecurrenceType.DAILY, recurrence_count=3, ) assert task.should_repeat() # After 3 executions, should not repeat task.executions_count = 3 assert not task.should_repeat() # After more than limit, still should not repeat task.executions_count = 5 assert not task.should_repeat() def test_task_expiration(self): """Test task expiration.""" # Non-expired task (using naive UTC datetimes) task = ScheduledTask( name="Valid Task", task_type=TaskType.CREDIT_RECHARGE, scheduled_at=datetime.now(tz=UTC).replace(tzinfo=None) + timedelta(hours=1), expires_at=datetime.now(tz=UTC).replace(tzinfo=None) + timedelta(hours=2), ) assert not task.is_expired() # Expired task (using naive UTC datetimes) expired_task = ScheduledTask( name="Expired Task", task_type=TaskType.CREDIT_RECHARGE, scheduled_at=datetime.now(tz=UTC).replace(tzinfo=None) + timedelta(hours=1), expires_at=datetime.now(tz=UTC).replace(tzinfo=None) - timedelta(hours=1), ) assert expired_task.is_expired() # Task with no expiration no_expiry_task = ScheduledTask( name="No Expiry Task", task_type=TaskType.CREDIT_RECHARGE, scheduled_at=datetime.now(tz=UTC) + timedelta(hours=1), ) assert not no_expiry_task.is_expired() def test_task_with_parameters(self): """Test task with custom parameters.""" parameters = { "sound_id": str(uuid.uuid4()), "volume": 80, "repeat": True, } task = ScheduledTask( name="Parametrized Task", task_type=TaskType.PLAY_SOUND, scheduled_at=datetime.now(tz=UTC) + timedelta(hours=1), parameters=parameters, ) assert task.parameters == parameters assert task.parameters["sound_id"] == parameters["sound_id"] assert task.parameters["volume"] == 80 assert task.parameters["repeat"] is True def test_task_with_timezone(self): """Test task with custom timezone.""" task = ScheduledTask( name="NY Task", task_type=TaskType.CREDIT_RECHARGE, scheduled_at=datetime.now(tz=UTC) + timedelta(hours=1), timezone="America/New_York", ) assert task.timezone == "America/New_York" def test_task_with_cron_expression(self): """Test task with cron expression.""" cron_expr = "0 9 * * 1-5" # 9 AM on weekdays task = ScheduledTask( name="Cron Task", task_type=TaskType.CREDIT_RECHARGE, scheduled_at=datetime.now(tz=UTC) + timedelta(hours=1), recurrence_type=RecurrenceType.CRON, cron_expression=cron_expr, ) assert task.recurrence_type == RecurrenceType.CRON assert task.cron_expression == cron_expr assert task.is_recurring() def test_task_status_enum_values(self): """Test all task status enum values.""" assert TaskStatus.PENDING == "pending" assert TaskStatus.RUNNING == "running" assert TaskStatus.COMPLETED == "completed" assert TaskStatus.FAILED == "failed" assert TaskStatus.CANCELLED == "cancelled" def test_task_type_enum_values(self): """Test all task type enum values.""" assert TaskType.CREDIT_RECHARGE == "credit_recharge" assert TaskType.PLAY_SOUND == "play_sound" assert TaskType.PLAY_PLAYLIST == "play_playlist" def test_recurrence_type_enum_values(self): """Test all recurrence type enum values.""" assert RecurrenceType.NONE == "none" assert RecurrenceType.HOURLY == "hourly" assert RecurrenceType.DAILY == "daily" assert RecurrenceType.WEEKLY == "weekly" assert RecurrenceType.MONTHLY == "monthly" assert RecurrenceType.YEARLY == "yearly" assert RecurrenceType.CRON == "cron"