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:
2025-12-13 22:59:51 +01:00
parent 94d268f330
commit 9920430b9e
123 changed files with 1408 additions and 840 deletions

View File

@@ -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()

View File

@@ -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

View File

@@ -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",

View File

@@ -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

View File

@@ -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()