| from __future__ import annotations |
|
|
| import tempfile |
| import unittest |
| from pathlib import Path |
|
|
| from fastapi import status |
| from fastapi.testclient import TestClient |
|
|
| from app.api.dependencies import get_container |
| from app.main import create_app |
| from tests.integration.api.support import FakeProcessRemoteImage, FakeProcessUploadedImage, make_container |
|
|
|
|
| class ApiProcessUploadIntegrationTests(unittest.TestCase): |
| def test_process_upload_accepts_real_demo_image_file(self) -> None: |
| with tempfile.TemporaryDirectory() as temp_dir: |
| root = Path(temp_dir) |
| process_uploaded_image = FakeProcessUploadedImage() |
| app = create_app() |
| app.dependency_overrides[get_container] = lambda: make_container( |
| root, |
| process_remote_image=FakeProcessRemoteImage(), |
| process_uploaded_image=process_uploaded_image, |
| ) |
| client = TestClient(app) |
| demo_path = Path(__file__).resolve().parents[2] / "demo.jpg" |
| expected_bytes = demo_path.read_bytes() |
| try: |
| with demo_path.open("rb") as image_file: |
| response = client.post( |
| "/process/upload", |
| files={"file": ("demo.jpg", image_file, "image/jpeg")}, |
| data={"options": '{"formats":["jpg"]}'}, |
| ) |
|
|
| self.assertEqual(status.HTTP_200_OK, response.status_code) |
| self.assertEqual("test-upload-job", response.json()["jobId"]) |
| self.assertEqual(1, len(process_uploaded_image.calls)) |
| self.assertEqual("demo.jpg", process_uploaded_image.calls[0][0]) |
| self.assertEqual(expected_bytes, process_uploaded_image.calls[0][1]) |
| self.assertEqual(["jpg"], process_uploaded_image.calls[0][2].formats) |
| finally: |
| client.close() |
| app.dependency_overrides.clear() |
|
|
| def test_process_upload_returns_job_id_on_success(self) -> None: |
| with tempfile.TemporaryDirectory() as temp_dir: |
| root = Path(temp_dir) |
| process_uploaded_image = FakeProcessUploadedImage() |
| app = create_app() |
| app.dependency_overrides[get_container] = lambda: make_container( |
| root, |
| process_remote_image=FakeProcessRemoteImage(), |
| process_uploaded_image=process_uploaded_image, |
| ) |
| client = TestClient(app) |
| try: |
| response = client.post( |
| "/process/upload", |
| files={"file": ("test.jpg", b"binary-image", "image/jpeg")}, |
| data={"options": '{"formats":["jpg"],"upload":{"uploadToR2":false}}'}, |
| ) |
|
|
| self.assertEqual(status.HTTP_200_OK, response.status_code) |
| self.assertEqual("test-upload-job", response.json()["jobId"]) |
| self.assertEqual(1, len(process_uploaded_image.calls)) |
| self.assertEqual("test.jpg", process_uploaded_image.calls[0][0]) |
| self.assertEqual(b"binary-image", process_uploaded_image.calls[0][1]) |
| self.assertEqual(["jpg"], process_uploaded_image.calls[0][2].formats) |
| finally: |
| client.close() |
| app.dependency_overrides.clear() |
|
|
| def test_process_upload_returns_400_for_invalid_options(self) -> None: |
| with tempfile.TemporaryDirectory() as temp_dir: |
| root = Path(temp_dir) |
| app = create_app() |
| app.dependency_overrides[get_container] = lambda: make_container( |
| root, |
| process_remote_image=FakeProcessRemoteImage(), |
| process_uploaded_image=FakeProcessUploadedImage(), |
| ) |
| client = TestClient(app) |
| try: |
| response = client.post( |
| "/process/upload", |
| files={"file": ("test.jpg", b"binary-image", "image/jpeg")}, |
| data={"options": "{not-json}"}, |
| ) |
|
|
| self.assertEqual(status.HTTP_400_BAD_REQUEST, response.status_code) |
| self.assertIn("Invalid options:", response.json()["detail"]) |
| finally: |
| client.close() |
| app.dependency_overrides.clear() |
|
|
| def test_process_upload_returns_400_when_source_fields_are_provided(self) -> None: |
| with tempfile.TemporaryDirectory() as temp_dir: |
| root = Path(temp_dir) |
| app = create_app() |
| app.dependency_overrides[get_container] = lambda: make_container( |
| root, |
| process_remote_image=FakeProcessRemoteImage(), |
| process_uploaded_image=FakeProcessUploadedImage(), |
| ) |
| client = TestClient(app) |
| try: |
| response = client.post( |
| "/process/upload", |
| files={"file": ("test.jpg", b"binary-image", "image/jpeg")}, |
| data={"options": '{"sourceUrl":"https://example.com/image.jpg"}'}, |
| ) |
|
|
| self.assertEqual(status.HTTP_400_BAD_REQUEST, response.status_code) |
| self.assertIn("must not include source fields", response.json()["detail"]) |
| finally: |
| client.close() |
| app.dependency_overrides.clear() |
|
|
| def test_process_upload_accepts_r2_prefix_override_with_nested_path(self) -> None: |
| with tempfile.TemporaryDirectory() as temp_dir: |
| root = Path(temp_dir) |
| process_uploaded_image = FakeProcessUploadedImage() |
| app = create_app() |
| app.dependency_overrides[get_container] = lambda: make_container( |
| root, |
| process_remote_image=FakeProcessRemoteImage(), |
| process_uploaded_image=process_uploaded_image, |
| ) |
| client = TestClient(app) |
| try: |
| response = client.post( |
| "/process/upload", |
| files={"file": ("test.jpg", b"binary-image", "image/jpeg")}, |
| data={"options": '{"formats":["jpg"],"upload":{"uploadToR2":true,"r2Prefix":"nested/listing-123/gallery"}}'}, |
| ) |
|
|
| self.assertEqual(status.HTTP_200_OK, response.status_code) |
| self.assertEqual("test-upload-job", response.json()["jobId"]) |
| self.assertEqual(1, len(process_uploaded_image.calls)) |
| request = process_uploaded_image.calls[0][2] |
| self.assertIsNotNone(request.upload) |
| self.assertTrue(request.upload.upload_to_r2) |
| self.assertEqual("nested/listing-123/gallery", request.upload.r2_prefix) |
| finally: |
| client.close() |
| app.dependency_overrides.clear() |
|
|
|
|
| if __name__ == "__main__": |
| unittest.main() |
|
|