Two milestones: a note can carry its own check (317), and a rule keeps what it used to say (323) #135
@@ -1,13 +1,23 @@
|
||||
"""Tests for task lifecycle timestamps and recurrence logic."""
|
||||
"""Tests for task lifecycle timestamps and recurrence logic.
|
||||
|
||||
The note stand-ins come from `fake_note`, not a bare MagicMock. These four
|
||||
predated that helper and broke the moment `update_note` started reading a
|
||||
column they did not set (milestone 317): a fresh MagicMock is truthy on every
|
||||
attribute, so `verify_with` read as "this record carries a check" and the
|
||||
guard refused the write. That is note 2109's lesson, and the reason fake_note
|
||||
exists — a stand-in has to be able to say NO.
|
||||
"""
|
||||
from datetime import date, datetime, timezone
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from tests.helpers import fake_note, make_mock_session
|
||||
|
||||
|
||||
# ── Timestamp side-effect tests ──────────────────────────────────────────────
|
||||
|
||||
async def test_update_note_sets_started_at_on_in_progress():
|
||||
"""started_at is set when status transitions to in_progress."""
|
||||
mock_note = MagicMock()
|
||||
mock_note = fake_note()
|
||||
mock_note.status = "in_progress"
|
||||
mock_note.started_at = None
|
||||
mock_note.recurrence_rule = None
|
||||
@@ -28,7 +38,7 @@ async def test_update_note_sets_started_at_on_in_progress():
|
||||
|
||||
async def test_update_note_sets_completed_at_on_done():
|
||||
"""completed_at is set when status transitions to done."""
|
||||
mock_note = MagicMock()
|
||||
mock_note = fake_note()
|
||||
mock_note.status = "done"
|
||||
mock_note.started_at = datetime(2026, 3, 1, tzinfo=timezone.utc)
|
||||
mock_note.completed_at = None
|
||||
@@ -50,7 +60,7 @@ async def test_update_note_sets_completed_at_on_done():
|
||||
|
||||
async def test_update_note_clears_timestamps_on_todo():
|
||||
"""started_at and completed_at are cleared when status resets to todo."""
|
||||
mock_note = MagicMock()
|
||||
mock_note = fake_note()
|
||||
mock_note.status = "todo"
|
||||
mock_note.started_at = datetime(2026, 3, 1, tzinfo=timezone.utc)
|
||||
mock_note.completed_at = datetime(2026, 3, 15, tzinfo=timezone.utc)
|
||||
@@ -74,7 +84,7 @@ async def test_update_note_clears_timestamps_on_todo():
|
||||
async def test_update_note_preserves_started_at_if_already_set():
|
||||
"""started_at is not overwritten on a second transition to in_progress."""
|
||||
original_start = datetime(2026, 3, 1, tzinfo=timezone.utc)
|
||||
mock_note = MagicMock()
|
||||
mock_note = fake_note()
|
||||
mock_note.status = "in_progress"
|
||||
mock_note.started_at = original_start
|
||||
mock_note.recurrence_rule = None
|
||||
@@ -96,7 +106,6 @@ async def test_update_note_preserves_started_at_if_already_set():
|
||||
# ── Recurrence rule validation ────────────────────────────────────────────────
|
||||
|
||||
import pytest
|
||||
from tests.helpers import make_mock_session
|
||||
|
||||
|
||||
def test_validate_interval_rule_valid():
|
||||
|
||||
Reference in New Issue
Block a user