test(api): fix ruff issues in routine tests
This commit is contained in:
parent
472a3034a0
commit
9bbc34ffd2
2 changed files with 61 additions and 38 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
import uuid
|
import uuid
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Routines
|
# Routines
|
||||||
|
|
@ -217,12 +218,17 @@ def test_delete_grooming_schedule_not_found(client):
|
||||||
r = client.delete(f"/routines/grooming-schedule/{uuid.uuid4()}")
|
r = client.delete(f"/routines/grooming-schedule/{uuid.uuid4()}")
|
||||||
assert r.status_code == 404
|
assert r.status_code == 404
|
||||||
|
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
def test_suggest_routine(client, session):
|
def test_suggest_routine(client, session):
|
||||||
with patch("innercontext.api.routines.call_gemini") as mock_gemini:
|
with patch("innercontext.api.routines.call_gemini") as mock_gemini:
|
||||||
# Mock the Gemini response
|
# Mock the Gemini response
|
||||||
mock_response = type("Response", (), {"text": '{"steps": [{"product_id": null, "action_type": "shaving_razor"}], "reasoning": "because"}'})
|
mock_response = type(
|
||||||
|
"Response",
|
||||||
|
(),
|
||||||
|
{
|
||||||
|
"text": '{"steps": [{"product_id": null, "action_type": "shaving_razor"}], "reasoning": "because"}'
|
||||||
|
},
|
||||||
|
)
|
||||||
mock_gemini.return_value = mock_response
|
mock_gemini.return_value = mock_response
|
||||||
|
|
||||||
r = client.post(
|
r = client.post(
|
||||||
|
|
@ -231,8 +237,8 @@ def test_suggest_routine(client, session):
|
||||||
"routine_date": "2026-03-03",
|
"routine_date": "2026-03-03",
|
||||||
"part_of_day": "am",
|
"part_of_day": "am",
|
||||||
"notes": "Testing",
|
"notes": "Testing",
|
||||||
"include_minoxidil_beard": True
|
"include_minoxidil_beard": True,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
data = r.json()
|
data = r.json()
|
||||||
|
|
@ -240,10 +246,17 @@ def test_suggest_routine(client, session):
|
||||||
assert data["steps"][0]["action_type"] == "shaving_razor"
|
assert data["steps"][0]["action_type"] == "shaving_razor"
|
||||||
assert data["reasoning"] == "because"
|
assert data["reasoning"] == "because"
|
||||||
|
|
||||||
|
|
||||||
def test_suggest_batch(client, session):
|
def test_suggest_batch(client, session):
|
||||||
with patch("innercontext.api.routines.call_gemini") as mock_gemini:
|
with patch("innercontext.api.routines.call_gemini") as mock_gemini:
|
||||||
# Mock the Gemini response
|
# Mock the Gemini response
|
||||||
mock_response = type("Response", (), {"text": '{"days": [{"date": "2026-03-03", "am_steps": [], "pm_steps": [], "reasoning": "none"}], "overall_reasoning": "batch test"}'})
|
mock_response = type(
|
||||||
|
"Response",
|
||||||
|
(),
|
||||||
|
{
|
||||||
|
"text": '{"days": [{"date": "2026-03-03", "am_steps": [], "pm_steps": [], "reasoning": "none"}], "overall_reasoning": "batch test"}'
|
||||||
|
},
|
||||||
|
)
|
||||||
mock_gemini.return_value = mock_response
|
mock_gemini.return_value = mock_response
|
||||||
|
|
||||||
r = client.post(
|
r = client.post(
|
||||||
|
|
@ -251,8 +264,8 @@ def test_suggest_batch(client, session):
|
||||||
json={
|
json={
|
||||||
"from_date": "2026-03-03",
|
"from_date": "2026-03-03",
|
||||||
"to_date": "2026-03-04",
|
"to_date": "2026-03-04",
|
||||||
"minimize_products": True
|
"minimize_products": True,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
data = r.json()
|
data = r.json()
|
||||||
|
|
@ -260,16 +273,18 @@ def test_suggest_batch(client, session):
|
||||||
assert data["days"][0]["date"] == "2026-03-03"
|
assert data["days"][0]["date"] == "2026-03-03"
|
||||||
assert data["overall_reasoning"] == "batch test"
|
assert data["overall_reasoning"] == "batch test"
|
||||||
|
|
||||||
|
|
||||||
def test_suggest_batch_invalid_date_range(client):
|
def test_suggest_batch_invalid_date_range(client):
|
||||||
r = client.post(
|
r = client.post(
|
||||||
"/routines/suggest-batch",
|
"/routines/suggest-batch",
|
||||||
json={"from_date": "2026-03-04", "to_date": "2026-03-03"}
|
json={"from_date": "2026-03-04", "to_date": "2026-03-03"},
|
||||||
)
|
)
|
||||||
assert r.status_code == 400
|
assert r.status_code == 400
|
||||||
|
|
||||||
|
|
||||||
def test_suggest_batch_too_long(client):
|
def test_suggest_batch_too_long(client):
|
||||||
r = client.post(
|
r = client.post(
|
||||||
"/routines/suggest-batch",
|
"/routines/suggest-batch",
|
||||||
json={"from_date": "2026-03-01", "to_date": "2026-03-20"}
|
json={"from_date": "2026-03-01", "to_date": "2026-03-20"},
|
||||||
)
|
)
|
||||||
assert r.status_code == 400
|
assert r.status_code == 400
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
from datetime import date, timedelta
|
from datetime import date, timedelta
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
import pytest
|
|
||||||
from sqlmodel import Session
|
from sqlmodel import Session
|
||||||
|
|
||||||
from innercontext.api.routines import (
|
from innercontext.api.routines import (
|
||||||
|
|
@ -23,7 +22,6 @@ from innercontext.models import (
|
||||||
RoutineStep,
|
RoutineStep,
|
||||||
ProductInventory,
|
ProductInventory,
|
||||||
)
|
)
|
||||||
from innercontext.models.enums import PartOfDay, GroomingAction
|
|
||||||
|
|
||||||
|
|
||||||
def test_contains_minoxidil_text():
|
def test_contains_minoxidil_text():
|
||||||
|
|
@ -89,7 +87,7 @@ def test_build_skin_context(session: Session):
|
||||||
barrier_state="intact",
|
barrier_state="intact",
|
||||||
active_concerns=["acne", "dryness"],
|
active_concerns=["acne", "dryness"],
|
||||||
priorities=["hydration"],
|
priorities=["hydration"],
|
||||||
notes="Feeling good"
|
notes="Feeling good",
|
||||||
)
|
)
|
||||||
session.add(snap)
|
session.add(snap)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
@ -108,10 +106,7 @@ def test_build_grooming_context(session: Session):
|
||||||
assert _build_grooming_context(session) == "GROOMING SCHEDULE: none\n"
|
assert _build_grooming_context(session) == "GROOMING SCHEDULE: none\n"
|
||||||
|
|
||||||
sch = GroomingSchedule(
|
sch = GroomingSchedule(
|
||||||
id=uuid.uuid4(),
|
id=uuid.uuid4(), day_of_week=0, action="shaving_oneblade", notes="Morning"
|
||||||
day_of_week=0,
|
|
||||||
action="shaving_oneblade",
|
|
||||||
notes="Morning"
|
|
||||||
)
|
)
|
||||||
session.add(sch)
|
session.add(sch)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
@ -121,27 +116,35 @@ def test_build_grooming_context(session: Session):
|
||||||
assert "poniedziałek: shaving_oneblade (Morning)" in ctx
|
assert "poniedziałek: shaving_oneblade (Morning)" in ctx
|
||||||
|
|
||||||
# Test weekdays filter
|
# Test weekdays filter
|
||||||
ctx2 = _build_grooming_context(session, weekdays=[1]) # not monday
|
ctx2 = _build_grooming_context(session, weekdays=[1]) # not monday
|
||||||
assert "(no entries for specified days)" in ctx2
|
assert "(no entries for specified days)" in ctx2
|
||||||
|
|
||||||
|
|
||||||
def test_build_recent_history(session: Session):
|
def test_build_recent_history(session: Session):
|
||||||
assert _build_recent_history(session) == "RECENT ROUTINES: none\n"
|
assert _build_recent_history(session) == "RECENT ROUTINES: none\n"
|
||||||
|
|
||||||
r = Routine(
|
r = Routine(id=uuid.uuid4(), routine_date=date.today(), part_of_day="am")
|
||||||
id=uuid.uuid4(),
|
|
||||||
routine_date=date.today(),
|
|
||||||
part_of_day="am"
|
|
||||||
)
|
|
||||||
session.add(r)
|
session.add(r)
|
||||||
p = Product(id=uuid.uuid4(), name="Cleanser", category="cleanser", brand="Test", recommended_time="both", leave_on=False, product_effect_profile={})
|
p = Product(
|
||||||
|
id=uuid.uuid4(),
|
||||||
|
name="Cleanser",
|
||||||
|
category="cleanser",
|
||||||
|
brand="Test",
|
||||||
|
recommended_time="both",
|
||||||
|
leave_on=False,
|
||||||
|
product_effect_profile={},
|
||||||
|
)
|
||||||
session.add(p)
|
session.add(p)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
s1 = RoutineStep(id=uuid.uuid4(), routine_id=r.id, order_index=1, product_id=p.id)
|
s1 = RoutineStep(id=uuid.uuid4(), routine_id=r.id, order_index=1, product_id=p.id)
|
||||||
s2 = RoutineStep(id=uuid.uuid4(), routine_id=r.id, order_index=2, action_type="shaving_razor")
|
s2 = RoutineStep(
|
||||||
|
id=uuid.uuid4(), routine_id=r.id, order_index=2, action_type="shaving_razor"
|
||||||
|
)
|
||||||
# Step with non-existent product
|
# Step with non-existent product
|
||||||
s3 = RoutineStep(id=uuid.uuid4(), routine_id=r.id, order_index=3, product_id=uuid.uuid4())
|
s3 = RoutineStep(
|
||||||
|
id=uuid.uuid4(), routine_id=r.id, order_index=3, product_id=uuid.uuid4()
|
||||||
|
)
|
||||||
|
|
||||||
session.add_all([s1, s2, s3])
|
session.add_all([s1, s2, s3])
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
@ -160,19 +163,24 @@ def test_build_products_context(session: Session):
|
||||||
name="Regaine",
|
name="Regaine",
|
||||||
category="serum",
|
category="serum",
|
||||||
is_medication=True,
|
is_medication=True,
|
||||||
brand="J&J", recommended_time="both", leave_on=True, product_effect_profile={}
|
brand="J&J",
|
||||||
|
recommended_time="both",
|
||||||
|
leave_on=True,
|
||||||
|
product_effect_profile={},
|
||||||
)
|
)
|
||||||
p2 = Product(
|
p2 = Product(
|
||||||
id=uuid.uuid4(),
|
id=uuid.uuid4(),
|
||||||
name="Sunscreen",
|
name="Sunscreen",
|
||||||
category="spf", brand="Test", leave_on=True,
|
category="spf",
|
||||||
|
brand="Test",
|
||||||
|
leave_on=True,
|
||||||
recommended_time="am",
|
recommended_time="am",
|
||||||
pao_months=6,
|
pao_months=6,
|
||||||
product_effect_profile={"hydration_immediate": 2, "exfoliation_strength": 0},
|
product_effect_profile={"hydration_immediate": 2, "exfoliation_strength": 0},
|
||||||
incompatible_with=[{"target": "retinol", "scope": "same_routine"}],
|
incompatible_with=[{"target": "retinol", "scope": "same_routine"}],
|
||||||
context_rules={"safe_after_shaving": False},
|
context_rules={"safe_after_shaving": False},
|
||||||
min_interval_hours=12,
|
min_interval_hours=12,
|
||||||
max_frequency_per_week=7
|
max_frequency_per_week=7,
|
||||||
)
|
)
|
||||||
session.add_all([p1, p2])
|
session.add_all([p1, p2])
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
@ -183,13 +191,9 @@ def test_build_products_context(session: Session):
|
||||||
product_id=p2.id,
|
product_id=p2.id,
|
||||||
is_opened=True,
|
is_opened=True,
|
||||||
opened_at=date.today() - timedelta(days=10),
|
opened_at=date.today() - timedelta(days=10),
|
||||||
expiry_date=date.today() + timedelta(days=365)
|
expiry_date=date.today() + timedelta(days=365),
|
||||||
)
|
|
||||||
inv2 = ProductInventory(
|
|
||||||
id=uuid.uuid4(),
|
|
||||||
product_id=p2.id,
|
|
||||||
is_opened=False
|
|
||||||
)
|
)
|
||||||
|
inv2 = ProductInventory(id=uuid.uuid4(), product_id=p2.id, is_opened=False)
|
||||||
session.add_all([inv1, inv2])
|
session.add_all([inv1, inv2])
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
|
|
@ -201,16 +205,20 @@ def test_build_products_context(session: Session):
|
||||||
session.add(s)
|
session.add(s)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
ctx = _build_products_context(session, time_filter="am", reference_date=date.today())
|
ctx = _build_products_context(
|
||||||
|
session, time_filter="am", reference_date=date.today()
|
||||||
|
)
|
||||||
# p1 is medication but not minoxidil (wait, Regaine name doesn't contain minoxidil!) -> skipped
|
# p1 is medication but not minoxidil (wait, Regaine name doesn't contain minoxidil!) -> skipped
|
||||||
assert "Regaine" not in ctx
|
assert "Regaine" not in ctx
|
||||||
|
|
||||||
# Let's fix p1 to be minoxidil
|
# Let's fix p1 to be minoxidil
|
||||||
p1.name = "Regaine Minoxidil"
|
p1.name = "Regaine Minoxidil"
|
||||||
session.add(p1)
|
session.add(p1)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
ctx = _build_products_context(session, time_filter="am", reference_date=date.today())
|
ctx = _build_products_context(
|
||||||
|
session, time_filter="am", reference_date=date.today()
|
||||||
|
)
|
||||||
assert "Regaine Minoxidil" in ctx
|
assert "Regaine Minoxidil" in ctx
|
||||||
assert "Sunscreen" in ctx
|
assert "Sunscreen" in ctx
|
||||||
assert "inventory_status={active:2,opened:1,sealed:1}" in ctx
|
assert "inventory_status={active:2,opened:1,sealed:1}" in ctx
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue