From bbe60bb4710396e300bbbc3f13ff562f3044376a Mon Sep 17 00:00:00 2001 From: Daniel Bedeleanu Date: Tue, 21 Apr 2026 19:31:26 +0300 Subject: [PATCH] test: add integration tests for item creation with auto-photo-save --- backend/tests/test_photo_extraction.py | 149 +++++++++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/backend/tests/test_photo_extraction.py b/backend/tests/test_photo_extraction.py index 3ae417c8..089ceb57 100644 --- a/backend/tests/test_photo_extraction.py +++ b/backend/tests/test_photo_extraction.py @@ -521,3 +521,152 @@ def test_auto_save_never_throws_exceptions( assert isinstance(result, dict) assert "status" in result assert result["status"] in ["ok", "skipped"] + + +# ============================================================================ +# INTEGRATION TESTS: FULL FLOW (create_item endpoint with auto-save) +# ============================================================================ + +def test_create_item_with_image_processing_integration( + admin_client, + sample_image_bytes +): + """Integration test: create item with extracted image → photo auto-saved with crop/rotation.""" + import base64 + + # Encode image as base64 for API payload + image_base64 = base64.b64encode(sample_image_bytes).decode() + + item_data = { + "name": "NVMe Storage Drive", + "category": "Storage", + "type": "NVMe", + "quantity": 1, + "barcode": "NVM-2024-001", + "part_number": "P66093-002", + "extracted_image_bytes": image_base64, + "image_processing": { + "crop_bounds": {"x": 45, "y": 80, "width": 350, "height": 220}, + "rotation_degrees": 12, + "confidence": 0.94 + } + } + + response = admin_client.post("/items/", json=item_data) + + # Verify item was created + assert response.status_code == 201 + data = response.json() + assert data["id"] is not None + assert data["name"] == "NVMe Storage Drive" + assert data["barcode"] == "NVM-2024-001" + + # Verify photo was auto-saved + assert data["photo_path"] is not None + assert data["photo_thumbnail_path"] is not None + assert data["photo_upload_date"] is not None + + # Verify photo paths are valid + assert "/images/" in data["photo_path"] + assert "/images/" in data["photo_thumbnail_path"] + assert data["photo_path"].endswith(".jpg") + assert data["photo_thumbnail_path"].endswith(".jpg") + + # Cleanup + Path(data["photo_path"].lstrip("/")).unlink(missing_ok=True) + Path(data["photo_thumbnail_path"].lstrip("/")).unlink(missing_ok=True) + + +def test_create_item_with_invalid_image_processing( + admin_client, + sample_image_bytes +): + """Integration test: Item created even if image_processing is invalid, photo skipped gracefully.""" + import base64 + + image_base64 = base64.b64encode(sample_image_bytes).decode() + + item_data = { + "name": "Test Item Invalid", + "category": "Storage", + "type": "SSD", + "quantity": 1, + "barcode": "TEST-INVALID-001", + "extracted_image_bytes": image_base64, + "image_processing": { + # Missing crop_bounds or invalid values + "rotation_degrees": 999, # Invalid (out of range) + "confidence": 1.5 # Invalid (>1.0) + } + } + + response = admin_client.post("/items/", json=item_data) + + # Item should still be created successfully + assert response.status_code == 201 + data = response.json() + assert data["id"] is not None + assert data["name"] == "Test Item Invalid" + + # Photo should not be saved (invalid image_processing) + assert data["photo_path"] is None + assert data["photo_thumbnail_path"] is None + assert data["photo_upload_date"] is None + + +def test_create_item_without_image_processing( + admin_client +): + """Integration test: Backward compatibility - old clients without image_processing work.""" + item_data = { + "name": "Old Style Item", + "category": "Storage", + "type": "SSD", + "quantity": 1, + "barcode": "OLD-STYLE-001" + } + + response = admin_client.post("/items/", json=item_data) + + # Item should be created + assert response.status_code == 201 + data = response.json() + assert data["id"] is not None + assert data["name"] == "Old Style Item" + + # No photo expected (no extracted_image_bytes provided) + assert data["photo_path"] is None + assert data["photo_thumbnail_path"] is None + assert data["photo_upload_date"] is None + + +def test_create_item_with_image_bytes_but_no_processing( + admin_client, + sample_image_bytes +): + """Integration test: Image bytes without image_processing → item created, photo not saved.""" + import base64 + + image_base64 = base64.b64encode(sample_image_bytes).decode() + + item_data = { + "name": "Image Bytes Only", + "category": "Storage", + "type": "SATA", + "quantity": 2, + "barcode": "BYTES-ONLY-001", + "extracted_image_bytes": image_base64 + # No image_processing field + } + + response = admin_client.post("/items/", json=item_data) + + # Item should be created + assert response.status_code == 201 + data = response.json() + assert data["id"] is not None + + # Photo not saved (no image_processing means no crop info) + assert data["photo_path"] is None + assert data["photo_thumbnail_path"] is None + assert data["photo_upload_date"] is None