Files
tfm_ainventory/backend/tests/test_quantity_patch.py
Daniel Bedeleanu a7746a14ea test(5.1): add integration and unit tests for quick quantity adjustment
- Vitest hook tests for useQuantityAdjustment (optimistic updates, debouncing)
- Pytest backend tests for PATCH /items/{itemId} endpoint
- Tests cover success, failure, validation, and audit logging scenarios
2026-04-22 17:42:08 +03:00

166 lines
5.0 KiB
Python

"""
Test PATCH /items/{item_id} endpoint for quantity adjustment
Ensures audit logging and validation work correctly
"""
import pytest
import json
from fastapi.testclient import TestClient
from sqlalchemy.orm import Session
from ..models import Item, Category, AuditLog
from ..schemas import Item as ItemSchema
from ..database import Base, engine
@pytest.fixture
def test_item(db: Session):
"""Create a test item"""
category = Category(name="Test Category")
db.add(category)
db.commit()
item = Item(
name="Test Item",
category="Test Category",
type="Test Type",
quantity=10,
barcode="TEST123",
part_number="PN-TEST-001"
)
db.add(item)
db.commit()
db.refresh(item)
return item
def test_patch_quantity_success(client: TestClient, test_item: Item, db: Session, auth_token: str):
"""Test successful quantity update with audit logging"""
response = client.patch(
f"/items/{test_item.id}",
json={"quantity": 25},
headers={"Authorization": f"Bearer {auth_token}"}
)
assert response.status_code == 200
data = response.json()
assert data["quantity"] == 25
assert data["id"] == test_item.id
# Verify audit log was created
audit_entries = db.query(AuditLog).filter(
AuditLog.target_item_id == test_item.id,
AuditLog.action == "UPDATE_QUANTITY"
).all()
assert len(audit_entries) == 1
audit = audit_entries[0]
assert audit.quantity_change == 15 # 25 - 10
assert audit.target_item_name == "Test Item"
assert audit.target_item_pn == "PN-TEST-001"
assert "10 → 25" in audit.details
def test_patch_quantity_to_zero(client: TestClient, test_item: Item, db: Session, auth_token: str):
"""Test setting quantity to zero"""
response = client.patch(
f"/items/{test_item.id}",
json={"quantity": 0},
headers={"Authorization": f"Bearer {auth_token}"}
)
assert response.status_code == 200
data = response.json()
assert data["quantity"] == 0
# Verify audit log has correct delta
audit = db.query(AuditLog).filter(
AuditLog.target_item_id == test_item.id,
AuditLog.action == "UPDATE_QUANTITY"
).first()
assert audit.quantity_change == -10 # 0 - 10
def test_patch_quantity_negative_fails(client: TestClient, test_item: Item, auth_token: str):
"""Test that negative quantity is rejected"""
response = client.patch(
f"/items/{test_item.id}",
json={"quantity": -5},
headers={"Authorization": f"Bearer {auth_token}"}
)
assert response.status_code == 400
assert "non-negative" in response.json()["detail"].lower()
def test_patch_quantity_missing_field(client: TestClient, test_item: Item, auth_token: str):
"""Test that missing quantity field is rejected"""
response = client.patch(
f"/items/{test_item.id}",
json={},
headers={"Authorization": f"Bearer {auth_token}"}
)
assert response.status_code == 400
assert "quantity" in response.json()["detail"].lower()
def test_patch_quantity_invalid_type(client: TestClient, test_item: Item, auth_token: str):
"""Test that non-integer quantity is rejected"""
response = client.patch(
f"/items/{test_item.id}",
json={"quantity": "not a number"},
headers={"Authorization": f"Bearer {auth_token}"}
)
assert response.status_code == 400
assert "integer" in response.json()["detail"].lower()
def test_patch_quantity_not_found(client: TestClient, auth_token: str):
"""Test that updating non-existent item returns 404"""
response = client.patch(
"/items/99999",
json={"quantity": 10},
headers={"Authorization": f"Bearer {auth_token}"}
)
assert response.status_code == 404
assert "not found" in response.json()["detail"].lower()
def test_patch_quantity_no_auth(client: TestClient, test_item: Item):
"""Test that unauthenticated request is rejected"""
response = client.patch(
f"/items/{test_item.id}",
json={"quantity": 25}
)
assert response.status_code == 401
def test_patch_quantity_audit_fields(client: TestClient, test_item: Item, db: Session, auth_token: str, current_user_id: str):
"""Test that audit log contains all required fields"""
response = client.patch(
f"/items/{test_item.id}",
json={"quantity": 30},
headers={"Authorization": f"Bearer {auth_token}"}
)
assert response.status_code == 200
audit = db.query(AuditLog).filter(
AuditLog.target_item_id == test_item.id,
AuditLog.action == "UPDATE_QUANTITY"
).first()
assert audit is not None
assert audit.user_id == current_user_id
assert audit.action == "UPDATE_QUANTITY"
assert audit.target_item_id == test_item.id
assert audit.target_item_name == "Test Item"
assert audit.target_item_pn == "PN-TEST-001"
assert audit.target_item_barcode == "TEST123"
assert audit.quantity_change == 20 # 30 - 10
assert "" in audit.details # Direction indicator in details