"""Integration tests for bulk image operations.""" import pytest from httpx import AsyncClient from sqlalchemy.ext.asyncio import AsyncSession from uuid import uuid4 from app.database.models.user import User from app.database.models.board import Board from app.database.models.image import Image from app.database.models.board_image import BoardImage @pytest.mark.asyncio async def test_bulk_update_position_delta(client: AsyncClient, test_user: User, db: AsyncSession): """Test bulk updating positions with delta.""" # Create board board = Board( id=uuid4(), user_id=test_user.id, title="Test Board", viewport_state={"x": 0, "y": 0, "zoom": 1.0, "rotation": 0}, ) db.add(board) # Create images images = [] board_images = [] for i in range(3): image = Image( id=uuid4(), user_id=test_user.id, filename=f"test{i}.jpg", storage_path=f"{test_user.id}/test{i}.jpg", file_size=1024, mime_type="image/jpeg", width=800, height=600, metadata={"format": "jpeg", "checksum": f"abc{i}"}, ) db.add(image) images.append(image) board_image = BoardImage( id=uuid4(), board_id=board.id, image_id=image.id, position={"x": 100 * i, "y": 100 * i}, transformations={ "scale": 1.0, "rotation": 0, "opacity": 1.0, "flipped_h": False, "flipped_v": False, "greyscale": False, }, z_order=i, ) db.add(board_image) board_images.append(board_image) await db.commit() # Bulk update position response = await client.patch( f"/api/images/boards/{board.id}/images/bulk", json={ "image_ids": [str(img.id) for img in images[:2]], # First 2 images "position_delta": {"dx": 50, "dy": 75}, }, ) assert response.status_code == 200 data = response.json() assert data["updated_count"] == 2 assert data["failed_count"] == 0 @pytest.mark.asyncio async def test_bulk_update_transformations(client: AsyncClient, test_user: User, db: AsyncSession): """Test bulk updating transformations.""" board = Board( id=uuid4(), user_id=test_user.id, title="Test Board", viewport_state={"x": 0, "y": 0, "zoom": 1.0, "rotation": 0}, ) db.add(board) images = [] for i in range(2): image = Image( id=uuid4(), user_id=test_user.id, filename=f"test{i}.jpg", storage_path=f"{test_user.id}/test{i}.jpg", file_size=1024, mime_type="image/jpeg", width=800, height=600, metadata={"format": "jpeg", "checksum": f"abc{i}"}, ) db.add(image) images.append(image) board_image = BoardImage( id=uuid4(), board_id=board.id, image_id=image.id, position={"x": 100, "y": 100}, transformations={ "scale": 1.0, "rotation": 0, "opacity": 1.0, "flipped_h": False, "flipped_v": False, "greyscale": False, }, z_order=0, ) db.add(board_image) await db.commit() # Bulk update transformations response = await client.patch( f"/api/images/boards/{board.id}/images/bulk", json={ "image_ids": [str(img.id) for img in images], "transformations": { "scale": 2.0, "rotation": 45, "opacity": 0.8, }, }, ) assert response.status_code == 200 data = response.json() assert data["updated_count"] == 2 @pytest.mark.asyncio async def test_bulk_update_z_order_delta(client: AsyncClient, test_user: User, db: AsyncSession): """Test bulk updating Z-order with delta.""" board = Board( id=uuid4(), user_id=test_user.id, title="Test Board", viewport_state={"x": 0, "y": 0, "zoom": 1.0, "rotation": 0}, ) db.add(board) images = [] for i in range(3): image = Image( id=uuid4(), user_id=test_user.id, filename=f"test{i}.jpg", storage_path=f"{test_user.id}/test{i}.jpg", file_size=1024, mime_type="image/jpeg", width=800, height=600, metadata={"format": "jpeg", "checksum": f"abc{i}"}, ) db.add(image) images.append(image) board_image = BoardImage( id=uuid4(), board_id=board.id, image_id=image.id, position={"x": 100, "y": 100}, transformations={ "scale": 1.0, "rotation": 0, "opacity": 1.0, "flipped_h": False, "flipped_v": False, "greyscale": False, }, z_order=i, ) db.add(board_image) await db.commit() # Bulk update Z-order response = await client.patch( f"/api/images/boards/{board.id}/images/bulk", json={ "image_ids": [str(images[0].id), str(images[1].id)], "z_order_delta": 10, }, ) assert response.status_code == 200 data = response.json() assert data["updated_count"] == 2 @pytest.mark.asyncio async def test_bulk_update_mixed_operations(client: AsyncClient, test_user: User, db: AsyncSession): """Test bulk update with position, transformations, and z-order together.""" board = Board( id=uuid4(), user_id=test_user.id, title="Test Board", viewport_state={"x": 0, "y": 0, "zoom": 1.0, "rotation": 0}, ) db.add(board) images = [] for i in range(2): image = Image( id=uuid4(), user_id=test_user.id, filename=f"test{i}.jpg", storage_path=f"{test_user.id}/test{i}.jpg", file_size=1024, mime_type="image/jpeg", width=800, height=600, metadata={"format": "jpeg", "checksum": f"abc{i}"}, ) db.add(image) images.append(image) board_image = BoardImage( id=uuid4(), board_id=board.id, image_id=image.id, position={"x": 100, "y": 100}, transformations={ "scale": 1.0, "rotation": 0, "opacity": 1.0, "flipped_h": False, "flipped_v": False, "greyscale": False, }, z_order=0, ) db.add(board_image) await db.commit() # Bulk update everything response = await client.patch( f"/api/images/boards/{board.id}/images/bulk", json={ "image_ids": [str(img.id) for img in images], "position_delta": {"dx": 50, "dy": 50}, "transformations": {"scale": 2.0}, "z_order_delta": 5, }, ) assert response.status_code == 200 data = response.json() assert data["updated_count"] == 2 assert data["failed_count"] == 0 @pytest.mark.asyncio async def test_bulk_update_non_existent_image(client: AsyncClient, test_user: User, db: AsyncSession): """Test bulk update with some non-existent images.""" board = Board( id=uuid4(), user_id=test_user.id, title="Test Board", viewport_state={"x": 0, "y": 0, "zoom": 1.0, "rotation": 0}, ) db.add(board) image = Image( id=uuid4(), user_id=test_user.id, filename="test.jpg", storage_path=f"{test_user.id}/test.jpg", file_size=1024, mime_type="image/jpeg", width=800, height=600, metadata={"format": "jpeg", "checksum": "abc"}, ) db.add(image) board_image = BoardImage( id=uuid4(), board_id=board.id, image_id=image.id, position={"x": 100, "y": 100}, transformations={ "scale": 1.0, "rotation": 0, "opacity": 1.0, "flipped_h": False, "flipped_v": False, "greyscale": False, }, z_order=0, ) db.add(board_image) await db.commit() # Try to update with one valid and one invalid ID response = await client.patch( f"/api/images/boards/{board.id}/images/bulk", json={ "image_ids": [str(image.id), str(uuid4())], # One valid, one invalid "transformations": {"scale": 2.0}, }, ) assert response.status_code == 200 data = response.json() assert data["updated_count"] == 1 # Only valid one updated assert data["failed_count"] == 1 @pytest.mark.asyncio async def test_bulk_update_unauthorized(client: AsyncClient, test_user: User, db: AsyncSession): """Test bulk update on board not owned by user.""" # Create another user other_user = User(id=uuid4(), email="other@example.com", password_hash="hashed") db.add(other_user) # Create board owned by other user board = Board( id=uuid4(), user_id=other_user.id, title="Other Board", viewport_state={"x": 0, "y": 0, "zoom": 1.0, "rotation": 0}, ) db.add(board) await db.commit() # Try bulk update as current user response = await client.patch( f"/api/images/boards/{board.id}/images/bulk", json={ "image_ids": [str(uuid4())], "transformations": {"scale": 2.0}, }, ) assert response.status_code == 403 @pytest.mark.asyncio async def test_bulk_update_empty_image_list(client: AsyncClient, test_user: User, db: AsyncSession): """Test bulk update with empty image list.""" board = Board( id=uuid4(), user_id=test_user.id, title="Test Board", viewport_state={"x": 0, "y": 0, "zoom": 1.0, "rotation": 0}, ) db.add(board) await db.commit() response = await client.patch( f"/api/images/boards/{board.id}/images/bulk", json={ "image_ids": [], "transformations": {"scale": 2.0}, }, ) # Should succeed with 0 updated assert response.status_code == 200 data = response.json() assert data["updated_count"] == 0