""" 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"