import datetime import pytest_asyncio from fooder.command.save_meal_as_preset import save_meal_as_preset TODAY = datetime.date.today().isoformat() @pytest_asyncio.fixture async def preset(auth_ctx, meal, entry): async with auth_ctx.repo.transaction(): obj = await save_meal_as_preset(auth_ctx, meal) await auth_ctx.repo.preset.session.refresh(obj) return obj @pytest_asyncio.fixture async def preset_entry(preset): return preset.entries[0] # --- save meal as preset --- async def test_save_meal_as_preset_returns_201(auth_client, meal, entry): response = await auth_client.post( f"/api/diary/{TODAY}/meal/{meal.id}/preset", json={} ) assert response.status_code == 201 async def test_save_meal_as_preset_returns_preset_name(auth_client, meal, entry): response = await auth_client.post( f"/api/diary/{TODAY}/meal/{meal.id}/preset", json={} ) assert response.json()["name"] == meal.name async def test_save_meal_as_preset_overrides_name(auth_client, meal, entry): response = await auth_client.post( f"/api/diary/{TODAY}/meal/{meal.id}/preset", json={"name": "My Custom Preset"} ) assert response.json()["name"] == "My Custom Preset" async def test_save_meal_as_preset_copies_entries(auth_client, meal, entry): response = await auth_client.post( f"/api/diary/{TODAY}/meal/{meal.id}/preset", json={} ) body = response.json() assert len(body["entries"]) == 1 assert body["entries"][0]["grams"] == entry.grams assert body["entries"][0]["product_id"] == entry.product_id async def test_save_empty_meal_as_preset_has_no_entries(auth_client, meal): response = await auth_client.post( f"/api/diary/{TODAY}/meal/{meal.id}/preset", json={} ) assert response.status_code == 201 assert response.json()["entries"] == [] async def test_save_meal_as_preset_meal_not_found_returns_404(auth_client, diary): response = await auth_client.post(f"/api/diary/{TODAY}/meal/99999/preset", json={}) assert response.status_code == 404 async def test_save_meal_as_preset_without_auth_returns_401(client, meal): response = await client.post(f"/api/diary/{TODAY}/meal/{meal.id}/preset", json={}) assert response.status_code == 401 # --- list presets --- async def test_list_presets_returns_200(auth_client): response = await auth_client.get("/api/preset") assert response.status_code == 200 assert isinstance(response.json(), list) async def test_list_presets_contains_saved(auth_client, preset): response = await auth_client.get("/api/preset") ids = [p["id"] for p in response.json()] assert preset.id in ids async def test_list_presets_without_auth_returns_401(client): response = await client.get("/api/preset") assert response.status_code == 401 # --- create preset --- async def test_create_preset_returns_201(auth_client): response = await auth_client.post("/api/preset/", json={"name": "Preset name"}) assert response.status_code == 201 async def test_create_preset_sets_name(auth_client): response = await auth_client.post("/api/preset/", json={"name": "Preset name"}) assert response.status_code == 201 assert response.json()["name"] == "Preset name" async def test_create_preset_without_auth_returns_401(client): response = await client.post("/api/preset/", json={"name": "x"}) assert response.status_code == 401 # --- update preset --- async def test_update_preset_returns_200(auth_client, preset): response = await auth_client.patch( f"/api/preset/{preset.id}", json={"name": "Renamed"} ) assert response.status_code == 200 async def test_update_preset_changes_name(auth_client, preset): response = await auth_client.patch( f"/api/preset/{preset.id}", json={"name": "Renamed"} ) assert response.json()["name"] == "Renamed" async def test_update_preset_not_found_returns_404(auth_client): response = await auth_client.patch("/api/preset/99999", json={"name": "Ghost"}) assert response.status_code == 404 async def test_update_preset_without_auth_returns_401(client, preset): response = await client.patch(f"/api/preset/{preset.id}", json={"name": "x"}) assert response.status_code == 401 # --- delete preset --- async def test_delete_preset_returns_204(auth_client, preset): response = await auth_client.delete(f"/api/preset/{preset.id}") assert response.status_code == 204 async def test_delete_preset_not_found_returns_404(auth_client): response = await auth_client.delete("/api/preset/99999") assert response.status_code == 404 async def test_delete_preset_without_auth_returns_401(client, preset): response = await client.delete(f"/api/preset/{preset.id}") assert response.status_code == 401 # --- create preset entry --- async def test_create_preset_entry_returns_201(auth_client, preset, product): response = await auth_client.post( f"/api/preset/{preset.id}/entry", json={"grams": 200.0, "product_id": product.id}, ) assert response.status_code == 201 async def test_create_preset_entry_returns_correct_grams(auth_client, preset, product): response = await auth_client.post( f"/api/preset/{preset.id}/entry", json={"grams": 200.0, "product_id": product.id}, ) assert response.json()["grams"] == 200.0 async def test_create_preset_entry_preset_not_found_returns_404(auth_client, product): response = await auth_client.post( "/api/preset/99999/entry", json={"grams": 100.0, "product_id": product.id} ) assert response.status_code == 404 async def test_create_preset_entry_without_auth_returns_401(client, preset, product): response = await client.post( f"/api/preset/{preset.id}/entry", json={"grams": 100.0, "product_id": product.id}, ) assert response.status_code == 401 # --- update preset entry --- async def test_update_preset_entry_returns_200(auth_client, preset, preset_entry): response = await auth_client.patch( f"/api/preset/{preset.id}/entry/{preset_entry.id}", json={"grams": 250.0}, ) assert response.status_code == 200 async def test_update_preset_entry_changes_grams(auth_client, preset, preset_entry): response = await auth_client.patch( f"/api/preset/{preset.id}/entry/{preset_entry.id}", json={"grams": 250.0}, ) assert response.json()["grams"] == 250.0 async def test_update_preset_entry_not_found_returns_404(auth_client, preset): response = await auth_client.patch( f"/api/preset/{preset.id}/entry/99999", json={"grams": 100.0} ) assert response.status_code == 404 async def test_update_preset_entry_without_auth_returns_401( client, preset, preset_entry ): response = await client.patch( f"/api/preset/{preset.id}/entry/{preset_entry.id}", json={"grams": 100.0}, ) assert response.status_code == 401 # --- delete preset entry --- async def test_delete_preset_entry_returns_204(auth_client, preset, preset_entry): response = await auth_client.delete( f"/api/preset/{preset.id}/entry/{preset_entry.id}" ) assert response.status_code == 204 async def test_delete_preset_entry_not_found_returns_404(auth_client, preset): response = await auth_client.delete(f"/api/preset/{preset.id}/entry/99999") assert response.status_code == 404 async def test_delete_preset_entry_without_auth_returns_401( client, preset, preset_entry ): response = await client.delete(f"/api/preset/{preset.id}/entry/{preset_entry.id}") assert response.status_code == 401 # --- load preset as meal --- async def test_load_preset_as_meal_returns_201(auth_client, diary, preset): response = await auth_client.post( f"/api/diary/{TODAY}/meal/from_preset", json={"preset_id": preset.id} ) assert response.status_code == 201 async def test_load_preset_as_meal_uses_preset_name(auth_client, diary, preset): response = await auth_client.post( f"/api/diary/{TODAY}/meal/from_preset", json={"preset_id": preset.id} ) assert response.json()["name"] == preset.name async def test_load_preset_as_meal_overrides_name(auth_client, diary, preset): response = await auth_client.post( f"/api/diary/{TODAY}/meal/from_preset", json={"preset_id": preset.id, "name": "Custom Name"}, ) assert response.json()["name"] == "Custom Name" async def test_load_preset_as_meal_copies_entries(auth_client, diary, preset): response = await auth_client.post( f"/api/diary/{TODAY}/meal/from_preset", json={"preset_id": preset.id} ) body = response.json() assert len(body["entries"]) == len(preset.entries) assert body["entries"][0]["grams"] == preset.entries[0].grams assert body["entries"][0]["product_id"] == preset.entries[0].product_id async def test_load_preset_as_meal_diary_not_found_returns_404(auth_client, preset): response = await auth_client.post( "/api/diary/2000-01-01/meal/from_preset", json={"preset_id": preset.id} ) assert response.status_code == 404 async def test_load_preset_as_meal_preset_not_found_returns_404(auth_client, diary): response = await auth_client.post( f"/api/diary/{TODAY}/meal/from_preset", json={"preset_id": 99999} ) assert response.status_code == 404 async def test_load_preset_as_meal_without_auth_returns_401(client, preset): response = await client.post( f"/api/diary/{TODAY}/meal/from_preset", json={"preset_id": preset.id} ) assert response.status_code == 401