venthrive-api / tests /test_account.py
GitHub Actions
Sync from GitHub 路 2026-09-24 23:37 UTC
889e86b
Raw History Blame Contribute Delete
3.37 kB
"""
Unit tests for routes/account.py's self-delete cascade.
Scope: verifies delete_all_user_data's Firestore traversal logic (every business's
subcollections, xpHistory, the root doc) using a fake Firestore client, per
docs/qa/test-strategy.md's unit layer. The actual Firebase Auth deletion
(fb_auth.delete_user) and the FastAPI route wiring are integration-level concerns,
not covered here.
"""
from unittest.mock import MagicMock
from routes.account import delete_all_user_data
def _make_fake_db():
"""
Builds a fake Firestore client deep enough to exercise delete_all_user_data:
one business with two subcollections each holding one doc, plus one
xpHistory entry. Returns (db, deleted_refs) where deleted_refs collects
every .delete() call made, in call order.
"""
deleted = []
def make_doc(name):
doc = MagicMock(name=f"doc:{name}")
doc.reference = MagicMock(name=f"ref:{name}")
doc.reference.delete = MagicMock(side_effect=lambda n=name: deleted.append(n))
return doc
biz_doc = make_doc("business:biz1")
def sub_collection(name):
coll = MagicMock(name=f"collection:{name}")
coll.stream = MagicMock(return_value=iter([make_doc(f"{name}:item1")]))
return coll
biz_doc.reference.collection = MagicMock(side_effect=sub_collection)
businesses_collection = MagicMock(name="collection:businesses")
businesses_collection.stream = MagicMock(return_value=iter([biz_doc]))
xp_history_collection = MagicMock(name="collection:xpHistory")
xp_history_collection.stream = MagicMock(return_value=iter([make_doc("xpHistory:entry1")]))
user_ref = MagicMock(name="ref:user_data/uid")
user_ref.delete = MagicMock(side_effect=lambda: deleted.append("user_data/uid"))
def user_ref_collection(name):
return {"businesses": businesses_collection, "xpHistory": xp_history_collection}[name]
user_ref.collection = MagicMock(side_effect=user_ref_collection)
user_data_collection = MagicMock(name="collection:user_data")
user_data_collection.document = MagicMock(return_value=user_ref)
db = MagicMock(name="firestore_client")
db.collection = MagicMock(return_value=user_data_collection)
return db, deleted
def test_deletes_every_business_subcollection_doc_and_the_business_itself(monkeypatch):
db, deleted = _make_fake_db()
monkeypatch.setattr("routes.account.firestore.client", lambda: db)
delete_all_user_data("some-uid")
# Every one of the 7 known subcollections was consulted for the business...
biz_doc = db.collection().document().collection("businesses").stream.return_value
# ...and each subcollection's one doc, plus the business doc itself, got deleted.
assert "bff:item1" in deleted
assert "documents:item1" in deleted
assert "team:item1" in deleted
assert "business:biz1" in deleted
def test_deletes_xp_history_entries(monkeypatch):
db, deleted = _make_fake_db()
monkeypatch.setattr("routes.account.firestore.client", lambda: db)
delete_all_user_data("some-uid")
assert "xpHistory:entry1" in deleted
def test_deletes_the_root_user_doc_last(monkeypatch):
db, deleted = _make_fake_db()
monkeypatch.setattr("routes.account.firestore.client", lambda: db)
delete_all_user_data("some-uid")
assert deleted[-1] == "user_data/uid"