diff --git a/backend/tests/test_products_invariants.py b/backend/tests/test_products_invariants.py index 3f9db0f..7e045cb 100644 --- a/backend/tests/test_products_invariants.py +++ b/backend/tests/test_products_invariants.py @@ -77,3 +77,25 @@ def test_apply_failure_rolls_back_whole_transaction_tel6(migrated_conn, monkeypa assert migrated_conn.execute("SELECT count(*) FROM import_draft").fetchone()[0] == 1 events = [json.loads(r.message) for r in caplog.records if r.name == "ecomm.telemetry"] assert any(e["event"] == "import_apply_failed" and e["error_class"] == "RuntimeError" for e in events) + + +# A partial Shopify export (signature: Body (HTML) + Variant Grams) naming only one +# of the two existing products — INV-10 must hold across the dialect boundary. +SHOPIFY_PARTIAL = ( + b"Handle,Title,Body (HTML),Variant Price,Variant Grams\n" + b"mug,Mug,

x

,12.00,180\n" +) + + +def test_inv10_shopify_partial_never_deletes(migrated_conn): + acct, sf = _merchant(migrated_conn) + _import(migrated_conn, acct, sf, CSV_A) + before = migrated_conn.execute("SELECT count(*) FROM product").fetchone()[0] + d = products.import_validate(migrated_conn, sf, acct, "shopify.csv", SHOPIFY_PARTIAL) + assert d["dialect"] == "shopify" + products.confirm_draft(migrated_conn, sf, acct, d["id"]) + after = migrated_conn.execute("SELECT count(*) FROM product").fetchone()[0] + # INV-10: nothing deleted; the unmentioned 'tee' is untouched. + assert after >= before == 2 + handles = {r[0] for r in migrated_conn.execute("SELECT handle FROM product").fetchall()} + assert {"mug", "tee"} <= handles