Preserve sub-component hierarchy in export/import

This commit is contained in:
2026-06-10 12:27:05 -05:00
parent d1fc80164f
commit d41fe7f4ab
2 changed files with 98 additions and 9 deletions
+70
View File
@@ -844,6 +844,76 @@ def test_full_roundtrip_export_import(client):
assert b"Import Results" in resp.data
def test_export_json_includes_parent_fields(client):
_setup_rc_car(client)
data = _json.loads(client.get("/export/all.json").data)
devs = {d["name"]: d for d in data["devices"]}
assert devs["RC Car Set"]["parent_id"] is None
assert devs["Remote"]["parent_id"] == devs["RC Car Set"]["id"]
assert devs["Remote"]["parent_name"] == "RC Car Set"
def test_import_rebuilds_hierarchy(client):
payload = _make_import_payload(devices=[
_dev(10, "Hub", battery_slots=0, battery_size=None),
_dev(11, "Probe", parent_id=10),
])
resp = _post_import(client, payload)
assert resp.status_code == 200
data = _json.loads(client.get("/export/all.json").data)
devs = {d["name"]: d for d in data["devices"]}
assert devs["Probe"]["parent_id"] == devs["Hub"]["id"]
assert devs["Probe"]["parent_name"] == "Hub"
# parent's 0 slots survive the import (previously coerced to 1)
assert devs["Hub"]["battery_slots"] == 0
def test_import_child_listed_before_parent(client):
payload = _make_import_payload(devices=[
_dev(11, "Probe", parent_id=10),
_dev(10, "Hub", battery_slots=0, battery_size=None),
])
resp = _post_import(client, payload)
assert resp.status_code == 200
data = _json.loads(client.get("/export/all.json").data)
devs = {d["name"]: d for d in data["devices"]}
assert devs["Probe"]["parent_id"] == devs["Hub"]["id"]
def test_import_subcomponent_missing_parent_becomes_top_level(client):
payload = _make_import_payload(devices=[_dev(11, "Probe", parent_id=99)])
resp = _post_import(client, payload)
assert resp.status_code == 200
data = _json.loads(client.get("/export/all.json").data)
devs = {d["name"]: d for d in data["devices"]}
assert devs["Probe"]["parent_id"] is None
def test_import_empty_battery_size_stored_as_null(client):
payload = _make_import_payload(devices=[_dev(10, "NoSize", battery_size="")])
resp = _post_import(client, payload)
assert resp.status_code == 200
data = _json.loads(client.get("/export/all.json").data)
devs = {d["name"]: d for d in data["devices"]}
assert devs["NoSize"]["battery_size"] is None
def test_roundtrip_import_preserves_hierarchy(client):
_setup_rc_car(client)
data = _json.loads(client.get("/export/all.json").data)
# rename everything so the import creates rows instead of skipping
for d in data["devices"]:
d["name"] = d["name"] + " v2"
buf = io.BytesIO(_json.dumps(data).encode())
resp = client.post("/import", data={"file": (buf, "export.json")},
content_type="multipart/form-data")
assert resp.status_code == 200
data2 = _json.loads(client.get("/export/all.json").data)
devs = {d["name"]: d for d in data2["devices"]}
assert devs["Remote v2"]["parent_id"] == devs["RC Car Set v2"]["id"]
assert devs["Car v2"]["parent_id"] == devs["RC Car Set v2"]["id"]
def test_device_detail_unassign_all(seeded_client):
client = seeded_client
# install battery 1 into device 1 (2-slot AA device)