import tempfile from io import BytesIO from pathlib import Path from unittest.mock import patch from django.core.files.uploadedfile import SimpleUploadedFile from django.test import TestCase, override_settings from PIL import Image from rest_framework.test import APIClient def png_upload(color=(32, 64, 128), size=(4, 4), name="sample.png"): buffer = BytesIO() Image.new("RGB", size, color).save(buffer, format="PNG") return SimpleUploadedFile(name, buffer.getvalue(), content_type="image/png") class ApiTests(TestCase): def setUp(self): self.tmp = tempfile.TemporaryDirectory() self.override = override_settings(MEDIA_ROOT=Path(self.tmp.name), IMAGE_SESSION_TTL_HOURS=1) self.override.enable() self.client = APIClient() def tearDown(self): self.override.disable() self.tmp.cleanup() def test_upload_and_process(self): upload = self.client.post("/api/images/", {"image": png_upload()}, format="multipart") self.assertEqual(upload.status_code, 201) session_id = upload.data["session_id"] self.assertEqual(len(upload.data["original_histogram"]), 256) processed = self.client.post( "/api/process/", {"session_id": session_id, "operation": "gamma", "params": {"gamma": 1, "c": 1}}, format="json", ) self.assertEqual(processed.status_code, 200) self.assertEqual(len(processed.data["processed_histogram"]), 256) self.assertTrue(processed.data["image_data"].startswith("data:image/png;base64,")) def test_invalid_kernel_rejected(self): upload = self.client.post("/api/images/", {"image": png_upload()}, format="multipart") processed = self.client.post( "/api/process/", {"session_id": upload.data["session_id"], "operation": "median_filter", "params": {"size": 4}}, format="json", ) self.assertEqual(processed.status_code, 400) @patch("processing.services.run_batch_job.delay") def test_batch_returns_job_id(self, delay): first = self.client.post("/api/images/", {"image": png_upload(name="a.png")}, format="multipart") second = self.client.post("/api/images/", {"image": png_upload(color=(96, 96, 96), name="b.png")}, format="multipart") response = self.client.post( "/api/batch/", {"operation": "average", "session_ids": [first.data["session_id"], second.data["session_id"]]}, format="json", ) self.assertEqual(response.status_code, 202) self.assertIn("job_id", response.data) delay.assert_called_once()