major refactoring adding vendor and customer features
This commit is contained in:
455
tests/integration/api/v1/test_inventory_endpoints.py
Normal file
455
tests/integration/api/v1/test_inventory_endpoints.py
Normal file
@@ -0,0 +1,455 @@
|
||||
# tests/integration/api/v1/test_inventory_endpoints.py
|
||||
import pytest
|
||||
|
||||
from models.database.inventory import Inventory
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
@pytest.mark.api
|
||||
@pytest.mark.inventory
|
||||
class TestInventoryAPI:
|
||||
|
||||
def test_set_inventory_new_success(self, client, auth_headers):
|
||||
"""Test setting inventory for new GTIN successfully"""
|
||||
inventory_data = {
|
||||
"gtin": "1234567890123",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 100,
|
||||
}
|
||||
|
||||
response = client.post("/api/v1/inventory", headers=auth_headers, json=inventory_data)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["gtin"] == "1234567890123"
|
||||
assert data["location"] == "WAREHOUSE_A"
|
||||
assert data["quantity"] == 100
|
||||
|
||||
def test_set_inventory_existing_success(self, client, auth_headers, db):
|
||||
"""Test updating existing inventory successfully"""
|
||||
# Create initial inventory
|
||||
inventory = Inventory(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
db.add(inventory)
|
||||
db.commit()
|
||||
|
||||
inventory_data = {
|
||||
"gtin": "1234567890123",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 75,
|
||||
}
|
||||
|
||||
response = client.post("/api/v1/inventory", headers=auth_headers, json=inventory_data)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["quantity"] == 75 # Should be replaced, not added
|
||||
|
||||
def test_set_inventory_invalid_gtin_validation_error(self, client, auth_headers):
|
||||
"""Test setting inventory with invalid GTIN returns ValidationException"""
|
||||
inventory_data = {
|
||||
"gtin": "", # Empty GTIN
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 100,
|
||||
}
|
||||
|
||||
response = client.post("/api/v1/inventory", headers=auth_headers, json=inventory_data)
|
||||
|
||||
assert response.status_code == 422
|
||||
data = response.json()
|
||||
assert data["error_code"] == "INVENTORY_VALIDATION_FAILED"
|
||||
assert data["status_code"] == 422
|
||||
assert "GTIN is required" in data["message"]
|
||||
|
||||
def test_set_inventory_invalid_quantity_validation_error(self, client, auth_headers):
|
||||
"""Test setting inventory with invalid quantity returns InvalidQuantityException"""
|
||||
inventory_data = {
|
||||
"gtin": "1234567890123",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": -10, # Negative quantity
|
||||
}
|
||||
|
||||
response = client.post("/api/v1/inventory", headers=auth_headers, json=inventory_data)
|
||||
|
||||
assert response.status_code in [400, 422]
|
||||
data = response.json()
|
||||
assert data["error_code"] in ["INVALID_QUANTITY", "VALIDATION_ERROR"]
|
||||
if data["error_code"] == "INVALID_QUANTITY":
|
||||
assert data["status_code"] == 422
|
||||
assert data["details"]["field"] == "quantity"
|
||||
|
||||
def test_add_inventory_success(self, client, auth_headers, db):
|
||||
"""Test adding to existing inventory successfully"""
|
||||
# Create initial inventory
|
||||
inventory = Inventory(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
db.add(inventory)
|
||||
db.commit()
|
||||
|
||||
inventory_data = {
|
||||
"gtin": "1234567890123",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 25,
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/inventory/add", headers=auth_headers, json=inventory_data
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["quantity"] == 75 # 50 + 25
|
||||
|
||||
def test_add_inventory_creates_new_if_not_exists(self, client, auth_headers):
|
||||
"""Test adding to nonexistent inventory creates new inventory entry"""
|
||||
inventory_data = {
|
||||
"gtin": "9999999999999",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 25,
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/inventory/add", headers=auth_headers, json=inventory_data
|
||||
)
|
||||
|
||||
# Your service creates new inventory if it doesn't exist (upsert behavior)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["gtin"] == "9999999999999"
|
||||
assert data["location"] == "WAREHOUSE_A"
|
||||
assert data["quantity"] == 25
|
||||
|
||||
def test_remove_inventory_success(self, client, auth_headers, db):
|
||||
"""Test removing from existing inventory successfully"""
|
||||
# Create initial inventory
|
||||
inventory = Inventory(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
db.add(inventory)
|
||||
db.commit()
|
||||
|
||||
inventory_data = {
|
||||
"gtin": "1234567890123",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 15,
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/inventory/remove", headers=auth_headers, json=inventory_data
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["quantity"] == 35 # 50 - 15
|
||||
|
||||
def test_remove_inventory_insufficient_returns_business_logic_error(self, client, auth_headers, db):
|
||||
"""Test removing more inventory than available returns InsufficientInventoryException"""
|
||||
# Create initial inventory
|
||||
inventory = Inventory(gtin="1234567890123", location="WAREHOUSE_A", quantity=10)
|
||||
db.add(inventory)
|
||||
db.commit()
|
||||
|
||||
inventory_data = {
|
||||
"gtin": "1234567890123",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 20,
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/inventory/remove", headers=auth_headers, json=inventory_data
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
data = response.json()
|
||||
assert data["error_code"] == "INSUFFICIENT_INVENTORY"
|
||||
assert data["status_code"] == 400
|
||||
assert "Insufficient inventory" in data["message"]
|
||||
assert data["details"]["gtin"] == "1234567890123"
|
||||
assert data["details"]["location"] == "WAREHOUSE_A"
|
||||
assert data["details"]["requested_quantity"] == 20
|
||||
assert data["details"]["available_quantity"] == 10
|
||||
|
||||
def test_remove_inventory_not_found(self, client, auth_headers):
|
||||
"""Test removing from nonexistent inventory returns InventoryNotFoundException"""
|
||||
inventory_data = {
|
||||
"gtin": "9999999999999",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 15,
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/inventory/remove", headers=auth_headers, json=inventory_data
|
||||
)
|
||||
|
||||
# This should actually return 404 since you can't remove from non-existent inventory
|
||||
# If it returns 200, your service might create inventory with negative quantity
|
||||
assert response.status_code == 404
|
||||
data = response.json()
|
||||
assert data["error_code"] == "INVENTORY_NOT_FOUND"
|
||||
assert data["status_code"] == 404
|
||||
|
||||
def test_negative_inventory_not_allowed_business_logic_error(self, client, auth_headers, db):
|
||||
"""Test operations resulting in negative inventory returns NegativeInventoryException"""
|
||||
# Create initial inventory
|
||||
inventory = Inventory(gtin="1234567890123", location="WAREHOUSE_A", quantity=5)
|
||||
db.add(inventory)
|
||||
db.commit()
|
||||
|
||||
inventory_data = {
|
||||
"gtin": "1234567890123",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 10,
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/inventory/remove", headers=auth_headers, json=inventory_data
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
data = response.json()
|
||||
# This might be caught as INSUFFICIENT_INVENTORY or NEGATIVE_INVENTORY_NOT_ALLOWED
|
||||
assert data["error_code"] in ["INSUFFICIENT_INVENTORY", "NEGATIVE_INVENTORY_NOT_ALLOWED"]
|
||||
assert data["status_code"] == 400
|
||||
|
||||
def test_get_inventory_by_gtin_success(self, client, auth_headers, db):
|
||||
"""Test getting inventory summary for GTIN successfully"""
|
||||
# Create inventory in multiple locations
|
||||
inventory1 = Inventory(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
inventory2 = Inventory(gtin="1234567890123", location="WAREHOUSE_B", quantity=25)
|
||||
db.add_all([inventory1, inventory2])
|
||||
db.commit()
|
||||
|
||||
response = client.get("/api/v1/inventory/1234567890123", headers=auth_headers)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["gtin"] == "1234567890123"
|
||||
assert data["total_quantity"] == 75
|
||||
assert len(data["locations"]) == 2
|
||||
|
||||
def test_get_inventory_by_gtin_not_found(self, client, auth_headers):
|
||||
"""Test getting inventory for nonexistent GTIN returns InventoryNotFoundException"""
|
||||
response = client.get("/api/v1/inventory/9999999999999", headers=auth_headers)
|
||||
|
||||
assert response.status_code == 404
|
||||
data = response.json()
|
||||
assert data["error_code"] == "INVENTORY_NOT_FOUND"
|
||||
assert data["status_code"] == 404
|
||||
assert "9999999999999" in data["message"]
|
||||
assert data["details"]["resource_type"] == "Inventory"
|
||||
assert data["details"]["identifier"] == "9999999999999"
|
||||
|
||||
def test_get_total_inventory_success(self, client, auth_headers, db):
|
||||
"""Test getting total inventory for GTIN successfully"""
|
||||
# Create inventory in multiple locations
|
||||
inventory1 = Inventory(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
inventory2 = Inventory(gtin="1234567890123", location="WAREHOUSE_B", quantity=25)
|
||||
db.add_all([inventory1, inventory2])
|
||||
db.commit()
|
||||
|
||||
response = client.get("/api/v1/inventory/1234567890123/total", headers=auth_headers)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["gtin"] == "1234567890123"
|
||||
assert data["total_quantity"] == 75
|
||||
assert data["locations_count"] == 2
|
||||
|
||||
def test_get_total_inventory_not_found(self, client, auth_headers):
|
||||
"""Test getting total inventory for nonexistent GTIN returns InventoryNotFoundException"""
|
||||
response = client.get("/api/v1/inventory/9999999999999/total", headers=auth_headers)
|
||||
|
||||
assert response.status_code == 404
|
||||
data = response.json()
|
||||
assert data["error_code"] == "INVENTORY_NOT_FOUND"
|
||||
assert data["status_code"] == 404
|
||||
|
||||
def test_get_all_inventory_success(self, client, auth_headers, db):
|
||||
"""Test getting all inventory entries successfully"""
|
||||
# Create some inventory entries
|
||||
inventory1 = Inventory(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
inventory2 = Inventory(gtin="9876543210987", location="WAREHOUSE_B", quantity=25)
|
||||
db.add_all([inventory1, inventory2])
|
||||
db.commit()
|
||||
|
||||
response = client.get("/api/v1/inventory", headers=auth_headers)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert len(data) >= 2
|
||||
|
||||
def test_get_all_inventory_with_filters(self, client, auth_headers, db):
|
||||
"""Test getting inventory entries with filtering"""
|
||||
# Create inventory entries
|
||||
inventory1 = Inventory(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
inventory2 = Inventory(gtin="9876543210987", location="WAREHOUSE_B", quantity=25)
|
||||
db.add_all([inventory1, inventory2])
|
||||
db.commit()
|
||||
|
||||
# Filter by location
|
||||
response = client.get("/api/v1/inventory?location=WAREHOUSE_A", headers=auth_headers)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
for inventory in data:
|
||||
assert inventory["location"] == "WAREHOUSE_A"
|
||||
|
||||
# Filter by GTIN
|
||||
response = client.get("/api/v1/inventory?gtin=1234567890123", headers=auth_headers)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
for inventory in data:
|
||||
assert inventory["gtin"] == "1234567890123"
|
||||
|
||||
def test_update_inventory_success(self, client, auth_headers, db):
|
||||
"""Test updating inventory quantity successfully"""
|
||||
# Create initial inventory
|
||||
inventory = Inventory(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
db.add(inventory)
|
||||
db.commit()
|
||||
db.refresh(inventory)
|
||||
|
||||
update_data = {"quantity": 75}
|
||||
|
||||
response = client.put(
|
||||
f"/api/v1/inventory/{inventory.id}",
|
||||
headers=auth_headers,
|
||||
json=update_data,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["quantity"] == 75
|
||||
|
||||
def test_update_inventory_not_found(self, client, auth_headers):
|
||||
"""Test updating nonexistent inventory returns InventoryNotFoundException"""
|
||||
update_data = {"quantity": 75}
|
||||
|
||||
response = client.put(
|
||||
"/api/v1/inventory/99999",
|
||||
headers=auth_headers,
|
||||
json=update_data,
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
||||
data = response.json()
|
||||
assert data["error_code"] == "INVENTORY_NOT_FOUND"
|
||||
assert data["status_code"] == 404
|
||||
|
||||
def test_update_inventory_invalid_quantity(self, client, auth_headers, db):
|
||||
"""Test updating inventory with invalid quantity returns ValidationException"""
|
||||
# Create initial inventory
|
||||
inventory = Inventory(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
db.add(inventory)
|
||||
db.commit()
|
||||
db.refresh(inventory)
|
||||
|
||||
update_data = {"quantity": -10} # Negative quantity
|
||||
|
||||
response = client.put(
|
||||
f"/api/v1/inventory/{inventory.id}",
|
||||
headers=auth_headers,
|
||||
json=update_data,
|
||||
)
|
||||
|
||||
assert response.status_code == 422
|
||||
data = response.json()
|
||||
assert data["error_code"] == "INVALID_QUANTITY"
|
||||
assert data["status_code"] == 422
|
||||
assert "Quantity cannot be negative" in data["message"]
|
||||
assert data["details"]["field"] == "quantity"
|
||||
|
||||
def test_delete_inventory_success(self, client, auth_headers, db):
|
||||
"""Test deleting inventory entry successfully"""
|
||||
# Create initial inventory
|
||||
inventory = Inventory(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
db.add(inventory)
|
||||
db.commit()
|
||||
db.refresh(inventory)
|
||||
|
||||
response = client.delete(
|
||||
f"/api/v1/inventory/{inventory.id}",
|
||||
headers=auth_headers,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "deleted successfully" in response.json()["message"]
|
||||
|
||||
def test_delete_inventory_not_found(self, client, auth_headers):
|
||||
"""Test deleting nonexistent inventory returns InventoryNotFoundException"""
|
||||
response = client.delete(
|
||||
"/api/v1/inventory/99999",
|
||||
headers=auth_headers,
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
||||
data = response.json()
|
||||
assert data["error_code"] == "INVENTORY_NOT_FOUND"
|
||||
assert data["status_code"] == 404
|
||||
|
||||
def test_location_not_found_error(self, client, auth_headers):
|
||||
"""Test operations on nonexistent location returns LocationNotFoundException (if implemented)"""
|
||||
inventory_data = {
|
||||
"gtin": "1234567890123",
|
||||
"location": "NONEXISTENT_LOCATION",
|
||||
"quantity": 100,
|
||||
}
|
||||
|
||||
response = client.post("/api/v1/inventory", headers=auth_headers, json=inventory_data)
|
||||
|
||||
# This depends on whether your service validates locations
|
||||
if response.status_code == 404:
|
||||
data = response.json()
|
||||
assert data["error_code"] == "LOCATION_NOT_FOUND"
|
||||
assert data["status_code"] == 404
|
||||
|
||||
def test_invalid_inventory_operation_error(self, client, auth_headers):
|
||||
"""Test invalid inventory operations return InvalidInventoryOperationException"""
|
||||
# This would test business logic validation
|
||||
# The exact scenario depends on your business rules
|
||||
pass # Implementation depends on specific business rules
|
||||
|
||||
def test_get_inventory_without_auth_returns_invalid_token(self, client):
|
||||
"""Test that inventory endpoints require authentication returns InvalidTokenException"""
|
||||
response = client.get("/api/v1/inventory")
|
||||
|
||||
assert response.status_code == 401
|
||||
data = response.json()
|
||||
assert data["error_code"] == "INVALID_TOKEN"
|
||||
assert data["status_code"] == 401
|
||||
|
||||
def test_pagination_validation_errors(self, client, auth_headers):
|
||||
"""Test pagination parameter validation"""
|
||||
# Test negative skip
|
||||
response = client.get("/api/v1/inventory?skip=-1", headers=auth_headers)
|
||||
assert response.status_code == 422
|
||||
data = response.json()
|
||||
assert data["error_code"] == "VALIDATION_ERROR"
|
||||
|
||||
# Test zero limit
|
||||
response = client.get("/api/v1/inventory?limit=0", headers=auth_headers)
|
||||
assert response.status_code == 422
|
||||
data = response.json()
|
||||
assert data["error_code"] == "VALIDATION_ERROR"
|
||||
|
||||
# Test excessive limit
|
||||
response = client.get("/api/v1/inventory?limit=10000", headers=auth_headers)
|
||||
assert response.status_code == 422
|
||||
data = response.json()
|
||||
assert data["error_code"] == "VALIDATION_ERROR"
|
||||
|
||||
def test_exception_structure_consistency(self, client, auth_headers):
|
||||
"""Test that all inventory exceptions follow the consistent LetzShopException structure"""
|
||||
# Test with a known error case
|
||||
response = client.get("/api/v1/inventory/9999999999999", headers=auth_headers)
|
||||
|
||||
assert response.status_code == 404
|
||||
data = response.json()
|
||||
|
||||
# Verify exception structure matches LetzShopException.to_dict()
|
||||
required_fields = ["error_code", "message", "status_code"]
|
||||
for field in required_fields:
|
||||
assert field in data, f"Missing required field: {field}"
|
||||
|
||||
assert isinstance(data["error_code"], str)
|
||||
assert isinstance(data["message"], str)
|
||||
assert isinstance(data["status_code"], int)
|
||||
|
||||
# Details field should be present for domain-specific exceptions
|
||||
if "details" in data:
|
||||
assert isinstance(data["details"], dict)
|
||||
@@ -11,7 +11,7 @@ class TestMarketplaceImportJobAPI:
|
||||
def test_import_from_marketplace(self, client, auth_headers, test_vendor, test_user):
|
||||
"""Test marketplace import endpoint - just test job creation"""
|
||||
# Ensure user owns the vendor
|
||||
test_vendor.owner_id = test_user.id
|
||||
test_vendor.owner_user_id = test_user.id
|
||||
|
||||
import_data = {
|
||||
"url": "https://example.com/products.csv",
|
||||
@@ -51,7 +51,7 @@ class TestMarketplaceImportJobAPI:
|
||||
def test_import_from_marketplace_unauthorized_vendor(self, client, auth_headers, test_vendor, other_user):
|
||||
"""Test marketplace import with unauthorized vendor access"""
|
||||
# Set vendor owner to different user
|
||||
test_vendor.owner_id = other_user.id
|
||||
test_vendor.owner_user_id = other_user.id
|
||||
|
||||
import_data = {
|
||||
"url": "https://example.com/products.csv",
|
||||
@@ -410,7 +410,7 @@ class TestMarketplaceImportJobAPI:
|
||||
"""Test that rate limiting is applied to import endpoint"""
|
||||
# This test verifies that the rate_limit decorator is present
|
||||
# Actual rate limiting testing would require multiple requests
|
||||
test_vendor.owner_id = test_user.id
|
||||
test_vendor.owner_user_id = test_user.id
|
||||
|
||||
import_data = {
|
||||
"url": "https://example.com/products.csv",
|
||||
|
||||
@@ -85,7 +85,7 @@ class TestExportFunctionality:
|
||||
db.commit()
|
||||
|
||||
response = client.get(
|
||||
"/api/v1/marketplace/product?vendor_name=TestVendor1", headers=auth_headers
|
||||
"/api/v1/marketplace/product?name=TestVendor1", headers=auth_headers
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
@@ -121,7 +121,7 @@ class TestExportFunctionality:
|
||||
db.commit()
|
||||
|
||||
response = client.get(
|
||||
"/api/v1/marketplace/product?marketplace=Amazon&vendor_name=TestVendor",
|
||||
"/api/v1/marketplace/product?marketplace=Amazon&name=TestVendor",
|
||||
headers=auth_headers
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
@@ -57,7 +57,7 @@ class TestMarketplaceProductsAPI:
|
||||
"price": "15.99",
|
||||
"brand": "NewBrand",
|
||||
"gtin": "9876543210987",
|
||||
"availability": "in stock",
|
||||
"availability": "in inventory",
|
||||
"marketplace": "Amazon",
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ class TestMarketplaceProductsAPI:
|
||||
"price": "15.99",
|
||||
"brand": "NewBrand",
|
||||
"gtin": "9876543210987",
|
||||
"availability": "in stock",
|
||||
"availability": "in inventory",
|
||||
"marketplace": "Amazon",
|
||||
}
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ class TestPagination:
|
||||
vendor = Vendor(
|
||||
vendor_code=f"PAGEVENDOR{i:03d}_{unique_suffix}",
|
||||
vendor_name=f"Pagination Vendor {i}",
|
||||
owner_id=test_user.id,
|
||||
owner_user_id=test_user.id,
|
||||
is_active=True,
|
||||
)
|
||||
vendors.append(vendor)
|
||||
@@ -212,33 +212,33 @@ class TestPagination:
|
||||
assert data["skip"] == 0
|
||||
assert data["limit"] == 5
|
||||
|
||||
def test_stock_pagination_success(self, client, auth_headers, db):
|
||||
"""Test pagination for stock listing successfully"""
|
||||
def test_inventory_pagination_success(self, client, auth_headers, db):
|
||||
"""Test pagination for inventory listing successfully"""
|
||||
import uuid
|
||||
unique_suffix = str(uuid.uuid4())[:8]
|
||||
|
||||
# Create multiple stock entries
|
||||
from models.database.stock import Stock
|
||||
stocks = []
|
||||
# Create multiple inventory entries
|
||||
from models.database.inventory import Inventory
|
||||
inventory_entries = []
|
||||
for i in range(20):
|
||||
stock = Stock(
|
||||
inventory = Inventory(
|
||||
gtin=f"123456789{i:04d}",
|
||||
location=f"LOC_{unique_suffix}_{i}",
|
||||
quantity=10 + i,
|
||||
)
|
||||
stocks.append(stock)
|
||||
inventory_entries.append(inventory)
|
||||
|
||||
db.add_all(stocks)
|
||||
db.add_all(inventory_entries)
|
||||
db.commit()
|
||||
|
||||
# Test first page
|
||||
response = client.get("/api/v1/stock?limit=8&skip=0", headers=auth_headers)
|
||||
response = client.get("/api/v1/inventory?limit=8&skip=0", headers=auth_headers)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert len(data) == 8
|
||||
|
||||
# Test second page
|
||||
response = client.get("/api/v1/stock?limit=8&skip=8", headers=auth_headers)
|
||||
response = client.get("/api/v1/inventory?limit=8&skip=8", headers=auth_headers)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert len(data) == 8
|
||||
|
||||
@@ -1,455 +0,0 @@
|
||||
# tests/integration/api/v1/test_stock_endpoints.py
|
||||
import pytest
|
||||
|
||||
from models.database.stock import Stock
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
@pytest.mark.api
|
||||
@pytest.mark.stock
|
||||
class TestStockAPI:
|
||||
|
||||
def test_set_stock_new_success(self, client, auth_headers):
|
||||
"""Test setting stock for new GTIN successfully"""
|
||||
stock_data = {
|
||||
"gtin": "1234567890123",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 100,
|
||||
}
|
||||
|
||||
response = client.post("/api/v1/stock", headers=auth_headers, json=stock_data)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["gtin"] == "1234567890123"
|
||||
assert data["location"] == "WAREHOUSE_A"
|
||||
assert data["quantity"] == 100
|
||||
|
||||
def test_set_stock_existing_success(self, client, auth_headers, db):
|
||||
"""Test updating existing stock successfully"""
|
||||
# Create initial stock
|
||||
stock = Stock(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
db.add(stock)
|
||||
db.commit()
|
||||
|
||||
stock_data = {
|
||||
"gtin": "1234567890123",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 75,
|
||||
}
|
||||
|
||||
response = client.post("/api/v1/stock", headers=auth_headers, json=stock_data)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["quantity"] == 75 # Should be replaced, not added
|
||||
|
||||
def test_set_stock_invalid_gtin_validation_error(self, client, auth_headers):
|
||||
"""Test setting stock with invalid GTIN returns ValidationException"""
|
||||
stock_data = {
|
||||
"gtin": "", # Empty GTIN
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 100,
|
||||
}
|
||||
|
||||
response = client.post("/api/v1/stock", headers=auth_headers, json=stock_data)
|
||||
|
||||
assert response.status_code == 422
|
||||
data = response.json()
|
||||
assert data["error_code"] == "STOCK_VALIDATION_FAILED"
|
||||
assert data["status_code"] == 422
|
||||
assert "GTIN is required" in data["message"]
|
||||
|
||||
def test_set_stock_invalid_quantity_validation_error(self, client, auth_headers):
|
||||
"""Test setting stock with invalid quantity returns InvalidQuantityException"""
|
||||
stock_data = {
|
||||
"gtin": "1234567890123",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": -10, # Negative quantity
|
||||
}
|
||||
|
||||
response = client.post("/api/v1/stock", headers=auth_headers, json=stock_data)
|
||||
|
||||
assert response.status_code in [400, 422]
|
||||
data = response.json()
|
||||
assert data["error_code"] in ["INVALID_QUANTITY", "VALIDATION_ERROR"]
|
||||
if data["error_code"] == "INVALID_QUANTITY":
|
||||
assert data["status_code"] == 422
|
||||
assert data["details"]["field"] == "quantity"
|
||||
|
||||
def test_add_stock_success(self, client, auth_headers, db):
|
||||
"""Test adding to existing stock successfully"""
|
||||
# Create initial stock
|
||||
stock = Stock(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
db.add(stock)
|
||||
db.commit()
|
||||
|
||||
stock_data = {
|
||||
"gtin": "1234567890123",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 25,
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/stock/add", headers=auth_headers, json=stock_data
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["quantity"] == 75 # 50 + 25
|
||||
|
||||
def test_add_stock_creates_new_if_not_exists(self, client, auth_headers):
|
||||
"""Test adding to nonexistent stock creates new stock entry"""
|
||||
stock_data = {
|
||||
"gtin": "9999999999999",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 25,
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/stock/add", headers=auth_headers, json=stock_data
|
||||
)
|
||||
|
||||
# Your service creates new stock if it doesn't exist (upsert behavior)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["gtin"] == "9999999999999"
|
||||
assert data["location"] == "WAREHOUSE_A"
|
||||
assert data["quantity"] == 25
|
||||
|
||||
def test_remove_stock_success(self, client, auth_headers, db):
|
||||
"""Test removing from existing stock successfully"""
|
||||
# Create initial stock
|
||||
stock = Stock(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
db.add(stock)
|
||||
db.commit()
|
||||
|
||||
stock_data = {
|
||||
"gtin": "1234567890123",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 15,
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/stock/remove", headers=auth_headers, json=stock_data
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["quantity"] == 35 # 50 - 15
|
||||
|
||||
def test_remove_stock_insufficient_returns_business_logic_error(self, client, auth_headers, db):
|
||||
"""Test removing more stock than available returns InsufficientStockException"""
|
||||
# Create initial stock
|
||||
stock = Stock(gtin="1234567890123", location="WAREHOUSE_A", quantity=10)
|
||||
db.add(stock)
|
||||
db.commit()
|
||||
|
||||
stock_data = {
|
||||
"gtin": "1234567890123",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 20,
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/stock/remove", headers=auth_headers, json=stock_data
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
data = response.json()
|
||||
assert data["error_code"] == "INSUFFICIENT_STOCK"
|
||||
assert data["status_code"] == 400
|
||||
assert "Insufficient stock" in data["message"]
|
||||
assert data["details"]["gtin"] == "1234567890123"
|
||||
assert data["details"]["location"] == "WAREHOUSE_A"
|
||||
assert data["details"]["requested_quantity"] == 20
|
||||
assert data["details"]["available_quantity"] == 10
|
||||
|
||||
def test_remove_stock_not_found(self, client, auth_headers):
|
||||
"""Test removing from nonexistent stock returns StockNotFoundException"""
|
||||
stock_data = {
|
||||
"gtin": "9999999999999",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 15,
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/stock/remove", headers=auth_headers, json=stock_data
|
||||
)
|
||||
|
||||
# This should actually return 404 since you can't remove from non-existent stock
|
||||
# If it returns 200, your service might create stock with negative quantity
|
||||
assert response.status_code == 404
|
||||
data = response.json()
|
||||
assert data["error_code"] == "STOCK_NOT_FOUND"
|
||||
assert data["status_code"] == 404
|
||||
|
||||
def test_negative_stock_not_allowed_business_logic_error(self, client, auth_headers, db):
|
||||
"""Test operations resulting in negative stock returns NegativeStockException"""
|
||||
# Create initial stock
|
||||
stock = Stock(gtin="1234567890123", location="WAREHOUSE_A", quantity=5)
|
||||
db.add(stock)
|
||||
db.commit()
|
||||
|
||||
stock_data = {
|
||||
"gtin": "1234567890123",
|
||||
"location": "WAREHOUSE_A",
|
||||
"quantity": 10,
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
"/api/v1/stock/remove", headers=auth_headers, json=stock_data
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
data = response.json()
|
||||
# This might be caught as INSUFFICIENT_STOCK or NEGATIVE_STOCK_NOT_ALLOWED
|
||||
assert data["error_code"] in ["INSUFFICIENT_STOCK", "NEGATIVE_STOCK_NOT_ALLOWED"]
|
||||
assert data["status_code"] == 400
|
||||
|
||||
def test_get_stock_by_gtin_success(self, client, auth_headers, db):
|
||||
"""Test getting stock summary for GTIN successfully"""
|
||||
# Create stock in multiple locations
|
||||
stock1 = Stock(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
stock2 = Stock(gtin="1234567890123", location="WAREHOUSE_B", quantity=25)
|
||||
db.add_all([stock1, stock2])
|
||||
db.commit()
|
||||
|
||||
response = client.get("/api/v1/stock/1234567890123", headers=auth_headers)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["gtin"] == "1234567890123"
|
||||
assert data["total_quantity"] == 75
|
||||
assert len(data["locations"]) == 2
|
||||
|
||||
def test_get_stock_by_gtin_not_found(self, client, auth_headers):
|
||||
"""Test getting stock for nonexistent GTIN returns StockNotFoundException"""
|
||||
response = client.get("/api/v1/stock/9999999999999", headers=auth_headers)
|
||||
|
||||
assert response.status_code == 404
|
||||
data = response.json()
|
||||
assert data["error_code"] == "STOCK_NOT_FOUND"
|
||||
assert data["status_code"] == 404
|
||||
assert "9999999999999" in data["message"]
|
||||
assert data["details"]["resource_type"] == "Stock"
|
||||
assert data["details"]["identifier"] == "9999999999999"
|
||||
|
||||
def test_get_total_stock_success(self, client, auth_headers, db):
|
||||
"""Test getting total stock for GTIN successfully"""
|
||||
# Create stock in multiple locations
|
||||
stock1 = Stock(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
stock2 = Stock(gtin="1234567890123", location="WAREHOUSE_B", quantity=25)
|
||||
db.add_all([stock1, stock2])
|
||||
db.commit()
|
||||
|
||||
response = client.get("/api/v1/stock/1234567890123/total", headers=auth_headers)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["gtin"] == "1234567890123"
|
||||
assert data["total_quantity"] == 75
|
||||
assert data["locations_count"] == 2
|
||||
|
||||
def test_get_total_stock_not_found(self, client, auth_headers):
|
||||
"""Test getting total stock for nonexistent GTIN returns StockNotFoundException"""
|
||||
response = client.get("/api/v1/stock/9999999999999/total", headers=auth_headers)
|
||||
|
||||
assert response.status_code == 404
|
||||
data = response.json()
|
||||
assert data["error_code"] == "STOCK_NOT_FOUND"
|
||||
assert data["status_code"] == 404
|
||||
|
||||
def test_get_all_stock_success(self, client, auth_headers, db):
|
||||
"""Test getting all stock entries successfully"""
|
||||
# Create some stock entries
|
||||
stock1 = Stock(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
stock2 = Stock(gtin="9876543210987", location="WAREHOUSE_B", quantity=25)
|
||||
db.add_all([stock1, stock2])
|
||||
db.commit()
|
||||
|
||||
response = client.get("/api/v1/stock", headers=auth_headers)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert len(data) >= 2
|
||||
|
||||
def test_get_all_stock_with_filters(self, client, auth_headers, db):
|
||||
"""Test getting stock entries with filtering"""
|
||||
# Create stock entries
|
||||
stock1 = Stock(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
stock2 = Stock(gtin="9876543210987", location="WAREHOUSE_B", quantity=25)
|
||||
db.add_all([stock1, stock2])
|
||||
db.commit()
|
||||
|
||||
# Filter by location
|
||||
response = client.get("/api/v1/stock?location=WAREHOUSE_A", headers=auth_headers)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
for stock in data:
|
||||
assert stock["location"] == "WAREHOUSE_A"
|
||||
|
||||
# Filter by GTIN
|
||||
response = client.get("/api/v1/stock?gtin=1234567890123", headers=auth_headers)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
for stock in data:
|
||||
assert stock["gtin"] == "1234567890123"
|
||||
|
||||
def test_update_stock_success(self, client, auth_headers, db):
|
||||
"""Test updating stock quantity successfully"""
|
||||
# Create initial stock
|
||||
stock = Stock(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
db.add(stock)
|
||||
db.commit()
|
||||
db.refresh(stock)
|
||||
|
||||
update_data = {"quantity": 75}
|
||||
|
||||
response = client.put(
|
||||
f"/api/v1/stock/{stock.id}",
|
||||
headers=auth_headers,
|
||||
json=update_data,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["quantity"] == 75
|
||||
|
||||
def test_update_stock_not_found(self, client, auth_headers):
|
||||
"""Test updating nonexistent stock returns StockNotFoundException"""
|
||||
update_data = {"quantity": 75}
|
||||
|
||||
response = client.put(
|
||||
"/api/v1/stock/99999",
|
||||
headers=auth_headers,
|
||||
json=update_data,
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
||||
data = response.json()
|
||||
assert data["error_code"] == "STOCK_NOT_FOUND"
|
||||
assert data["status_code"] == 404
|
||||
|
||||
def test_update_stock_invalid_quantity(self, client, auth_headers, db):
|
||||
"""Test updating stock with invalid quantity returns ValidationException"""
|
||||
# Create initial stock
|
||||
stock = Stock(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
db.add(stock)
|
||||
db.commit()
|
||||
db.refresh(stock)
|
||||
|
||||
update_data = {"quantity": -10} # Negative quantity
|
||||
|
||||
response = client.put(
|
||||
f"/api/v1/stock/{stock.id}",
|
||||
headers=auth_headers,
|
||||
json=update_data,
|
||||
)
|
||||
|
||||
assert response.status_code == 422
|
||||
data = response.json()
|
||||
assert data["error_code"] == "INVALID_QUANTITY"
|
||||
assert data["status_code"] == 422
|
||||
assert "Quantity cannot be negative" in data["message"]
|
||||
assert data["details"]["field"] == "quantity"
|
||||
|
||||
def test_delete_stock_success(self, client, auth_headers, db):
|
||||
"""Test deleting stock entry successfully"""
|
||||
# Create initial stock
|
||||
stock = Stock(gtin="1234567890123", location="WAREHOUSE_A", quantity=50)
|
||||
db.add(stock)
|
||||
db.commit()
|
||||
db.refresh(stock)
|
||||
|
||||
response = client.delete(
|
||||
f"/api/v1/stock/{stock.id}",
|
||||
headers=auth_headers,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "deleted successfully" in response.json()["message"]
|
||||
|
||||
def test_delete_stock_not_found(self, client, auth_headers):
|
||||
"""Test deleting nonexistent stock returns StockNotFoundException"""
|
||||
response = client.delete(
|
||||
"/api/v1/stock/99999",
|
||||
headers=auth_headers,
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
||||
data = response.json()
|
||||
assert data["error_code"] == "STOCK_NOT_FOUND"
|
||||
assert data["status_code"] == 404
|
||||
|
||||
def test_location_not_found_error(self, client, auth_headers):
|
||||
"""Test operations on nonexistent location returns LocationNotFoundException (if implemented)"""
|
||||
stock_data = {
|
||||
"gtin": "1234567890123",
|
||||
"location": "NONEXISTENT_LOCATION",
|
||||
"quantity": 100,
|
||||
}
|
||||
|
||||
response = client.post("/api/v1/stock", headers=auth_headers, json=stock_data)
|
||||
|
||||
# This depends on whether your service validates locations
|
||||
if response.status_code == 404:
|
||||
data = response.json()
|
||||
assert data["error_code"] == "LOCATION_NOT_FOUND"
|
||||
assert data["status_code"] == 404
|
||||
|
||||
def test_invalid_stock_operation_error(self, client, auth_headers):
|
||||
"""Test invalid stock operations return InvalidStockOperationException"""
|
||||
# This would test business logic validation
|
||||
# The exact scenario depends on your business rules
|
||||
pass # Implementation depends on specific business rules
|
||||
|
||||
def test_get_stock_without_auth_returns_invalid_token(self, client):
|
||||
"""Test that stock endpoints require authentication returns InvalidTokenException"""
|
||||
response = client.get("/api/v1/stock")
|
||||
|
||||
assert response.status_code == 401
|
||||
data = response.json()
|
||||
assert data["error_code"] == "INVALID_TOKEN"
|
||||
assert data["status_code"] == 401
|
||||
|
||||
def test_pagination_validation_errors(self, client, auth_headers):
|
||||
"""Test pagination parameter validation"""
|
||||
# Test negative skip
|
||||
response = client.get("/api/v1/stock?skip=-1", headers=auth_headers)
|
||||
assert response.status_code == 422
|
||||
data = response.json()
|
||||
assert data["error_code"] == "VALIDATION_ERROR"
|
||||
|
||||
# Test zero limit
|
||||
response = client.get("/api/v1/stock?limit=0", headers=auth_headers)
|
||||
assert response.status_code == 422
|
||||
data = response.json()
|
||||
assert data["error_code"] == "VALIDATION_ERROR"
|
||||
|
||||
# Test excessive limit
|
||||
response = client.get("/api/v1/stock?limit=10000", headers=auth_headers)
|
||||
assert response.status_code == 422
|
||||
data = response.json()
|
||||
assert data["error_code"] == "VALIDATION_ERROR"
|
||||
|
||||
def test_exception_structure_consistency(self, client, auth_headers):
|
||||
"""Test that all stock exceptions follow the consistent LetzShopException structure"""
|
||||
# Test with a known error case
|
||||
response = client.get("/api/v1/stock/9999999999999", headers=auth_headers)
|
||||
|
||||
assert response.status_code == 404
|
||||
data = response.json()
|
||||
|
||||
# Verify exception structure matches LetzShopException.to_dict()
|
||||
required_fields = ["error_code", "message", "status_code"]
|
||||
for field in required_fields:
|
||||
assert field in data, f"Missing required field: {field}"
|
||||
|
||||
assert isinstance(data["error_code"], str)
|
||||
assert isinstance(data["message"], str)
|
||||
assert isinstance(data["status_code"], int)
|
||||
|
||||
# Details field should be present for domain-specific exceptions
|
||||
if "details" in data:
|
||||
assert isinstance(data["details"], dict)
|
||||
@@ -11,7 +11,7 @@ class TestVendorsAPI:
|
||||
"""Test creating a new vendor successfully"""
|
||||
vendor_data = {
|
||||
"vendor_code": "NEWVENDOR001",
|
||||
"vendor_name": "New Vendor",
|
||||
"name": "New Vendor",
|
||||
"description": "A new test vendor ",
|
||||
}
|
||||
|
||||
@@ -20,14 +20,14 @@ class TestVendorsAPI:
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["vendor_code"] == "NEWVENDOR001"
|
||||
assert data["vendor_name"] == "New Vendor"
|
||||
assert data["name"] == "New Vendor"
|
||||
assert data["is_active"] is True
|
||||
|
||||
def test_create_vendor_duplicate_code_returns_conflict(self, client, auth_headers, test_vendor):
|
||||
"""Test creating vendor with duplicate code returns VendorAlreadyExistsException"""
|
||||
vendor_data = {
|
||||
"vendor_code": test_vendor.vendor_code,
|
||||
"vendor_name": "Different Name",
|
||||
"name": "Different Name",
|
||||
"description": "Different description",
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ class TestVendorsAPI:
|
||||
def test_create_vendor_missing_vendor_code_validation_error(self, client, auth_headers):
|
||||
"""Test creating vendor without vendor_code returns ValidationException"""
|
||||
vendor_data = {
|
||||
"vendor_name": "Vendor without Code",
|
||||
"name": "Vendor without Code",
|
||||
"description": "Missing vendor code",
|
||||
}
|
||||
|
||||
@@ -57,10 +57,10 @@ class TestVendorsAPI:
|
||||
assert "validation_errors" in data["details"]
|
||||
|
||||
def test_create_vendor_empty_vendor_name_validation_error(self, client, auth_headers):
|
||||
"""Test creating vendor with empty vendor_name returns VendorValidationException"""
|
||||
"""Test creating vendor with empty name returns VendorValidationException"""
|
||||
vendor_data = {
|
||||
"vendor_code": "EMPTYNAME",
|
||||
"vendor_name": "", # Empty vendor name
|
||||
"name": "", # Empty vendor name
|
||||
"description": "Vendor with empty name",
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ class TestVendorsAPI:
|
||||
assert data["error_code"] == "INVALID_VENDOR_DATA"
|
||||
assert data["status_code"] == 422
|
||||
assert "Vendor name is required" in data["message"]
|
||||
assert data["details"]["field"] == "vendor_name"
|
||||
assert data["details"]["field"] == "name"
|
||||
|
||||
def test_create_vendor_max_vendors_reached_business_logic_error(self, client, auth_headers, db, test_user):
|
||||
"""Test creating vendor when max vendors reached returns MaxVendorsReachedException"""
|
||||
@@ -121,7 +121,7 @@ class TestVendorsAPI:
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["vendor_code"] == test_vendor.vendor_code
|
||||
assert data["vendor_name"] == test_vendor.vendor_name
|
||||
assert data["name"] == test_vendor.name
|
||||
|
||||
def test_get_vendor_by_code_not_found(self, client, auth_headers):
|
||||
"""Test getting nonexistent vendor returns VendorNotFoundException"""
|
||||
@@ -139,7 +139,7 @@ class TestVendorsAPI:
|
||||
"""Test accessing vendor owned by another user returns UnauthorizedVendorAccessException"""
|
||||
# Change vendor owner to other user AND make it unverified/inactive
|
||||
# so that non-owner users cannot access it
|
||||
test_vendor.owner_id = other_user.id
|
||||
test_vendor.owner_user_id = other_user.id
|
||||
test_vendor.is_verified = False # Make it not publicly accessible
|
||||
db.commit()
|
||||
|
||||
@@ -179,7 +179,7 @@ class TestVendorsAPI:
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["vendor_code"] == verified_vendor.vendor_code
|
||||
assert data["vendor_name"] == verified_vendor.vendor_name
|
||||
assert data["name"] == verified_vendor.name
|
||||
|
||||
def test_add_product_to_vendor_success(self, client, auth_headers, test_vendor, unique_product):
|
||||
"""Test adding product to vendor successfully"""
|
||||
|
||||
Reference in New Issue
Block a user