88 lines
2.9 KiB
Python
88 lines
2.9 KiB
Python
import pytest
|
|
from fastapi.testclient import TestClient
|
|
from app.db import get_engine, make_session_factory, init_db
|
|
from app.main import create_app
|
|
|
|
|
|
@pytest.fixture()
|
|
def client():
|
|
engine = get_engine("sqlite:///:memory:")
|
|
init_db(engine)
|
|
SessionLocal = make_session_factory(engine)
|
|
app = create_app(SessionLocal)
|
|
return TestClient(app)
|
|
|
|
|
|
def test_create_item_returns_201(client):
|
|
resp = client.post("/items", json={
|
|
"modality": "bh_email",
|
|
"raw_content": "Books to donate",
|
|
"captured_at": "2026-07-13T07:00:00Z",
|
|
"discord_message_id": "abc-1",
|
|
})
|
|
assert resp.status_code == 201
|
|
body = resp.json()
|
|
assert body["stage"] == "new"
|
|
assert body["modality"] == "bh_email"
|
|
|
|
|
|
def test_create_item_idempotent_returns_200(client):
|
|
payload = {
|
|
"modality": "bh_email", "raw_content": "x",
|
|
"captured_at": "2026-07-13T07:00:00Z", "discord_message_id": "dup-9",
|
|
}
|
|
first = client.post("/items", json=payload)
|
|
second = client.post("/items", json=payload)
|
|
assert first.status_code == 201
|
|
assert second.status_code == 200
|
|
assert first.json()["id"] == second.json()["id"]
|
|
|
|
|
|
def test_list_items_excludes_done_by_default(client):
|
|
resp = client.post("/items", json={
|
|
"modality": "voice", "raw_content": "call note",
|
|
"captured_at": "2026-07-13T07:00:00Z", "discord_message_id": "v-1",
|
|
})
|
|
item_id = resp.json()["id"]
|
|
client.patch(f"/items/{item_id}", json={"type": "other"})
|
|
client.patch(f"/items/{item_id}", json={"stage": "done"})
|
|
|
|
listed = client.get("/items").json()
|
|
assert item_id not in [i["id"] for i in listed]
|
|
|
|
listed_all = client.get("/items?include_done=true").json()
|
|
assert item_id in [i["id"] for i in listed_all]
|
|
|
|
|
|
def test_patch_invalid_stage_returns_422(client):
|
|
resp = client.post("/items", json={
|
|
"modality": "voice", "raw_content": "x",
|
|
"captured_at": "2026-07-13T07:00:00Z", "discord_message_id": "v-2",
|
|
})
|
|
item_id = resp.json()["id"]
|
|
client.patch(f"/items/{item_id}", json={"type": "other"})
|
|
bad = client.patch(f"/items/{item_id}", json={"stage": "pickup_scheduled"})
|
|
assert bad.status_code == 422
|
|
|
|
|
|
def test_get_missing_item_returns_404(client):
|
|
resp = client.get("/items/999999")
|
|
assert resp.status_code == 404
|
|
|
|
|
|
def test_create_item_with_outbound_direction(client):
|
|
resp = client.post("/items", json={
|
|
"modality": "lead_found", "raw_content": "found on Nextdoor",
|
|
"captured_at": "2026-07-13T07:00:00Z", "discord_message_id": "out-1",
|
|
"direction": "outbound",
|
|
})
|
|
assert resp.status_code == 201
|
|
assert resp.json()["direction"] == "outbound"
|
|
|
|
|
|
def test_create_item_direction_defaults_to_inbound(client):
|
|
resp = client.post("/items", json={
|
|
"modality": "voice", "raw_content": "call",
|
|
"captured_at": "2026-07-13T07:00:00Z", "discord_message_id": "out-2",
|
|
})
|
|
assert resp.json()["direction"] == "inbound"
|