Notes field per entry #14
1 changed files with 159 additions and 0 deletions
159
tests/test_notes.py
Normal file
159
tests/test_notes.py
Normal file
|
|
@ -0,0 +1,159 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
|
from quartermaster import month_service, service
|
||||||
|
from quartermaster.models import Section
|
||||||
|
|
||||||
|
|
||||||
|
def test_add_entry_stores_notes(db):
|
||||||
|
entry = service.add_entry(
|
||||||
|
db,
|
||||||
|
Section.sinking_fund,
|
||||||
|
"Emergency",
|
||||||
|
Decimal("500.00"),
|
||||||
|
notes="Target: 3 months of expenses",
|
||||||
|
)
|
||||||
|
assert entry.notes == "Target: 3 months of expenses"
|
||||||
|
|
||||||
|
|
||||||
|
def test_add_entry_strips_and_nulls_empty_notes(db):
|
||||||
|
entry = service.add_entry(
|
||||||
|
db, Section.other, "Gift", Decimal("25.00"), notes=" "
|
||||||
|
)
|
||||||
|
assert entry.notes is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_set_entry_notes_updates(db):
|
||||||
|
entry = service.add_entry(db, Section.food, "Groceries", Decimal("400.00"))
|
||||||
|
updated = service.set_entry_notes(db, entry.id, "weekly Costco run")
|
||||||
|
assert updated is not None
|
||||||
|
assert updated.notes == "weekly Costco run"
|
||||||
|
|
||||||
|
|
||||||
|
def test_set_entry_notes_missing_returns_none(db):
|
||||||
|
assert service.set_entry_notes(db, 9999, "oops") is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_snapshot_copies_notes(db):
|
||||||
|
service.add_entry(
|
||||||
|
db,
|
||||||
|
Section.sinking_fund,
|
||||||
|
"Emergency",
|
||||||
|
Decimal("500.00"),
|
||||||
|
notes="3 months expenses",
|
||||||
|
)
|
||||||
|
month = month_service.create_month(db, "2026-04")
|
||||||
|
emergency = next(e for e in month.entries if e.origin_name == "Emergency")
|
||||||
|
assert emergency.notes == "3 months expenses"
|
||||||
|
|
||||||
|
|
||||||
|
def test_month_notes_edit_does_not_change_deviation_state(db):
|
||||||
|
service.add_entry(
|
||||||
|
db, Section.fixed_bill, "Rent", Decimal("1200.00"), notes="auto-pay"
|
||||||
|
)
|
||||||
|
month = month_service.create_month(db, "2026-04")
|
||||||
|
rent = next(e for e in month.entries if e.origin_name == "Rent")
|
||||||
|
# unchanged initially
|
||||||
|
assert (
|
||||||
|
month_service.deviation_state(rent) == month_service.DeviationState.unchanged
|
||||||
|
)
|
||||||
|
# update notes only
|
||||||
|
month_service.update_month_entry(
|
||||||
|
db, month, rent.id, notes="auto-pay; renew July 2027"
|
||||||
|
)
|
||||||
|
db.refresh(rent)
|
||||||
|
assert rent.notes == "auto-pay; renew July 2027"
|
||||||
|
assert (
|
||||||
|
month_service.deviation_state(rent) == month_service.DeviationState.unchanged
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_month_entry_notes_to_empty_nulls(db):
|
||||||
|
service.add_entry(db, Section.other, "Parking", Decimal("25.00"), notes="work")
|
||||||
|
month = month_service.create_month(db, "2026-04")
|
||||||
|
entry = next(e for e in month.entries if e.origin_name == "Parking")
|
||||||
|
assert entry.notes == "work"
|
||||||
|
month_service.update_month_entry(db, month, entry.id, notes="")
|
||||||
|
db.refresh(entry)
|
||||||
|
assert entry.notes is None
|
||||||
|
|
||||||
|
|
||||||
|
# --- route-level -----------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_entry_route_accepts_notes(client):
|
||||||
|
response = client.post(
|
||||||
|
"/sections/sinking_fund/entries",
|
||||||
|
data={"name": "Emergency", "amount": "500.00", "notes": "3 mo cushion"},
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert "3 mo cushion" in response.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_entry_notes_route(client):
|
||||||
|
client.post(
|
||||||
|
"/sections/food/entries",
|
||||||
|
data={"name": "Groceries", "amount": "400.00"},
|
||||||
|
)
|
||||||
|
response = client.post("/entries/1/notes", data={"notes": "weekly"})
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert "weekly" in response.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_entry_notes_empty_clears(client):
|
||||||
|
client.post(
|
||||||
|
"/sections/food/entries",
|
||||||
|
data={"name": "Groceries", "amount": "400.00", "notes": "weekly"},
|
||||||
|
)
|
||||||
|
response = client.post("/entries/1/notes", data={"notes": ""})
|
||||||
|
assert response.status_code == 200
|
||||||
|
# the input's value="" still renders but the placeholder kicks in;
|
||||||
|
# specifically, no literal "weekly" anymore
|
||||||
|
assert "value=\"weekly\"" not in response.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_month_entry_route_accepts_notes(client):
|
||||||
|
client.post("/month/2026-04/create")
|
||||||
|
response = client.post(
|
||||||
|
"/month/2026-04/sections/other/entries",
|
||||||
|
data={"name": "Gift", "planned": "25.00", "notes": "birthday"},
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert "birthday" in response.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_month_entry_route_accepts_notes(client):
|
||||||
|
client.post(
|
||||||
|
"/sections/fixed_bill/entries",
|
||||||
|
data={"name": "Rent", "amount": "1200.00"},
|
||||||
|
)
|
||||||
|
client.post("/month/2026-04/create")
|
||||||
|
response = client.post(
|
||||||
|
"/month/2026-04/entries/1", data={"notes": "auto-pay"}
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert "auto-pay" in response.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_budget_page_renders_notes_inputs(client):
|
||||||
|
client.post(
|
||||||
|
"/sections/fixed_bill/entries",
|
||||||
|
data={"name": "Rent", "amount": "1200.00", "notes": "due 1st"},
|
||||||
|
)
|
||||||
|
response = client.get("/")
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert "entry-notes-row" in response.text
|
||||||
|
assert "due 1st" in response.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_month_page_renders_notes_inputs(client):
|
||||||
|
client.post(
|
||||||
|
"/sections/fixed_bill/entries",
|
||||||
|
data={"name": "Rent", "amount": "1200.00", "notes": "auto-pay"},
|
||||||
|
)
|
||||||
|
client.post("/month/2026-04/create")
|
||||||
|
response = client.get("/month/2026-04")
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert "entry-notes-row" in response.text
|
||||||
|
assert "auto-pay" in response.text
|
||||||
Loading…
Reference in a new issue