import anyio from anyio import Path as AsyncPath from app.agent.middleware.jobs import _alist_jobs, filter_active_jobs def test_filter_active_jobs_only_keeps_pending_and_in_progress(): """筛选任务时只保留待执行和执行中的任务。""" jobs_metadata = [ { "id": "pending-job", "name": "待执行任务", "description": "desc", "path": "/tmp/pending/JOB.md", "schedule": "once", "status": "pending", "last_run": None, }, { "id": "running-job", "name": "执行中任务", "description": "desc", "path": "/tmp/running/JOB.md", "schedule": "recurring", "status": "in_progress", "last_run": "2026-05-10 10:00", }, { "id": "completed-recurring-job", "name": "已完成循环任务", "description": "desc", "path": "/tmp/completed/JOB.md", "schedule": "recurring", "status": "completed", "last_run": "2026-05-10 11:00", }, { "id": "cancelled-job", "name": "已取消任务", "description": "desc", "path": "/tmp/cancelled/JOB.md", "schedule": "once", "status": "cancelled", "last_run": None, }, ] active_job_ids = [job["id"] for job in filter_active_jobs(jobs_metadata)] assert active_job_ids == ["pending-job", "running-job"] def test_alist_jobs_sorts_job_directories_by_name(tmp_path): """加载任务元数据时按任务目录名稳定排序。""" for job_id in ("z-job", "a-job", "m-job"): job_dir = tmp_path / job_id job_dir.mkdir() (job_dir / "JOB.md").write_text( f"""--- name: {job_id} description: test schedule: once status: pending --- # {job_id} """, encoding="utf-8", ) jobs = anyio.run(_alist_jobs, AsyncPath(str(tmp_path))) assert [job["id"] for job in jobs] == ["a-job", "m-job", "z-job"] def test_alist_jobs_tolerates_invalid_utf8_bytes(tmp_path): """加载任务元数据时非法 UTF-8 字节不应中断整个 Agent。""" job_dir = tmp_path / "broken-job" job_dir.mkdir() (job_dir / "JOB.md").write_bytes( b"""--- name: broken-job description: test schedule: once status: pending --- # broken-job \x90 """ ) jobs = anyio.run(_alist_jobs, AsyncPath(str(tmp_path))) assert [job["id"] for job in jobs] == ["broken-job"]