fix: resolve frontend/backend integration bugs
- Rename skincare route prefix /skin-snapshots → /skincare to match API client - Add redirect_slashes=False to FastAPI app; change collection routes from "/" to "" to eliminate 307 redirects on POST/GET without trailing slash - Fix redirect() inside try/catch in products/new and routines/new server actions (SvelteKit redirect() throws and was being caught as a 500 error) - Eagerly load inventory and steps relationships via explicit SELECT + model_dump(mode="json"), working around SQLModel 0.0.37 not serializing Relationship fields in response_model - Add field_validator for product_effect_profile to coerce DB-returned dict → ProductEffectProfile, eliminating Pydantic serializer warning - Update all tests to use routes without trailing slash Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
8d4f9d1fc6
commit
9bf94a979c
11 changed files with 85 additions and 68 deletions
|
|
@ -2,7 +2,7 @@ import uuid
|
|||
|
||||
|
||||
def test_create_minimal(client, product_data):
|
||||
r = client.post("/products/", json=product_data)
|
||||
r = client.post("/products", json=product_data)
|
||||
assert r.status_code == 201
|
||||
data = r.json()
|
||||
assert "id" in data
|
||||
|
|
@ -15,7 +15,7 @@ def test_create_with_actives(client, product_data):
|
|||
product_data["actives"] = [
|
||||
{"name": "Niacinamide", "percent": 10.0, "functions": ["niacinamide"]}
|
||||
]
|
||||
r = client.post("/products/", json=product_data)
|
||||
r = client.post("/products", json=product_data)
|
||||
assert r.status_code == 201
|
||||
data = r.json()
|
||||
assert len(data["actives"]) == 1
|
||||
|
|
@ -25,24 +25,24 @@ def test_create_with_actives(client, product_data):
|
|||
|
||||
def test_create_invalid_enum(client, product_data):
|
||||
product_data["category"] = "not_a_category"
|
||||
r = client.post("/products/", json=product_data)
|
||||
r = client.post("/products", json=product_data)
|
||||
assert r.status_code == 422
|
||||
|
||||
|
||||
def test_create_missing_required(client, product_data):
|
||||
del product_data["name"]
|
||||
r = client.post("/products/", json=product_data)
|
||||
r = client.post("/products", json=product_data)
|
||||
assert r.status_code == 422
|
||||
|
||||
|
||||
def test_list_empty(client):
|
||||
r = client.get("/products/")
|
||||
r = client.get("/products")
|
||||
assert r.status_code == 200
|
||||
assert r.json() == []
|
||||
|
||||
|
||||
def test_list_returns_created(client, created_product):
|
||||
r = client.get("/products/")
|
||||
r = client.get("/products")
|
||||
assert r.status_code == 200
|
||||
ids = [p["id"] for p in r.json()]
|
||||
assert created_product["id"] in ids
|
||||
|
|
@ -56,12 +56,12 @@ def test_list_filter_category(client, client_and_data=None):
|
|||
"recommended_time": "both",
|
||||
"leave_on": True,
|
||||
}
|
||||
r1 = client.post("/products/", json={**base, "name": "Moist", "category": "moisturizer"})
|
||||
r2 = client.post("/products/", json={**base, "name": "Ser", "category": "serum"})
|
||||
r1 = client.post("/products", json={**base, "name": "Moist", "category": "moisturizer"})
|
||||
r2 = client.post("/products", json={**base, "name": "Ser", "category": "serum"})
|
||||
assert r1.status_code == 201
|
||||
assert r2.status_code == 201
|
||||
|
||||
r = client.get("/products/?category=moisturizer")
|
||||
r = client.get("/products?category=moisturizer")
|
||||
assert r.status_code == 200
|
||||
data = r.json()
|
||||
assert all(p["category"] == "moisturizer" for p in data)
|
||||
|
|
@ -77,10 +77,10 @@ def test_list_filter_brand(client):
|
|||
"leave_on": True,
|
||||
"category": "serum",
|
||||
}
|
||||
client.post("/products/", json={**base, "name": "A1", "brand": "BrandA"})
|
||||
client.post("/products/", json={**base, "name": "B1", "brand": "BrandB"})
|
||||
client.post("/products", json={**base, "name": "A1", "brand": "BrandA"})
|
||||
client.post("/products", json={**base, "name": "B1", "brand": "BrandB"})
|
||||
|
||||
r = client.get("/products/?brand=BrandA")
|
||||
r = client.get("/products?brand=BrandA")
|
||||
assert r.status_code == 200
|
||||
data = r.json()
|
||||
assert all(p["brand"] == "BrandA" for p in data)
|
||||
|
|
@ -95,14 +95,14 @@ def test_list_filter_is_medication(client):
|
|||
"leave_on": True,
|
||||
"category": "serum",
|
||||
}
|
||||
client.post("/products/", json={**base, "name": "Normal", "is_medication": False})
|
||||
client.post("/products", json={**base, "name": "Normal", "is_medication": False})
|
||||
# is_medication=True requires usage_notes (model validator)
|
||||
client.post(
|
||||
"/products/",
|
||||
"/products",
|
||||
json={**base, "name": "Med", "is_medication": True, "usage_notes": "Apply pea-sized amount"},
|
||||
)
|
||||
|
||||
r = client.get("/products/?is_medication=true")
|
||||
r = client.get("/products?is_medication=true")
|
||||
assert r.status_code == 200
|
||||
data = r.json()
|
||||
assert all(p["is_medication"] is True for p in data)
|
||||
|
|
@ -118,10 +118,10 @@ def test_list_filter_targets(client):
|
|||
"leave_on": True,
|
||||
"category": "serum",
|
||||
}
|
||||
client.post("/products/", json={**base, "name": "Acne", "targets": ["acne"]})
|
||||
client.post("/products/", json={**base, "name": "Aging", "targets": ["aging"]})
|
||||
client.post("/products", json={**base, "name": "Acne", "targets": ["acne"]})
|
||||
client.post("/products", json={**base, "name": "Aging", "targets": ["aging"]})
|
||||
|
||||
r = client.get("/products/?targets=acne")
|
||||
r = client.get("/products?targets=acne")
|
||||
assert r.status_code == 200
|
||||
data = r.json()
|
||||
assert len(data) == 1
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue