Add tests for unretire, logbook, charge-log delete, CSV exports, sub-component edit
This commit is contained in:
@@ -1216,3 +1216,113 @@ def test_device_charge_all_parent_no_installed(client):
|
|||||||
)
|
)
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
assert b"No installed batteries" in resp.data
|
assert b"No installed batteries" in resp.data
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------ #
|
||||||
|
# Battery — unretire
|
||||||
|
# ------------------------------------------------------------------ #
|
||||||
|
|
||||||
|
def test_unretire_battery(seeded_client):
|
||||||
|
# id=3 is retired by fixture
|
||||||
|
resp = seeded_client.post("/battery/3/unretire", follow_redirects=True)
|
||||||
|
assert resp.status_code == 200
|
||||||
|
assert b"now available again" in resp.data
|
||||||
|
assert b"available" in seeded_client.get("/battery/3").data.lower()
|
||||||
|
|
||||||
|
|
||||||
|
def test_unretire_not_retired(seeded_client):
|
||||||
|
resp = seeded_client.post("/battery/1/unretire", follow_redirects=True)
|
||||||
|
assert b"is not retired" in resp.data
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------ #
|
||||||
|
# Logbook
|
||||||
|
# ------------------------------------------------------------------ #
|
||||||
|
|
||||||
|
def test_battery_logbook_add_and_delete(seeded_client):
|
||||||
|
resp = seeded_client.post("/battery/1/logbook/add",
|
||||||
|
data={"body": "Swapped terminals"}, follow_redirects=True)
|
||||||
|
assert b"Swapped terminals" in resp.data
|
||||||
|
resp = seeded_client.post("/battery/1/logbook/1/delete", follow_redirects=True)
|
||||||
|
assert b"Logbook entry deleted" in resp.data
|
||||||
|
assert b"Swapped terminals" not in seeded_client.get("/battery/1").data
|
||||||
|
|
||||||
|
|
||||||
|
def test_battery_logbook_add_empty_body(seeded_client):
|
||||||
|
resp = seeded_client.post("/battery/1/logbook/add",
|
||||||
|
data={"body": " "}, follow_redirects=True)
|
||||||
|
assert b"Entry text is required" in resp.data
|
||||||
|
|
||||||
|
|
||||||
|
def test_device_logbook_add_and_delete(seeded_client):
|
||||||
|
resp = seeded_client.post("/device/1/logbook/add",
|
||||||
|
data={"body": "Cleaned contacts"}, follow_redirects=True)
|
||||||
|
assert b"Cleaned contacts" in resp.data
|
||||||
|
resp = seeded_client.post("/device/1/logbook/1/delete", follow_redirects=True)
|
||||||
|
assert b"Logbook entry deleted" in resp.data
|
||||||
|
assert b"Cleaned contacts" not in seeded_client.get("/device/1").data
|
||||||
|
|
||||||
|
|
||||||
|
def test_device_logbook_add_empty_body(seeded_client):
|
||||||
|
resp = seeded_client.post("/device/1/logbook/add",
|
||||||
|
data={"body": ""}, follow_redirects=True)
|
||||||
|
assert b"Entry text is required" in resp.data
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------ #
|
||||||
|
# Charge log — delete
|
||||||
|
# ------------------------------------------------------------------ #
|
||||||
|
|
||||||
|
def test_charge_log_delete_reverts_cycles(seeded_client):
|
||||||
|
seeded_client.post("/battery/1/charge-log/add",
|
||||||
|
data={"charged_date": "2026-06-01", "increment_cycles": "1"})
|
||||||
|
data = _json.loads(seeded_client.get("/export/all.json").data)
|
||||||
|
assert next(b for b in data["batteries"] if b["id"] == 1)["charge_cycles"] == 1
|
||||||
|
log_id = data["charge_logs"][0]["id"]
|
||||||
|
resp = seeded_client.post(f"/battery/1/charge-log/{log_id}/delete",
|
||||||
|
follow_redirects=True)
|
||||||
|
assert b"Charge log entry deleted" in resp.data
|
||||||
|
data = _json.loads(seeded_client.get("/export/all.json").data)
|
||||||
|
assert next(b for b in data["batteries"] if b["id"] == 1)["charge_cycles"] == 0
|
||||||
|
assert data["charge_logs"] == []
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------ #
|
||||||
|
# CSV exports
|
||||||
|
# ------------------------------------------------------------------ #
|
||||||
|
|
||||||
|
def test_csv_export_routes(seeded_client):
|
||||||
|
expectations = {
|
||||||
|
"/export/batteries.csv": b"label",
|
||||||
|
"/export/devices.csv": b"parent_id,parent_name",
|
||||||
|
"/export/charge-logs.csv": b"charged_date",
|
||||||
|
"/export/capacity-tests.csv": b"tested_capacity_mah",
|
||||||
|
"/export/pct-logs.csv": b"percentage",
|
||||||
|
}
|
||||||
|
for url, marker in expectations.items():
|
||||||
|
resp = seeded_client.get(url)
|
||||||
|
assert resp.status_code == 200, url
|
||||||
|
assert "text/csv" in resp.content_type, url
|
||||||
|
assert marker in resp.data, url
|
||||||
|
resp = seeded_client.get("/export/csv.zip")
|
||||||
|
assert resp.status_code == 200
|
||||||
|
assert "zip" in resp.content_type
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------ #
|
||||||
|
# Sub-component edit — type/location stay NULL
|
||||||
|
# ------------------------------------------------------------------ #
|
||||||
|
|
||||||
|
def test_subcomponent_edit_resave_keeps_nulls(client):
|
||||||
|
_setup_rc_car(client)
|
||||||
|
# device 2 = Remote, sub-component of 1; re-save smuggling in type/location
|
||||||
|
resp = client.post("/device/2/edit", data={
|
||||||
|
"name": "Remote", "battery_slots": "2", "parent_id": "1",
|
||||||
|
"device_type": "Toy", "location": "Garage", "battery_size": "AA",
|
||||||
|
}, follow_redirects=True)
|
||||||
|
assert resp.status_code == 200
|
||||||
|
data = _json.loads(client.get("/export/all.json").data)
|
||||||
|
rem = next(d for d in data["devices"] if d["name"] == "Remote")
|
||||||
|
assert rem["parent_id"] is not None
|
||||||
|
assert rem["device_type"] is None
|
||||||
|
assert rem["location"] is None
|
||||||
|
|||||||
Reference in New Issue
Block a user