style: apply black and isort formatting across entire codebase
- Standardize quote style (single to double quotes) - Reorder and group imports alphabetically - Fix line breaks and indentation for consistency - Apply PEP 8 formatting standards Also updated Makefile to exclude both venv and .venv from code quality checks. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -3,19 +3,17 @@ import uuid
|
||||
|
||||
import pytest
|
||||
|
||||
from app.exceptions import (InsufficientInventoryException,
|
||||
InvalidInventoryOperationException,
|
||||
InvalidQuantityException,
|
||||
InventoryNotFoundException,
|
||||
InventoryValidationException,
|
||||
NegativeInventoryException, ValidationException)
|
||||
from app.services.inventory_service import InventoryService
|
||||
from app.exceptions import (
|
||||
InventoryNotFoundException,
|
||||
InsufficientInventoryException,
|
||||
InvalidInventoryOperationException,
|
||||
InventoryValidationException,
|
||||
NegativeInventoryException,
|
||||
InvalidQuantityException,
|
||||
ValidationException,
|
||||
)
|
||||
from models.schema.inventory import InventoryAdd, InventoryCreate, InventoryUpdate
|
||||
from models.database.marketplace_product import MarketplaceProduct
|
||||
from models.database.inventory import Inventory
|
||||
from models.database.marketplace_product import MarketplaceProduct
|
||||
from models.schema.inventory import (InventoryAdd, InventoryCreate,
|
||||
InventoryUpdate)
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@@ -40,10 +38,14 @@ class TestInventoryService:
|
||||
def test_normalize_gtin_valid(self):
|
||||
"""Test GTIN normalization with valid GTINs."""
|
||||
# Test various valid GTIN formats - these should remain unchanged
|
||||
assert self.service._normalize_gtin("1234567890123") == "1234567890123" # EAN-13
|
||||
assert (
|
||||
self.service._normalize_gtin("1234567890123") == "1234567890123"
|
||||
) # EAN-13
|
||||
assert self.service._normalize_gtin("123456789012") == "123456789012" # UPC-A
|
||||
assert self.service._normalize_gtin("12345678") == "12345678" # EAN-8
|
||||
assert self.service._normalize_gtin("12345678901234") == "12345678901234" # GTIN-14
|
||||
assert (
|
||||
self.service._normalize_gtin("12345678901234") == "12345678901234"
|
||||
) # GTIN-14
|
||||
|
||||
# Test with decimal points (should be removed)
|
||||
assert self.service._normalize_gtin("1234567890123.0") == "1234567890123"
|
||||
@@ -52,11 +54,17 @@ class TestInventoryService:
|
||||
assert self.service._normalize_gtin(" 1234567890123 ") == "1234567890123"
|
||||
|
||||
# Test short GTINs being padded
|
||||
assert self.service._normalize_gtin("123") == "0000000000123" # Padded to EAN-13
|
||||
assert self.service._normalize_gtin("12345") == "0000000012345" # Padded to EAN-13
|
||||
assert (
|
||||
self.service._normalize_gtin("123") == "0000000000123"
|
||||
) # Padded to EAN-13
|
||||
assert (
|
||||
self.service._normalize_gtin("12345") == "0000000012345"
|
||||
) # Padded to EAN-13
|
||||
|
||||
# Test long GTINs being truncated
|
||||
assert self.service._normalize_gtin("123456789012345") == "3456789012345" # Truncated to 13
|
||||
assert (
|
||||
self.service._normalize_gtin("123456789012345") == "3456789012345"
|
||||
) # Truncated to 13
|
||||
|
||||
def test_normalize_gtin_edge_cases(self):
|
||||
"""Test GTIN normalization edge cases."""
|
||||
@@ -65,9 +73,15 @@ class TestInventoryService:
|
||||
assert self.service._normalize_gtin(123) == "0000000000123"
|
||||
|
||||
# Test mixed valid/invalid characters
|
||||
assert self.service._normalize_gtin("123-456-789-012") == "123456789012" # Dashes removed
|
||||
assert self.service._normalize_gtin("123 456 789 012") == "123456789012" # Spaces removed
|
||||
assert self.service._normalize_gtin("ABC123456789012DEF") == "123456789012" # Letters removed
|
||||
assert (
|
||||
self.service._normalize_gtin("123-456-789-012") == "123456789012"
|
||||
) # Dashes removed
|
||||
assert (
|
||||
self.service._normalize_gtin("123 456 789 012") == "123456789012"
|
||||
) # Spaces removed
|
||||
assert (
|
||||
self.service._normalize_gtin("ABC123456789012DEF") == "123456789012"
|
||||
) # Letters removed
|
||||
|
||||
def test_set_inventory_new_entry_success(self, db):
|
||||
"""Test setting inventory for a new GTIN/location combination successfully."""
|
||||
@@ -162,7 +176,9 @@ class TestInventoryService:
|
||||
|
||||
def test_add_inventory_invalid_gtin_validation_error(self, db):
|
||||
"""Test adding inventory with invalid GTIN returns InventoryValidationException."""
|
||||
inventory_data = InventoryAdd(gtin="invalid_gtin", location="WAREHOUSE_A", quantity=50)
|
||||
inventory_data = InventoryAdd(
|
||||
gtin="invalid_gtin", location="WAREHOUSE_A", quantity=50
|
||||
)
|
||||
|
||||
with pytest.raises(InventoryValidationException) as exc_info:
|
||||
self.service.add_inventory(db, inventory_data)
|
||||
@@ -180,11 +196,12 @@ class TestInventoryService:
|
||||
assert exc_info.value.error_code == "INVALID_QUANTITY"
|
||||
assert "Quantity must be positive" in str(exc_info.value)
|
||||
|
||||
|
||||
def test_remove_inventory_success(self, db, test_inventory):
|
||||
"""Test removing inventory successfully."""
|
||||
original_quantity = test_inventory.quantity
|
||||
remove_quantity = min(10, original_quantity) # Ensure we don't remove more than available
|
||||
remove_quantity = min(
|
||||
10, original_quantity
|
||||
) # Ensure we don't remove more than available
|
||||
|
||||
inventory_data = InventoryAdd(
|
||||
gtin=test_inventory.gtin,
|
||||
@@ -212,7 +229,9 @@ class TestInventoryService:
|
||||
assert exc_info.value.error_code == "INSUFFICIENT_INVENTORY"
|
||||
assert exc_info.value.details["gtin"] == test_inventory.gtin
|
||||
assert exc_info.value.details["location"] == test_inventory.location
|
||||
assert exc_info.value.details["requested_quantity"] == test_inventory.quantity + 10
|
||||
assert (
|
||||
exc_info.value.details["requested_quantity"] == test_inventory.quantity + 10
|
||||
)
|
||||
assert exc_info.value.details["available_quantity"] == test_inventory.quantity
|
||||
|
||||
def test_remove_inventory_nonexistent_entry_not_found(self, db):
|
||||
@@ -231,7 +250,9 @@ class TestInventoryService:
|
||||
|
||||
def test_remove_inventory_invalid_gtin_validation_error(self, db):
|
||||
"""Test removing inventory with invalid GTIN returns InventoryValidationException."""
|
||||
inventory_data = InventoryAdd(gtin="invalid_gtin", location="WAREHOUSE_A", quantity=10)
|
||||
inventory_data = InventoryAdd(
|
||||
gtin="invalid_gtin", location="WAREHOUSE_A", quantity=10
|
||||
)
|
||||
|
||||
with pytest.raises(InventoryValidationException) as exc_info:
|
||||
self.service.remove_inventory(db, inventory_data)
|
||||
@@ -254,7 +275,9 @@ class TestInventoryService:
|
||||
# The service prevents negative inventory through InsufficientInventoryException
|
||||
assert exc_info.value.error_code == "INSUFFICIENT_INVENTORY"
|
||||
|
||||
def test_get_inventory_by_gtin_success(self, db, test_inventory, test_marketplace_product):
|
||||
def test_get_inventory_by_gtin_success(
|
||||
self, db, test_inventory, test_marketplace_product
|
||||
):
|
||||
"""Test getting inventory summary by GTIN successfully."""
|
||||
result = self.service.get_inventory_by_gtin(db, test_inventory.gtin)
|
||||
|
||||
@@ -265,14 +288,20 @@ class TestInventoryService:
|
||||
assert result.locations[0].quantity == test_inventory.quantity
|
||||
assert result.product_title == test_marketplace_product.title
|
||||
|
||||
def test_get_inventory_by_gtin_multiple_locations_success(self, db, test_marketplace_product):
|
||||
def test_get_inventory_by_gtin_multiple_locations_success(
|
||||
self, db, test_marketplace_product
|
||||
):
|
||||
"""Test getting inventory summary with multiple locations successfully."""
|
||||
unique_gtin = test_marketplace_product.gtin
|
||||
unique_id = str(uuid.uuid4())[:8]
|
||||
|
||||
# Create multiple inventory entries for the same GTIN with unique locations
|
||||
inventory1 = Inventory(gtin=unique_gtin, location=f"WAREHOUSE_A_{unique_id}", quantity=50)
|
||||
inventory2 = Inventory(gtin=unique_gtin, location=f"WAREHOUSE_B_{unique_id}", quantity=30)
|
||||
inventory1 = Inventory(
|
||||
gtin=unique_gtin, location=f"WAREHOUSE_A_{unique_id}", quantity=50
|
||||
)
|
||||
inventory2 = Inventory(
|
||||
gtin=unique_gtin, location=f"WAREHOUSE_B_{unique_id}", quantity=30
|
||||
)
|
||||
|
||||
db.add(inventory1)
|
||||
db.add(inventory2)
|
||||
@@ -301,7 +330,9 @@ class TestInventoryService:
|
||||
assert exc_info.value.error_code == "INVENTORY_VALIDATION_FAILED"
|
||||
assert "Invalid GTIN format" in str(exc_info.value)
|
||||
|
||||
def test_get_total_inventory_success(self, db, test_inventory, test_marketplace_product):
|
||||
def test_get_total_inventory_success(
|
||||
self, db, test_inventory, test_marketplace_product
|
||||
):
|
||||
"""Test getting total inventory for a GTIN successfully."""
|
||||
result = self.service.get_total_inventory(db, test_inventory.gtin)
|
||||
|
||||
@@ -364,7 +395,9 @@ class TestInventoryService:
|
||||
|
||||
result = self.service.get_all_inventory(db, skip=2, limit=2)
|
||||
|
||||
assert len(result) <= 2 # Should be at most 2, might be less if other records exist
|
||||
assert (
|
||||
len(result) <= 2
|
||||
) # Should be at most 2, might be less if other records exist
|
||||
|
||||
def test_update_inventory_success(self, db, test_inventory):
|
||||
"""Test updating inventory quantity successfully."""
|
||||
@@ -404,7 +437,9 @@ class TestInventoryService:
|
||||
assert result is True
|
||||
|
||||
# Verify the inventory is actually deleted
|
||||
deleted_inventory = db.query(Inventory).filter(Inventory.id == inventory_id).first()
|
||||
deleted_inventory = (
|
||||
db.query(Inventory).filter(Inventory.id == inventory_id).first()
|
||||
)
|
||||
assert deleted_inventory is None
|
||||
|
||||
def test_delete_inventory_not_found_error(self, db):
|
||||
@@ -415,7 +450,9 @@ class TestInventoryService:
|
||||
assert exc_info.value.error_code == "INVENTORY_NOT_FOUND"
|
||||
assert "99999" in str(exc_info.value)
|
||||
|
||||
def test_get_low_inventory_items_success(self, db, test_inventory, test_marketplace_product):
|
||||
def test_get_low_inventory_items_success(
|
||||
self, db, test_inventory, test_marketplace_product
|
||||
):
|
||||
"""Test getting low inventory items successfully."""
|
||||
# Set inventory to a low value
|
||||
test_inventory.quantity = 5
|
||||
@@ -424,7 +461,9 @@ class TestInventoryService:
|
||||
result = self.service.get_low_inventory_items(db, threshold=10)
|
||||
|
||||
assert len(result) >= 1
|
||||
low_inventory_item = next((item for item in result if item["gtin"] == test_inventory.gtin), None)
|
||||
low_inventory_item = next(
|
||||
(item for item in result if item["gtin"] == test_inventory.gtin), None
|
||||
)
|
||||
assert low_inventory_item is not None
|
||||
assert low_inventory_item["current_quantity"] == 5
|
||||
assert low_inventory_item["location"] == test_inventory.location
|
||||
@@ -440,9 +479,13 @@ class TestInventoryService:
|
||||
|
||||
def test_get_inventory_summary_by_location_success(self, db, test_inventory):
|
||||
"""Test getting inventory summary by location successfully."""
|
||||
result = self.service.get_inventory_summary_by_location(db, test_inventory.location)
|
||||
result = self.service.get_inventory_summary_by_location(
|
||||
db, test_inventory.location
|
||||
)
|
||||
|
||||
assert result["location"] == test_inventory.location.upper() # Service normalizes to uppercase
|
||||
assert (
|
||||
result["location"] == test_inventory.location.upper()
|
||||
) # Service normalizes to uppercase
|
||||
assert result["total_items"] >= 1
|
||||
assert result["total_quantity"] >= test_inventory.quantity
|
||||
assert result["unique_gtins"] >= 1
|
||||
@@ -450,7 +493,9 @@ class TestInventoryService:
|
||||
def test_get_inventory_summary_by_location_empty_result(self, db):
|
||||
"""Test getting inventory summary for location with no inventory."""
|
||||
unique_id = str(uuid.uuid4())[:8]
|
||||
result = self.service.get_inventory_summary_by_location(db, f"EMPTY_LOCATION_{unique_id}")
|
||||
result = self.service.get_inventory_summary_by_location(
|
||||
db, f"EMPTY_LOCATION_{unique_id}"
|
||||
)
|
||||
|
||||
assert result["total_items"] == 0
|
||||
assert result["total_quantity"] == 0
|
||||
@@ -459,12 +504,16 @@ class TestInventoryService:
|
||||
def test_validate_quantity_edge_cases(self, db):
|
||||
"""Test quantity validation with edge cases."""
|
||||
# Test zero quantity with allow_zero=True (should succeed)
|
||||
inventory_data = InventoryCreate(gtin="1234567890123", location="WAREHOUSE_A", quantity=0)
|
||||
inventory_data = InventoryCreate(
|
||||
gtin="1234567890123", location="WAREHOUSE_A", quantity=0
|
||||
)
|
||||
result = self.service.set_inventory(db, inventory_data)
|
||||
assert result.quantity == 0
|
||||
|
||||
# Test zero quantity with add_inventory (should fail - doesn't allow zero)
|
||||
inventory_data_add = InventoryAdd(gtin="1234567890123", location="WAREHOUSE_B", quantity=0)
|
||||
inventory_data_add = InventoryAdd(
|
||||
gtin="1234567890123", location="WAREHOUSE_B", quantity=0
|
||||
)
|
||||
with pytest.raises(InvalidQuantityException):
|
||||
self.service.add_inventory(db, inventory_data_add)
|
||||
|
||||
@@ -477,10 +526,10 @@ class TestInventoryService:
|
||||
exception = exc_info.value
|
||||
|
||||
# Verify exception structure matches WizamartException.to_dict()
|
||||
assert hasattr(exception, 'error_code')
|
||||
assert hasattr(exception, 'message')
|
||||
assert hasattr(exception, 'status_code')
|
||||
assert hasattr(exception, 'details')
|
||||
assert hasattr(exception, "error_code")
|
||||
assert hasattr(exception, "message")
|
||||
assert hasattr(exception, "status_code")
|
||||
assert hasattr(exception, "details")
|
||||
|
||||
assert isinstance(exception.error_code, str)
|
||||
assert isinstance(exception.message, str)
|
||||
|
||||
Reference in New Issue
Block a user