feat(products): SD-0002 §6.3 schema — migration 0002 + nh3/multipart deps (SLICE-5)

Also updates test_migrate_from_empty_applies_0001 → test_migrate_from_empty_applies_all
to assert both migrations apply on a fresh DB (mechanical consequence of adding 0002).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 14:52:18 -07:00
parent 1267d4f29d
commit 0ee948b34d
3 changed files with 156 additions and 2 deletions
+24 -2
View File
@@ -1,4 +1,5 @@
import psycopg
import pytest
from app.platform import db
@@ -12,10 +13,10 @@ def _table_names(conn) -> set[str]:
return {r[0] for r in rows}
def test_migrate_from_empty_applies_0001(fresh_db_url):
def test_migrate_from_empty_applies_all(fresh_db_url):
with psycopg.connect(fresh_db_url) as conn:
applied = db.migrate(conn)
assert applied == ["0001_init.sql"]
assert applied == ["0001_init.sql", "0002_products.sql"]
with psycopg.connect(fresh_db_url) as conn:
assert _TABLES.issubset(_table_names(conn))
@@ -41,3 +42,24 @@ def test_membership_has_no_unique_account_constraint(fresh_db_url):
).fetchall()
defs = " ".join(r[0] for r in rows).lower()
assert "unique" not in defs.replace("primary key", "") or "(account_id)" not in defs
def test_0002_products_tables_exist(fresh_db_url):
with psycopg.connect(fresh_db_url) as conn:
db.migrate(conn)
for table in ("product", "variant", "product_image", "import_draft", "import_run", "import_run_error"):
assert conn.execute("SELECT to_regclass(%s)", (f"public.{table}",)).fetchone()[0] == table
def test_0002_variant_option_combo_unique_treats_nulls_as_equal(fresh_db_url):
# INV-13: the no-option product's single variant has NULL option values; a second
# all-NULL combo must collide (NULLS NOT DISTINCT).
with psycopg.connect(fresh_db_url) as conn:
db.migrate(conn)
sf = conn.execute("INSERT INTO storefront (name) VALUES ('s') RETURNING id").fetchone()[0]
pid = conn.execute(
"INSERT INTO product (storefront_id, handle, title) VALUES (%s,'h','T') RETURNING id", (sf,)
).fetchone()[0]
conn.execute("INSERT INTO variant (product_id, position) VALUES (%s, 1)", (pid,))
with pytest.raises(psycopg.errors.UniqueViolation):
conn.execute("INSERT INTO variant (product_id, position) VALUES (%s, 2)", (pid,))