fix(tests): the recurrence stand-ins come from fake_note, not a bare MagicMock (#3164)
CI & Build / Python lint (push) Successful in 5s
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / integration (push) Successful in 26s
CI & Build / TypeScript typecheck (push) Successful in 35s
CI & Build / Python tests (push) Successful in 1m7s
CI & Build / Build & push image (push) Successful in 23s
CI & Build / Python lint (push) Successful in 5s
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / integration (push) Successful in 26s
CI & Build / TypeScript typecheck (push) Successful in 35s
CI & Build / Python tests (push) Successful in 1m7s
CI & Build / Build & push image (push) Successful in 23s
Four tests predating the helper built their note with MagicMock(), which is truthy on every attribute nobody set. update_note now reads verify_with, so the stand-in claimed to carry a check and the milestone-317 guard refused the write. That is note 2109 exactly, and the reason fake_note exists: a stand-in has to be able to say NO. The product behaviour is right — a real column is None or a string, so this cannot happen outside a test. Observation, not changed here: fake_note sets is_task=False but leaves `status` unset, so it too is a truthy mock on the column is_task is derived FROM. Nothing depends on it today; worth making self-consistent when something does.
This commit is contained in:
@@ -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