feat(api): GET /api/products/export — streamed canonical CSV, 409 empty_catalog (§6.4, PUC-9)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 22:05:55 -07:00
parent 1c2a6af986
commit 155f9bd147
2 changed files with 62 additions and 1 deletions
+40
View File
@@ -93,3 +93,43 @@ def test_sample_csv_imports_clean(fresh_db_url):
sample = client.get("/api/products/sample.csv").content
body = _upload(client, sample, "sample.csv").json()
assert body["summary"]["errors"] == 0 and body["summary"]["adds"] == 2
def test_export_returns_canonical_csv(fresh_db_url):
with _merchant_client(fresh_db_url) as client:
draft = _upload(client).json()
client.post(f"/api/products/imports/drafts/{draft['id']}/confirm")
resp = client.get("/api/products/export")
assert resp.status_code == 200
assert resp.headers["content-type"].startswith("text/csv")
assert "attachment" in resp.headers["content-disposition"]
body = resp.text
assert body.splitlines()[0].startswith("Handle,")
assert "moon-mug" in body
def test_export_status_filter_respected(fresh_db_url):
with _merchant_client(fresh_db_url) as client:
# GOOD_CSV's moon-mug has no Status column → defaults to active.
draft = _upload(client).json()
client.post(f"/api/products/imports/drafts/{draft['id']}/confirm")
assert "moon-mug" in client.get("/api/products/export?status=active").text
# No archived products → 409.
assert client.get("/api/products/export?status=archived").status_code == 409
def test_export_empty_catalog_409(fresh_db_url):
with _merchant_client(fresh_db_url) as client:
resp = client.get("/api/products/export")
assert resp.status_code == 409
assert resp.json()["error"]["code"] == "empty_catalog"
def test_export_requires_merchant(fresh_db_url):
with TestClient(create_app(database_url=fresh_db_url)) as client:
assert client.get("/api/products/export").status_code == 401
def test_export_bad_status_422(fresh_db_url):
with _merchant_client(fresh_db_url) as client:
assert client.get("/api/products/export?status=bogus").status_code == 422