from typing import Callable import importlib import unittest from fastapi.testclient import TestClient from db import connect, create import main import tests.test_data as test_data def reload_test_data(): global test_data test_data = importlib.reload(test_data) @unittest.skip("Legacy v1 shopping API removed; see v2 household-scoped tests.") class TestShoppingAPI(unittest.IsolatedAsyncioTestCase): async def asyncSetUp(self): self.conn = await connect(":memory:") await create(self.conn) await test_data.create_test_data(self.conn) reload_test_data() async def override_get_db(): try: yield self.conn finally: pass main.app.dependency_overrides[main.get_db] = override_get_db self.client = TestClient(main.app) return await super().asyncSetUp() async def asyncTearDown(self) -> None: await self.conn.close() main.app.dependency_overrides.clear() return await super().asyncTearDown() def test_purchase_unauthorized_without_cookie(self): # Do NOT override cookie_person; no cookie provided => 401 body = {"storeName": "woolworths", "items": []} resp = self.client.post("/api/v1/shopping", json=body) assert resp.status_code == 401 assert "application/problem+json" in resp.headers.get("content-type", "") prob = resp.json() assert prob.get("status") == 401 assert prob.get("title") def test_purchase_validation_error_returns_problem(self): # Override cookie_person to simulate authenticated user async def override_cookie_person(): return test_data.MemberRefs.jacob main.app.dependency_overrides[main.cookie_person] = override_cookie_person # Empty items triggers domain validation error => 400 with Problem Details body = {"storeName": "woolworths", "items": []} resp = self.client.post("/api/v1/shopping", json=body) assert resp.status_code == 400 assert "application/problem+json" in resp.headers.get("content-type", "") prob = resp.json() assert prob.get("status") == 400 assert "items" in prob.get("title", "").lower() or prob.get("title") def test_request_ingredient_scoped( self, household_and_user: dict, auth_headers: dict, ingredient_factory: Callable, ): slug = household_and_user["household"]["slug"] ingredient = ingredient_factory() # Request an ingredient response = self.client.post( f"/households/{slug}/shopping/current/ingredients", headers=auth_headers, json={"ingredientId": ingredient.id}, ) assert response.status_code == 200 requested_item = response.json() assert requested_item["ingredientId"] == ingredient.id assert requested_item["mealId"] is None # Check that it appears in the outstanding list response = self.client.get(f"/households/{slug}/shopping/current", headers=auth_headers) assert response.status_code == 200 current_list = response.json() assert len(current_list["outstandingItems"]) == 1 assert current_list["outstandingItems"][0]["ingredientId"] == ingredient.id