from datetime import datetime from unittest.mock import MagicMock from uuid import uuid4 import pytest from pydantic import ValidationError from schemas.agent.skill_config import SkillName from schemas.domain.automation import AutomationJobConfig from v1.automation_jobs.schemas import ( AutomationJobCreateRequest, AutomationJobResponse, AutomationJobUpdateRequest, ) def _mock_orm_job() -> MagicMock: mock_orm_job = MagicMock() mock_orm_job.id = uuid4() mock_orm_job.owner_id = uuid4() mock_orm_job.bootstrap_key = "memory_extraction" mock_orm_job.title = "Test Job" mock_orm_job.config = { "input_template": "Hello", "enabled_skills": ["memory"], "context": { "source": "latest_chat", "window_mode": "day", "window_count": 2, }, "schedule": { "type": "daily", "run_at": {"hour": 8, "minute": 0}, }, } mock_orm_job.status = "active" mock_orm_job.timezone = "Asia/Shanghai" mock_orm_job.next_run_at = datetime.now() mock_orm_job.last_run_at = None mock_orm_job.created_at = datetime.now() mock_orm_job.updated_at = datetime.now() return mock_orm_job def test_response_is_system_true_when_bootstrap_key_present() -> None: resp = AutomationJobResponse.from_orm(_mock_orm_job()) assert resp.is_system is True def test_response_parses_schedule_from_config() -> None: resp = AutomationJobResponse.from_orm(_mock_orm_job()) assert resp.config.schedule is not None assert resp.config.schedule.type.value == "daily" assert resp.config.schedule.run_at.hour == 8 def test_create_request_requires_config_schedule() -> None: with pytest.raises(ValidationError): AutomationJobCreateRequest.model_validate( { "title": "Test Job", "timezone": "Asia/Shanghai", "config": { "input_template": "Hello", }, } ) def test_create_request_valid_timezone() -> None: request = AutomationJobCreateRequest.model_validate( { "title": "Test Job", "timezone": "Asia/Shanghai", "config": { "input_template": "Hello", "enabled_skills": ["memory"], "context": { "source": "latest_chat", "window_mode": "day", "window_count": 2, }, "schedule": { "type": "daily", "run_at": {"hour": 9, "minute": 0}, }, }, } ) assert request.timezone == "Asia/Shanghai" def test_update_timezone_validation() -> None: request = AutomationJobUpdateRequest.model_validate( {"timezone": "America/New_York"} ) assert request.timezone == "America/New_York" with pytest.raises(ValidationError): AutomationJobUpdateRequest.model_validate({"timezone": "Invalid/Timezone"}) def test_config_patch_still_allows_partial_payload() -> None: patch = AutomationJobConfig.model_validate( {"enabled_skills": [SkillName.MEMORY]} ) assert patch.input_template is None assert patch.enabled_skills == [SkillName.MEMORY]