Files
webref/backend/tests/api/test_bulk_operations.py
Danilo Reyes 948fe591dc
All checks were successful
CI/CD Pipeline / VM Test - security (push) Successful in 7s
CI/CD Pipeline / Backend Linting (push) Successful in 4s
CI/CD Pipeline / VM Test - backend-integration (push) Successful in 11s
CI/CD Pipeline / VM Test - full-stack (push) Successful in 8s
CI/CD Pipeline / VM Test - performance (push) Successful in 8s
CI/CD Pipeline / Nix Flake Check (push) Successful in 38s
CI/CD Pipeline / CI Summary (push) Successful in 0s
CI/CD Pipeline / Frontend Linting (push) Successful in 17s
phase 13
2025-11-02 14:48:03 -06:00

379 lines
10 KiB
Python

"""Integration tests for bulk image operations."""
from uuid import uuid4
import pytest
from httpx import AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession
from app.database.models.board import Board
from app.database.models.board_image import BoardImage
from app.database.models.image import Image
from app.database.models.user import User
@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