Files
orion/tests/unit/models/schema/test_inventory.py
Samir Boulahtit ca9f17fc37 refactor: split database model tests into organized modules
Split the monolithic test_database_models.py into focused test modules:

Database model tests (tests/unit/models/database/):
- test_customer.py: Customer model and authentication tests
- test_inventory.py: Inventory model tests
- test_marketplace_import_job.py: Import job model tests
- test_marketplace_product.py: Marketplace product model tests
- test_order.py: Order and OrderItem model tests
- test_product.py: Product model tests
- test_team.py: Team invitation and membership tests
- test_user.py: User model tests
- test_vendor.py: Vendor model tests

Schema validation tests (tests/unit/models/schema/):
- test_auth.py: Auth schema validation tests
- test_customer.py: Customer schema validation tests
- test_inventory.py: Inventory schema validation tests
- test_marketplace_import_job.py: Import job schema tests
- test_order.py: Order schema validation tests
- test_product.py: Product schema validation tests

This improves test organization and makes it easier to find
and maintain tests for specific models.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:42:26 +01:00

300 lines
9.1 KiB
Python

# tests/unit/models/schema/test_inventory.py
"""Unit tests for inventory Pydantic schemas."""
import pytest
from pydantic import ValidationError
from models.schema.inventory import (
InventoryBase,
InventoryCreate,
InventoryAdjust,
InventoryUpdate,
InventoryReserve,
InventoryResponse,
InventoryLocationResponse,
ProductInventorySummary,
)
@pytest.mark.unit
@pytest.mark.schema
class TestInventoryCreateSchema:
"""Test InventoryCreate schema validation."""
def test_valid_inventory_create(self):
"""Test valid inventory creation data."""
inventory = InventoryCreate(
product_id=1,
location="Warehouse A",
quantity=100,
)
assert inventory.product_id == 1
assert inventory.location == "Warehouse A"
assert inventory.quantity == 100
def test_product_id_required(self):
"""Test product_id is required."""
with pytest.raises(ValidationError) as exc_info:
InventoryCreate(location="Warehouse A", quantity=10)
assert "product_id" in str(exc_info.value).lower()
def test_location_required(self):
"""Test location is required."""
with pytest.raises(ValidationError) as exc_info:
InventoryCreate(product_id=1, quantity=10)
assert "location" in str(exc_info.value).lower()
def test_quantity_required(self):
"""Test quantity is required."""
with pytest.raises(ValidationError) as exc_info:
InventoryCreate(product_id=1, location="Warehouse A")
assert "quantity" in str(exc_info.value).lower()
def test_quantity_must_be_non_negative(self):
"""Test quantity must be >= 0."""
with pytest.raises(ValidationError) as exc_info:
InventoryCreate(
product_id=1,
location="Warehouse A",
quantity=-5,
)
assert "quantity" in str(exc_info.value).lower()
def test_quantity_zero_is_valid(self):
"""Test quantity of 0 is valid."""
inventory = InventoryCreate(
product_id=1,
location="Warehouse A",
quantity=0,
)
assert inventory.quantity == 0
@pytest.mark.unit
@pytest.mark.schema
class TestInventoryAdjustSchema:
"""Test InventoryAdjust schema validation."""
def test_positive_adjustment(self):
"""Test positive quantity adjustment (add stock)."""
adjustment = InventoryAdjust(
product_id=1,
location="Warehouse A",
quantity=50,
)
assert adjustment.quantity == 50
def test_negative_adjustment(self):
"""Test negative quantity adjustment (remove stock)."""
adjustment = InventoryAdjust(
product_id=1,
location="Warehouse A",
quantity=-20,
)
assert adjustment.quantity == -20
def test_zero_adjustment_is_valid(self):
"""Test zero adjustment is technically valid."""
adjustment = InventoryAdjust(
product_id=1,
location="Warehouse A",
quantity=0,
)
assert adjustment.quantity == 0
@pytest.mark.unit
@pytest.mark.schema
class TestInventoryUpdateSchema:
"""Test InventoryUpdate schema validation."""
def test_partial_update(self):
"""Test partial update with only some fields."""
update = InventoryUpdate(quantity=150)
assert update.quantity == 150
assert update.reserved_quantity is None
assert update.location is None
def test_empty_update_is_valid(self):
"""Test empty update is valid."""
update = InventoryUpdate()
assert update.model_dump(exclude_unset=True) == {}
def test_quantity_must_be_non_negative(self):
"""Test quantity must be >= 0 in update."""
with pytest.raises(ValidationError):
InventoryUpdate(quantity=-10)
def test_reserved_quantity_must_be_non_negative(self):
"""Test reserved_quantity must be >= 0."""
with pytest.raises(ValidationError):
InventoryUpdate(reserved_quantity=-5)
def test_location_update(self):
"""Test location can be updated."""
update = InventoryUpdate(location="Warehouse B")
assert update.location == "Warehouse B"
@pytest.mark.unit
@pytest.mark.schema
class TestInventoryReserveSchema:
"""Test InventoryReserve schema validation."""
def test_valid_reservation(self):
"""Test valid inventory reservation."""
reservation = InventoryReserve(
product_id=1,
location="Warehouse A",
quantity=10,
)
assert reservation.product_id == 1
assert reservation.quantity == 10
def test_quantity_must_be_positive(self):
"""Test reservation quantity must be > 0."""
with pytest.raises(ValidationError) as exc_info:
InventoryReserve(
product_id=1,
location="Warehouse A",
quantity=0,
)
assert "quantity" in str(exc_info.value).lower()
def test_negative_quantity_invalid(self):
"""Test negative reservation quantity is invalid."""
with pytest.raises(ValidationError):
InventoryReserve(
product_id=1,
location="Warehouse A",
quantity=-5,
)
@pytest.mark.unit
@pytest.mark.schema
class TestInventoryResponseSchema:
"""Test InventoryResponse schema."""
def test_from_dict(self):
"""Test creating response from dict."""
from datetime import datetime
data = {
"id": 1,
"product_id": 1,
"vendor_id": 1,
"location": "Warehouse A",
"quantity": 100,
"reserved_quantity": 20,
"gtin": "1234567890123",
"created_at": datetime.now(),
"updated_at": datetime.now(),
}
response = InventoryResponse(**data)
assert response.id == 1
assert response.quantity == 100
assert response.reserved_quantity == 20
def test_available_quantity_property(self):
"""Test available_quantity calculated property."""
from datetime import datetime
data = {
"id": 1,
"product_id": 1,
"vendor_id": 1,
"location": "Warehouse A",
"quantity": 100,
"reserved_quantity": 30,
"gtin": None,
"created_at": datetime.now(),
"updated_at": datetime.now(),
}
response = InventoryResponse(**data)
assert response.available_quantity == 70
def test_available_quantity_never_negative(self):
"""Test available_quantity is never negative."""
from datetime import datetime
data = {
"id": 1,
"product_id": 1,
"vendor_id": 1,
"location": "Warehouse A",
"quantity": 10,
"reserved_quantity": 50, # Over-reserved
"gtin": None,
"created_at": datetime.now(),
"updated_at": datetime.now(),
}
response = InventoryResponse(**data)
assert response.available_quantity == 0
@pytest.mark.unit
@pytest.mark.schema
class TestInventoryLocationResponseSchema:
"""Test InventoryLocationResponse schema."""
def test_valid_location_response(self):
"""Test valid location response."""
location = InventoryLocationResponse(
location="Warehouse A",
quantity=100,
reserved_quantity=20,
available_quantity=80,
)
assert location.location == "Warehouse A"
assert location.quantity == 100
assert location.available_quantity == 80
@pytest.mark.unit
@pytest.mark.schema
class TestProductInventorySummarySchema:
"""Test ProductInventorySummary schema."""
def test_valid_summary(self):
"""Test valid inventory summary."""
summary = ProductInventorySummary(
product_id=1,
vendor_id=1,
product_sku="SKU-001",
product_title="Test Product",
total_quantity=200,
total_reserved=50,
total_available=150,
locations=[
InventoryLocationResponse(
location="Warehouse A",
quantity=100,
reserved_quantity=25,
available_quantity=75,
),
InventoryLocationResponse(
location="Warehouse B",
quantity=100,
reserved_quantity=25,
available_quantity=75,
),
],
)
assert summary.product_id == 1
assert summary.total_quantity == 200
assert len(summary.locations) == 2
def test_empty_locations(self):
"""Test summary with no locations."""
summary = ProductInventorySummary(
product_id=1,
vendor_id=1,
product_sku=None,
product_title="Test Product",
total_quantity=0,
total_reserved=0,
total_available=0,
locations=[],
)
assert summary.locations == []