97 lines
3.5 KiB
Python
97 lines
3.5 KiB
Python
from datetime import datetime, timezone
|
|
import pytest
|
|
from app import crud
|
|
|
|
|
|
def _now():
|
|
return datetime.now(timezone.utc)
|
|
|
|
|
|
def test_create_item_sets_defaults(db_session):
|
|
item, created = crud.create_item(
|
|
db_session,
|
|
modality="bh_email",
|
|
raw_content="Hi, I have books to donate",
|
|
captured_at=_now(),
|
|
discord_message_id="msg-1",
|
|
)
|
|
assert created is True
|
|
assert item.id is not None
|
|
assert item.stage == "new"
|
|
assert item.type is None
|
|
|
|
|
|
def test_create_item_is_idempotent_by_discord_message_id(db_session):
|
|
first, first_created = crud.create_item(
|
|
db_session, modality="bh_email", raw_content="a", captured_at=_now(),
|
|
discord_message_id="dup-1",
|
|
)
|
|
second, second_created = crud.create_item(
|
|
db_session, modality="bh_email", raw_content="b (should be ignored)",
|
|
captured_at=_now(), discord_message_id="dup-1",
|
|
)
|
|
assert first_created is True
|
|
assert second_created is False
|
|
assert second.id == first.id
|
|
assert second.raw_content == "a"
|
|
|
|
|
|
def test_list_items_excludes_done_by_default(db_session):
|
|
crud.create_item(db_session, modality="voice", raw_content="x", captured_at=_now(),
|
|
discord_message_id="m1")
|
|
done_item, _ = crud.create_item(db_session, modality="voice", raw_content="y",
|
|
captured_at=_now(), discord_message_id="m2")
|
|
crud.update_item(db_session, done_item.id, type="other", stage="new")
|
|
crud.update_item(db_session, done_item.id, stage="done")
|
|
|
|
results = crud.list_items(db_session)
|
|
assert done_item.id not in [i.id for i in results]
|
|
|
|
results_with_done = crud.list_items(db_session, include_done=True)
|
|
assert done_item.id in [i.id for i in results_with_done]
|
|
|
|
|
|
def test_update_item_rejects_invalid_stage_for_type(db_session):
|
|
item, _ = crud.create_item(db_session, modality="voice", raw_content="x",
|
|
captured_at=_now(), discord_message_id="m3")
|
|
crud.update_item(db_session, item.id, type="other")
|
|
with pytest.raises(ValueError):
|
|
crud.update_item(db_session, item.id, stage="pickup_scheduled")
|
|
|
|
|
|
def test_update_item_returns_none_for_missing_id(db_session):
|
|
assert crud.update_item(db_session, 9999, notes="x") is None
|
|
|
|
|
|
def test_create_item_defaults_direction_to_inbound(db_session):
|
|
item, _ = crud.create_item(
|
|
db_session, modality="bh_email", raw_content="x", captured_at=_now(),
|
|
discord_message_id="dir-1",
|
|
)
|
|
assert item.direction == "inbound"
|
|
|
|
|
|
def test_create_item_accepts_outbound_direction(db_session):
|
|
item, _ = crud.create_item(
|
|
db_session, modality="lead_found", raw_content="found post", captured_at=_now(),
|
|
discord_message_id="dir-2", direction="outbound",
|
|
)
|
|
assert item.direction == "outbound"
|
|
|
|
|
|
def test_update_item_validates_stage_against_outbound_direction(db_session):
|
|
item, _ = crud.create_item(
|
|
db_session, modality="lead_found", raw_content="x", captured_at=_now(),
|
|
discord_message_id="dir-3", direction="outbound",
|
|
)
|
|
updated = crud.update_item(db_session, item.id, stage="outreach_sent")
|
|
assert updated.stage == "outreach_sent"
|
|
|
|
|
|
def test_update_item_rejects_inbound_only_stage_for_outbound_item(db_session):
|
|
item, _ = crud.create_item(
|
|
db_session, modality="lead_found", raw_content="x", captured_at=_now(),
|
|
discord_message_id="dir-4", direction="outbound",
|
|
)
|
|
with pytest.raises(ValueError):
|
|
crud.update_item(db_session, item.id, stage="done")
|