From 0ca846af1567d5057e7e9eb7d02377630cb78496 Mon Sep 17 00:00:00 2001 From: Daniel Bedeleanu Date: Sat, 18 Apr 2026 16:59:56 +0000 Subject: [PATCH] test: add item CRUD and validation tests --- backend/tests/test_items.py | 165 ++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 backend/tests/test_items.py diff --git a/backend/tests/test_items.py b/backend/tests/test_items.py new file mode 100644 index 00000000..89fccca6 --- /dev/null +++ b/backend/tests/test_items.py @@ -0,0 +1,165 @@ +import pytest +from fastapi import status + + +class TestItemCRUD: + """Test item creation, read, update, delete.""" + + def test_create_item(self, test_client, test_db): + """Test creating an inventory item.""" + response = test_client.post( + "/api/items", + json={ + "name": "Test Item", + "category": "Electronics", + "item_type": "Component", + "quantity": 10, + "barcode": "123456789", + "part_number": "PN-12345" + } + ) + assert response.status_code == status.HTTP_201_CREATED + data = response.json() + assert data["name"] == "Test Item" + assert data["quantity"] == 10 + + def test_create_item_missing_required_field(self, test_client): + """Test that missing required fields fail.""" + response = test_client.post( + "/api/items", + json={"name": "Test Item"} + ) + assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY + + def test_get_item_by_id(self, test_client, test_db): + """Test retrieving an item by ID.""" + from backend.models import Item + + item = Item( + name="Test Item", + category="Electronics", + item_type="Component", + quantity=10, + barcode="123456789", + part_number="PN-12345" + ) + test_db.add(item) + test_db.commit() + + response = test_client.get(f"/api/items/{item.id}") + assert response.status_code == status.HTTP_200_OK + data = response.json() + assert data["name"] == "Test Item" + assert data["barcode"] == "123456789" + + def test_list_items(self, test_client, test_db): + """Test listing all items.""" + from backend.models import Item + + item1 = Item(name="Item1", category="A", item_type="Type", quantity=5, barcode="111", part_number="PN1") + item2 = Item(name="Item2", category="B", item_type="Type", quantity=3, barcode="222", part_number="PN2") + test_db.add_all([item1, item2]) + test_db.commit() + + response = test_client.get("/api/items") + assert response.status_code == status.HTTP_200_OK + data = response.json() + assert len(data) >= 2 + + def test_update_item(self, test_client, test_db): + """Test updating an item.""" + from backend.models import Item + + item = Item( + name="Test Item", + category="Electronics", + item_type="Component", + quantity=10, + barcode="123456789", + part_number="PN-12345" + ) + test_db.add(item) + test_db.commit() + + response = test_client.put( + f"/api/items/{item.id}", + json={"quantity": 20, "part_number": "PN-99999"} + ) + assert response.status_code == status.HTTP_200_OK + data = response.json() + assert data["quantity"] == 20 + assert data["part_number"] == "PN-99999" + + def test_delete_item_admin_only(self, test_client, test_db, admin_token): + """Test deleting an item (admin only).""" + from backend.models import Item + + item = Item( + name="Test Item", + category="Electronics", + item_type="Component", + quantity=10, + barcode="123456789", + part_number="PN-12345" + ) + test_db.add(item) + test_db.commit() + item_id = item.id + + response = test_client.delete( + f"/api/items/{item_id}", + headers={"Authorization": f"Bearer {admin_token}"} + ) + assert response.status_code == status.HTTP_204_NO_CONTENT + + # Verify audit log persists + response = test_client.get(f"/api/audit-logs?item_id={item_id}") + assert response.status_code == status.HTTP_200_OK + + +class TestItemValidation: + """Test item field validation.""" + + def test_barcode_unique(self, test_client, test_db): + """Test that barcodes must be unique.""" + from backend.models import Item + + item1 = Item( + name="Item1", + category="A", + item_type="Type", + quantity=5, + barcode="UNIQUE123", + part_number="PN1" + ) + test_db.add(item1) + test_db.commit() + + # Try to create duplicate barcode + response = test_client.post( + "/api/items", + json={ + "name": "Item2", + "category": "B", + "item_type": "Type", + "quantity": 5, + "barcode": "UNIQUE123", + "part_number": "PN2" + } + ) + assert response.status_code == status.HTTP_409_CONFLICT + + def test_quantity_non_negative(self, test_client): + """Test that quantity must be non-negative.""" + response = test_client.post( + "/api/items", + json={ + "name": "Test", + "category": "A", + "item_type": "Type", + "quantity": -5, + "barcode": "123", + "part_number": "PN" + } + ) + assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY