"""Regression tests for KIN-126 — фильтр по дате выполнения задач. Проверяет backend-поведение: 1. Колонка completed_at добавляется в таблицу tasks при инициализации БД 2. Новая задача имеет completed_at=None по умолчанию 3. update_task(status='done') устанавливает completed_at как ISO-строку 4. update_task(status='done') — completed_at является валидной ISO-строкой 5. update_task(status='in_progress') не устанавливает completed_at 6. update_task(status='cancelled') не устанавливает completed_at 7. Обновление полей без смены статуса на done не трогает completed_at 8. update_task(status='blocked') не устанавливает completed_at """ import pytest from datetime import datetime from core.db import init_db from core import models @pytest.fixture def conn(): """Fresh in-memory DB for each test.""" c = init_db(db_path=":memory:") yield c c.close() # --------------------------------------------------------------------------- # Schema # --------------------------------------------------------------------------- def test_schema_tasks_has_completed_at_column(conn): """KIN-126: таблица tasks содержит колонку completed_at после инициализации БД.""" cols = {r[1] for r in conn.execute("PRAGMA table_info(tasks)").fetchall()} assert "completed_at" in cols, "KIN-126: колонка completed_at должна быть в таблице tasks" # --------------------------------------------------------------------------- # Default value # --------------------------------------------------------------------------- def test_new_task_completed_at_is_null(conn): """KIN-126: новая задача имеет completed_at=None по умолчанию.""" models.create_project(conn, "p1", "P1", "/p1") t = models.create_task(conn, "P1-001", "p1", "Task") assert t["completed_at"] is None # --------------------------------------------------------------------------- # Setting completed_at on status='done' # --------------------------------------------------------------------------- def test_update_task_to_done_sets_completed_at(conn): """KIN-126: update_task(status='done') устанавливает completed_at.""" models.create_project(conn, "p1", "P1", "/p1") models.create_task(conn, "P1-001", "p1", "Task") updated = models.update_task(conn, "P1-001", status="done") assert updated["completed_at"] is not None def test_update_task_to_done_completed_at_is_valid_iso(conn): """KIN-126: completed_at при status='done' — валидная ISO-строка datetime.""" models.create_project(conn, "p1", "P1", "/p1") models.create_task(conn, "P1-001", "p1", "Task") updated = models.update_task(conn, "P1-001", status="done") # Must parse without exception parsed = datetime.fromisoformat(updated["completed_at"]) assert parsed is not None # --------------------------------------------------------------------------- # Non-done statuses do NOT set completed_at # --------------------------------------------------------------------------- def test_update_task_to_in_progress_does_not_set_completed_at(conn): """KIN-126: update_task(status='in_progress') не устанавливает completed_at.""" models.create_project(conn, "p1", "P1", "/p1") models.create_task(conn, "P1-001", "p1", "Task") updated = models.update_task(conn, "P1-001", status="in_progress") assert updated["completed_at"] is None def test_update_task_to_cancelled_does_not_set_completed_at(conn): """KIN-126: update_task(status='cancelled') не устанавливает completed_at.""" models.create_project(conn, "p1", "P1", "/p1") models.create_task(conn, "P1-001", "p1", "Task") updated = models.update_task(conn, "P1-001", status="cancelled") assert updated["completed_at"] is None def test_update_task_to_blocked_does_not_set_completed_at(conn): """KIN-126: update_task(status='blocked') не устанавливает completed_at.""" models.create_project(conn, "p1", "P1", "/p1") models.create_task(conn, "P1-001", "p1", "Task") updated = models.update_task(conn, "P1-001", status="blocked") assert updated["completed_at"] is None # --------------------------------------------------------------------------- # Non-status updates do NOT touch completed_at # --------------------------------------------------------------------------- def test_update_task_priority_only_does_not_set_completed_at(conn): """KIN-126: update_task с изменением только priority не трогает completed_at.""" models.create_project(conn, "p1", "P1", "/p1") models.create_task(conn, "P1-001", "p1", "Task") updated = models.update_task(conn, "P1-001", priority=1) assert updated["completed_at"] is None