venthrive-api / tests /test_niche_requests.py
GitHub Actions
Sync from GitHub 路 2026-10-22 20:43 UTC
89a70e2
Raw History Blame Contribute Delete
3.13 kB
"""
Unit tests for utils/niche_requests.py and the /niche-request route: the list of
niches people couldn't find. Firestore is mocked.
"""
from unittest.mock import MagicMock, patch
import pytest
from fastapi import HTTPException
from utils import niche_requests
from routes.bff import NicheRequestIn, niche_request
def test_key_ignores_case_spacing_and_punctuation():
assert niche_requests.niche_key(" School Stationery! ") == "school-stationery"
assert niche_requests.niche_key("school stationery") == "school-stationery"
assert niche_requests.niche_key("!!!") == ""
def test_route_rejects_text_without_letters():
with pytest.raises(HTTPException) as e:
niche_request(NicheRequestIn(text="!!!"), user={"uid": "u1"})
assert e.value.status_code == 400
def test_list_hides_who_asked_and_sorts_by_count():
def doc(id_, **d):
m = MagicMock(id=id_)
m.to_dict.return_value = d
return m
db = MagicMock()
db.collection.return_value.stream.return_value = [
doc("a", text="A", userCount=1, uids=["u1"], status="open"),
doc("b", text="B", userCount=3, uids=["u1", "u2", "u3"], status="open"),
doc("c", text="C", userCount=9, uids=["x"], status="added"),
]
with patch.object(niche_requests.firestore, "client", return_value=db):
rows = niche_requests.list_requests("open")
assert [r["text"] for r in rows] == ["B", "A"]
assert all("uids" not in r for r in rows)
def test_set_status_validates():
with pytest.raises(ValueError):
niche_requests.set_status("x", "deleted")
def _fake_firestore(existing: dict | None):
fs = MagicMock()
fs.transactional = lambda f: f # run the body directly with our fake transaction
snap = MagicMock(exists=existing is not None)
snap.to_dict.return_value = existing or {}
ref = fs.client.return_value.collection.return_value.document.return_value
ref.get.return_value = snap
tx = fs.client.return_value.transaction.return_value
return fs, ref, tx
def test_record_counts_each_person_once_and_keeps_where_they_put_it():
fs, ref, tx = _fake_firestore({"uids": ["u1"], "sectors": ["trade_commerce/retail_trade"], "status": "added"})
with patch.object(niche_requests, "firestore", fs):
key = niche_requests.record("u1", "School stationery", "trade_commerce", "retail_trade")
assert key == "school-stationery"
saved = tx.set.call_args[0][1]
assert saved["userCount"] == 1 and saved["uids"] == ["u1"]
assert saved["sectors"] == ["trade_commerce/retail_trade"]
assert saved["status"] == "added" # an admin decision isn't reset by a new request
assert saved["text"] == "School stationery"
assert "firstAt" not in saved
def test_record_new_niche_starts_open_with_one_person():
fs, ref, tx = _fake_firestore(None)
with patch.object(niche_requests, "firestore", fs):
niche_requests.record("u2", "Shoe repair")
saved = tx.set.call_args[0][1]
assert saved["userCount"] == 1 and saved["status"] == "open" and "firstAt" in saved
assert saved["sectors"] == []