"""Tests for POST /api/recipes/{id}/duplicate (#52).""" from httpx import AsyncClient from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from src.backend.models.orm.recipe import Recipe, RecipeVersion from src.backend.models.orm.task import RecipeSubtask, RecipeTask from src.backend.models.orm.user import User from src.backend.tests.conftest import auth_headers, create_test_recipe class TestDuplicateRecipe: async def test_duplicate_copies_tasks_and_keeps_original( self, client: AsyncClient, maker_user: User, db_session: AsyncSession ): src = await create_test_recipe(db_session, maker_user.id) src_id = src.id before_tasks = (await db_session.execute(select(func.count(RecipeTask.id)))).scalar_one() before_subs = (await db_session.execute(select(func.count(RecipeSubtask.id)))).scalar_one() resp = await client.post( f"/api/recipes/{src_id}/duplicate", json={"code": "REC-COPIA", "name": "Copia"}, headers=auth_headers(maker_user), ) assert resp.status_code == 201 data = resp.json() assert data["code"] == "REC-COPIA" and data["name"] == "Copia" assert data["id"] != src_id assert data["description"] == "A recipe for testing" assert data["current_version"]["version_number"] == 1 # Tasks and subtasks doubled: copied, not moved after_tasks = (await db_session.execute(select(func.count(RecipeTask.id)))).scalar_one() after_subs = (await db_session.execute(select(func.count(RecipeSubtask.id)))).scalar_one() assert after_tasks == before_tasks * 2 assert after_subs == before_subs * 2 new_version = (await db_session.execute( select(RecipeVersion).where(RecipeVersion.recipe_id == data["id"]) )).scalar_one() new_tasks = (await db_session.execute( select(RecipeTask).where(RecipeTask.version_id == new_version.id) )).scalars().all() assert len(new_tasks) == before_tasks # Original unchanged orig = (await db_session.execute(select(Recipe).where(Recipe.id == src_id))).scalar_one() assert orig.code == "REC-001" and orig.name == "Test Recipe" orig_versions = (await db_session.execute( select(func.count(RecipeVersion.id)).where(RecipeVersion.recipe_id == src_id) )).scalar_one() assert orig_versions == 1 async def test_duplicate_code_conflict( self, client: AsyncClient, maker_user: User, db_session: AsyncSession ): src = await create_test_recipe(db_session, maker_user.id) resp = await client.post( f"/api/recipes/{src.id}/duplicate", json={"code": "REC-001", "name": "X"}, headers=auth_headers(maker_user), ) assert resp.status_code == 409 async def test_duplicate_missing_recipe( self, client: AsyncClient, maker_user: User ): resp = await client.post( "/api/recipes/99999/duplicate", json={"code": "NEW", "name": "X"}, headers=auth_headers(maker_user), ) assert resp.status_code == 404