From 14bdcbb202799c40fddc634db7926ec122990c38 Mon Sep 17 00:00:00 2001 From: jableader Date: Sun, 2 Nov 2025 18:54:04 +1100 Subject: [PATCH] load recipe ingredients --- api/recipes.py | 2 + tests/test_recipes_ingredients_loaded_v2.py | 96 +++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 tests/test_recipes_ingredients_loaded_v2.py diff --git a/api/recipes.py b/api/recipes.py index 6fab118..392e8eb 100644 --- a/api/recipes.py +++ b/api/recipes.py @@ -120,6 +120,8 @@ async def get_recipe( r = await recipes.find_recipe_by_id_scoped(conn, recipe_id, household["id"]) if not r: return error_response(None, 404, "Recipe not found") + # Ensure ingredients are loaded for single-recipe fetch + await recipes.load_recipe_ingredients(conn, r) # load creator display name mref = None from users.repository import get_by_id as get_user_by_id diff --git a/tests/test_recipes_ingredients_loaded_v2.py b/tests/test_recipes_ingredients_loaded_v2.py new file mode 100644 index 0000000..43aa2be --- /dev/null +++ b/tests/test_recipes_ingredients_loaded_v2.py @@ -0,0 +1,96 @@ +import unittest +from fastapi.testclient import TestClient + +import main +from db import connect, create + + +class TestRecipeIngredientsLoadedV2(unittest.IsolatedAsyncioTestCase): + async def asyncSetUp(self): + self.conn = await connect(":memory:") + await create(self.conn) + + 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) + + # Register a user and create household + r = self.client.post( + "/api/v1/auth/register", + json={"email": "ing@test.com", "password": "pw", "displayName": "ING"}, + ) + assert r.status_code == 200, r.text + self.headers = {"Authorization": f"Bearer {r.json()['accessToken']}"} + + r = self.client.post("/api/v1/households", headers=self.headers, json={"name": "H"}) + assert r.status_code == 200, r.text + self.slug = r.json()["slug"] + + async def asyncTearDown(self): + await self.conn.close() + main.app.dependency_overrides.clear() + + def _create_recipe(self): + recipe = { + "id": -1, + "name": "HasIngredients", + "link": "https://example.com/has", + "serves": 2, + "imageUrls": [], + "ingredients": [ + { + "id": 0, + "line": "2 Eggs", + "name": "Eggs", + "unit": "Items", + "quantity": 2, + "preparation": "", + "product": None, + }, + { + "id": 0, + "line": "1 tbsp Butter", + "name": "Butter", + "unit": "Tablespoon", + "quantity": 1, + "preparation": "", + "product": None, + }, + ], + } + r = self.client.post( + f"/api/v1/households/{self.slug}/recipes", headers=self.headers, json=recipe + ) + assert r.status_code == 200, r.text + return r.json()["id"], recipe + + def test_get_by_id_includes_ingredients(self): + rid, expected = self._create_recipe() + g = self.client.get( + f"/api/v1/households/{self.slug}/recipes/{rid}", headers=self.headers + ) + assert g.status_code == 200, g.text + body = g.json() + ings = body.get("ingredients", []) + assert len(ings) == 2 + lines = [i.get("line") for i in ings] + assert "2 Eggs" in lines and "1 tbsp Butter" in lines + + def test_list_includes_ingredients(self): + rid, expected = self._create_recipe() + lst = self.client.get( + f"/api/v1/households/{self.slug}/recipes", headers=self.headers + ) + assert lst.status_code == 200, lst.text + items = lst.json().get("items", []) + # Find our recipe + match = next(i for i in items if i["id"] == rid) + ings = match.get("ingredients", []) + assert len(ings) == 2 + lines = [i.get("line") for i in ings] + assert "2 Eggs" in lines and "1 tbsp Butter" in lines