test: add integration tests for item creation with auto-photo-save
This commit is contained in:
@@ -521,3 +521,152 @@ def test_auto_save_never_throws_exceptions(
|
|||||||
assert isinstance(result, dict)
|
assert isinstance(result, dict)
|
||||||
assert "status" in result
|
assert "status" in result
|
||||||
assert result["status"] in ["ok", "skipped"]
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user