fix: correct tojson|safe usage in templates and update validator
- Remove |safe from |tojson in HTML attributes (x-data) - quotes must become " for browsers to parse correctly - Update LANG-002 and LANG-003 architecture rules to document correct |tojson usage patterns: - HTML attributes: |tojson (no |safe) - Script blocks: |tojson|safe - Fix validator to warn when |tojson|safe is used in x-data (breaks HTML attribute parsing) - Improve code quality across services, APIs, and tests 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -90,7 +90,9 @@ class TestVendorDashboardAPI:
|
||||
db.commit()
|
||||
|
||||
# Get stats for vendor
|
||||
response = client.get("/api/v1/vendor/dashboard/stats", headers=vendor_user_headers)
|
||||
response = client.get(
|
||||
"/api/v1/vendor/dashboard/stats", headers=vendor_user_headers
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
Tests the /api/v1/vendor/inventory/* endpoints.
|
||||
All endpoints require vendor JWT authentication.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@@ -14,11 +15,17 @@ class TestVendorInventoryAPI:
|
||||
"""Test vendor inventory management endpoints at /api/v1/vendor/inventory/*."""
|
||||
|
||||
def test_set_inventory_success(
|
||||
self, client, vendor_user_headers, test_vendor_with_vendor_user, test_product, db
|
||||
self,
|
||||
client,
|
||||
vendor_user_headers,
|
||||
test_vendor_with_vendor_user,
|
||||
test_product,
|
||||
db,
|
||||
):
|
||||
"""Test setting inventory for a product."""
|
||||
# Ensure test_product belongs to the vendor
|
||||
from models.database.product import Product
|
||||
|
||||
product = db.query(Product).filter(Product.id == test_product.id).first()
|
||||
product.vendor_id = test_vendor_with_vendor_user.id
|
||||
db.commit()
|
||||
@@ -41,10 +48,16 @@ class TestVendorInventoryAPI:
|
||||
assert data["quantity"] == 100
|
||||
|
||||
def test_adjust_inventory_success(
|
||||
self, client, vendor_user_headers, test_vendor_with_vendor_user, test_product, db
|
||||
self,
|
||||
client,
|
||||
vendor_user_headers,
|
||||
test_vendor_with_vendor_user,
|
||||
test_product,
|
||||
db,
|
||||
):
|
||||
"""Test adjusting inventory quantity."""
|
||||
from models.database.product import Product
|
||||
|
||||
product = db.query(Product).filter(Product.id == test_product.id).first()
|
||||
product.vendor_id = test_vendor_with_vendor_user.id
|
||||
db.commit()
|
||||
@@ -102,10 +115,16 @@ class TestVendorInventoryAPI:
|
||||
assert "total" in data
|
||||
|
||||
def test_get_product_inventory_success(
|
||||
self, client, vendor_user_headers, test_vendor_with_vendor_user, test_product, db
|
||||
self,
|
||||
client,
|
||||
vendor_user_headers,
|
||||
test_vendor_with_vendor_user,
|
||||
test_product,
|
||||
db,
|
||||
):
|
||||
"""Test getting inventory for a specific product."""
|
||||
from models.database.product import Product
|
||||
|
||||
product = db.query(Product).filter(Product.id == test_product.id).first()
|
||||
product.vendor_id = test_vendor_with_vendor_user.id
|
||||
db.commit()
|
||||
@@ -128,10 +147,16 @@ class TestVendorInventoryAPI:
|
||||
assert data["error_code"] == "INVALID_TOKEN"
|
||||
|
||||
def test_reserve_inventory_success(
|
||||
self, client, vendor_user_headers, test_vendor_with_vendor_user, test_product, db
|
||||
self,
|
||||
client,
|
||||
vendor_user_headers,
|
||||
test_vendor_with_vendor_user,
|
||||
test_product,
|
||||
db,
|
||||
):
|
||||
"""Test reserving inventory for an order."""
|
||||
from models.database.product import Product
|
||||
|
||||
product = db.query(Product).filter(Product.id == test_product.id).first()
|
||||
product.vendor_id = test_vendor_with_vendor_user.id
|
||||
db.commit()
|
||||
@@ -165,11 +190,15 @@ class TestVendorInventoryAPI:
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_update_inventory_success(
|
||||
self, client, vendor_user_headers, test_vendor_with_vendor_user, test_product, db
|
||||
self,
|
||||
client,
|
||||
vendor_user_headers,
|
||||
test_vendor_with_vendor_user,
|
||||
test_product,
|
||||
db,
|
||||
):
|
||||
"""Test updating inventory record."""
|
||||
from models.database.product import Product
|
||||
from models.database.inventory import Inventory
|
||||
|
||||
product = db.query(Product).filter(Product.id == test_product.id).first()
|
||||
product.vendor_id = test_vendor_with_vendor_user.id
|
||||
@@ -203,7 +232,12 @@ class TestVendorInventoryAPI:
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_delete_inventory_success(
|
||||
self, client, vendor_user_headers, test_vendor_with_vendor_user, test_product, db
|
||||
self,
|
||||
client,
|
||||
vendor_user_headers,
|
||||
test_vendor_with_vendor_user,
|
||||
test_product,
|
||||
db,
|
||||
):
|
||||
"""Test deleting inventory record."""
|
||||
from models.database.product import Product
|
||||
|
||||
11
tests/integration/api/v1/vendor/test_letzshop.py
vendored
11
tests/integration/api/v1/vendor/test_letzshop.py
vendored
@@ -8,8 +8,9 @@ Tests cover:
|
||||
3. Order listing
|
||||
"""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
@@ -524,11 +525,11 @@ class TestVendorLetzshopExportAPI:
|
||||
self, client, db, vendor_user_headers, test_vendor_with_vendor_user
|
||||
):
|
||||
"""Test exporting products with actual data."""
|
||||
from models.database.product import Product
|
||||
from models.database.marketplace_product import MarketplaceProduct
|
||||
from models.database.marketplace_product_translation import (
|
||||
MarketplaceProductTranslation,
|
||||
)
|
||||
from models.database.product import Product
|
||||
|
||||
# Create marketplace product
|
||||
mp = MarketplaceProduct(
|
||||
@@ -577,11 +578,11 @@ class TestVendorLetzshopExportAPI:
|
||||
self, client, db, vendor_user_headers, test_vendor_with_vendor_user
|
||||
):
|
||||
"""Test exporting products in French."""
|
||||
from models.database.product import Product
|
||||
from models.database.marketplace_product import MarketplaceProduct
|
||||
from models.database.marketplace_product_translation import (
|
||||
MarketplaceProductTranslation,
|
||||
)
|
||||
from models.database.product import Product
|
||||
|
||||
mp = MarketplaceProduct(
|
||||
marketplace_product_id="VENDOR-FR-001",
|
||||
@@ -623,11 +624,11 @@ class TestVendorLetzshopExportAPI:
|
||||
self, client, db, vendor_user_headers, test_vendor_with_vendor_user
|
||||
):
|
||||
"""Test exporting products in German."""
|
||||
from models.database.product import Product
|
||||
from models.database.marketplace_product import MarketplaceProduct
|
||||
from models.database.marketplace_product_translation import (
|
||||
MarketplaceProductTranslation,
|
||||
)
|
||||
from models.database.product import Product
|
||||
|
||||
mp = MarketplaceProduct(
|
||||
marketplace_product_id="VENDOR-DE-001",
|
||||
@@ -667,11 +668,11 @@ class TestVendorLetzshopExportAPI:
|
||||
self, client, db, vendor_user_headers, test_vendor_with_vendor_user
|
||||
):
|
||||
"""Test exporting including inactive products."""
|
||||
from models.database.product import Product
|
||||
from models.database.marketplace_product import MarketplaceProduct
|
||||
from models.database.marketplace_product_translation import (
|
||||
MarketplaceProductTranslation,
|
||||
)
|
||||
from models.database.product import Product
|
||||
|
||||
mp = MarketplaceProduct(
|
||||
marketplace_product_id="VENDOR-INACTIVE-001",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
Tests the /api/v1/vendor/marketplace/* endpoints.
|
||||
All endpoints require vendor JWT authentication.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@@ -78,8 +79,12 @@ class TestVendorMarketplaceImportJobAPI:
|
||||
"""Test vendor marketplace import job management."""
|
||||
|
||||
def test_get_import_job_success(
|
||||
self, client, vendor_user_headers, test_vendor_with_vendor_user,
|
||||
test_marketplace_import_job, db
|
||||
self,
|
||||
client,
|
||||
vendor_user_headers,
|
||||
test_vendor_with_vendor_user,
|
||||
test_marketplace_import_job,
|
||||
db,
|
||||
):
|
||||
"""Test getting import job status by ID."""
|
||||
# Ensure the import job belongs to the vendor
|
||||
|
||||
53
tests/integration/api/v1/vendor/test_products.py
vendored
53
tests/integration/api/v1/vendor/test_products.py
vendored
@@ -4,6 +4,7 @@
|
||||
Tests the /api/v1/vendor/products/* endpoints.
|
||||
All endpoints require vendor JWT authentication.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@@ -40,11 +41,17 @@ class TestVendorProductsAPI:
|
||||
assert data["marketplace_product"]["id"] == unique_product.id
|
||||
|
||||
def test_add_product_duplicate_returns_error(
|
||||
self, client, vendor_user_headers, test_vendor_with_vendor_user, test_product, db
|
||||
self,
|
||||
client,
|
||||
vendor_user_headers,
|
||||
test_vendor_with_vendor_user,
|
||||
test_product,
|
||||
db,
|
||||
):
|
||||
"""Test adding product that already exists returns error."""
|
||||
# Ensure test_product belongs to the vendor
|
||||
from models.database.product import Product
|
||||
|
||||
product = db.query(Product).filter(Product.id == test_product.id).first()
|
||||
product.vendor_id = test_vendor_with_vendor_user.id
|
||||
db.commit()
|
||||
@@ -65,9 +72,7 @@ class TestVendorProductsAPI:
|
||||
data = response.json()
|
||||
assert data["error_code"] in ["PRODUCT_ALREADY_EXISTS", "VALIDATION_ERROR"]
|
||||
|
||||
def test_add_nonexistent_product_returns_error(
|
||||
self, client, vendor_user_headers
|
||||
):
|
||||
def test_add_nonexistent_product_returns_error(self, client, vendor_user_headers):
|
||||
"""Test adding nonexistent marketplace product returns error."""
|
||||
product_data = {
|
||||
"marketplace_product_id": 99999,
|
||||
@@ -126,11 +131,17 @@ class TestVendorProductsAPI:
|
||||
assert data["error_code"] == "INVALID_TOKEN"
|
||||
|
||||
def test_get_product_detail_success(
|
||||
self, client, vendor_user_headers, test_vendor_with_vendor_user, test_product, db
|
||||
self,
|
||||
client,
|
||||
vendor_user_headers,
|
||||
test_vendor_with_vendor_user,
|
||||
test_product,
|
||||
db,
|
||||
):
|
||||
"""Test getting product details."""
|
||||
# Ensure test_product belongs to the vendor
|
||||
from models.database.product import Product
|
||||
|
||||
product = db.query(Product).filter(Product.id == test_product.id).first()
|
||||
product.vendor_id = test_vendor_with_vendor_user.id
|
||||
db.commit()
|
||||
@@ -154,11 +165,17 @@ class TestVendorProductsAPI:
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_update_product_success(
|
||||
self, client, vendor_user_headers, test_vendor_with_vendor_user, test_product, db
|
||||
self,
|
||||
client,
|
||||
vendor_user_headers,
|
||||
test_vendor_with_vendor_user,
|
||||
test_product,
|
||||
db,
|
||||
):
|
||||
"""Test updating product details."""
|
||||
# Ensure test_product belongs to the vendor
|
||||
from models.database.product import Product
|
||||
|
||||
product = db.query(Product).filter(Product.id == test_product.id).first()
|
||||
product.vendor_id = test_vendor_with_vendor_user.id
|
||||
db.commit()
|
||||
@@ -180,11 +197,17 @@ class TestVendorProductsAPI:
|
||||
assert data["is_featured"] is True
|
||||
|
||||
def test_toggle_product_active(
|
||||
self, client, vendor_user_headers, test_vendor_with_vendor_user, test_product, db
|
||||
self,
|
||||
client,
|
||||
vendor_user_headers,
|
||||
test_vendor_with_vendor_user,
|
||||
test_product,
|
||||
db,
|
||||
):
|
||||
"""Test toggling product active status."""
|
||||
# Ensure test_product belongs to the vendor
|
||||
from models.database.product import Product
|
||||
|
||||
product = db.query(Product).filter(Product.id == test_product.id).first()
|
||||
product.vendor_id = test_vendor_with_vendor_user.id
|
||||
db.commit()
|
||||
@@ -200,11 +223,17 @@ class TestVendorProductsAPI:
|
||||
assert "message" in data
|
||||
|
||||
def test_toggle_product_featured(
|
||||
self, client, vendor_user_headers, test_vendor_with_vendor_user, test_product, db
|
||||
self,
|
||||
client,
|
||||
vendor_user_headers,
|
||||
test_vendor_with_vendor_user,
|
||||
test_product,
|
||||
db,
|
||||
):
|
||||
"""Test toggling product featured status."""
|
||||
# Ensure test_product belongs to the vendor
|
||||
from models.database.product import Product
|
||||
|
||||
product = db.query(Product).filter(Product.id == test_product.id).first()
|
||||
product.vendor_id = test_vendor_with_vendor_user.id
|
||||
db.commit()
|
||||
@@ -220,11 +249,17 @@ class TestVendorProductsAPI:
|
||||
assert "message" in data
|
||||
|
||||
def test_delete_product_success(
|
||||
self, client, vendor_user_headers, test_vendor_with_vendor_user, test_product, db
|
||||
self,
|
||||
client,
|
||||
vendor_user_headers,
|
||||
test_vendor_with_vendor_user,
|
||||
test_product,
|
||||
db,
|
||||
):
|
||||
"""Test removing product from catalog."""
|
||||
# Ensure test_product belongs to the vendor
|
||||
from models.database.product import Product
|
||||
|
||||
product = db.query(Product).filter(Product.id == test_product.id).first()
|
||||
product.vendor_id = test_vendor_with_vendor_user.id
|
||||
db.commit()
|
||||
|
||||
Reference in New Issue
Block a user