def state(client): return client.get("/api/haushalt").json() def add(client, list_id, name, area="einkauf", quantity=1, unit="stk"): return client.post("/api/haushalt/items", json={"list": area, "name": name, "quantity": quantity, "unit": unit, "listId": list_id}) def items(data, list_id, area=None): return [i for i in data["items"] if i["listId"] == list_id and (area is None or i["list"] == area)] def new_list(client, name, members=()): res = client.post("/api/haushalt/listen", json={"name": name, "members": list(members)}) assert res.status_code == 201, res.text return res.json()["created"] def home(client): """Erste eigene Liste – Listen sind privat, jedes Konto legt seine eigene an.""" lists = [l for l in state(client)["lists"] if l["createdBy"] and l["createdBy"]["id"] == client.user["id"]] return lists[0]["id"] if lists else new_list(client, "Zuhause") def test_neue_liste_ist_privat(login): anna, ben = login("anna"), login("ben") home(anna) assert [l["name"] for l in state(anna)["lists"]] == ["Zuhause"] assert state(ben)["lists"] == [] def test_erstes_konto_bekommt_startliste(): from fastapi.testclient import TestClient from app.main import app client = TestClient(app) client.post("/api/auth/setup", json={"username": "erste", "password": "passwort123"}) assert [l["name"] for l in client.get("/api/haushalt").json()["lists"]] == ["Zuhause"] def test_hinzufuegen_fuehrt_zusammen_und_vereinheitlicht_namen(login): anna = login("anna") home_id = home(anna) add(anna, home_id, "milch", quantity=2) data = add(anna, home_id, "Milch", quantity=1).json() assert [(i["name"], i["quantity"]) for i in items(data, home_id, "einkauf")] == [("Milch", 3)] # Andere Einheit = eigene Zeile data = add(anna, home_id, "Milch", quantity=1.5, unit="l").json() assert len(items(data, home_id, "einkauf")) == 2 def test_listen_haben_eigenen_vorrat(login): anna = login("anna") home_id = home(anna) urlaub = new_list(anna, "Urlaub") add(anna, urlaub, "Brot", area="vorrat") data = state(anna) assert [i["name"] for i in items(data, urlaub, "vorrat")] == ["Brot"] assert items(data, home_id, "vorrat") == [] def test_private_liste_nur_fuer_mitglieder(login, befriend): anna, ben, chef = login("anna"), login("ben"), login("chef", admin=True) geheim = new_list(anna, "Geheim") item = add(anna, geheim, "Kuchen").json() item_id = items(item, geheim)[0]["id"] assert all(l["id"] != geheim for l in state(ben)["lists"]) assert add(ben, geheim, "x").status_code == 404 assert ben.patch(f"/api/haushalt/items/{item_id}", json={"quantity": 5}).status_code == 404 # Administratoren sehen und bearbeiten alles assert any(l["id"] == geheim and l["canManage"] for l in state(chef)["lists"]) assert chef.patch(f"/api/haushalt/items/{item_id}", json={"quantity": 5}).status_code == 200 # Teilen geht nur mit Freunden res = anna.patch(f"/api/haushalt/listen/{geheim}", json={"name": "Geheim", "members": [ben.user["id"]]}) assert res.status_code == 400 befriend(anna, ben) anna.patch(f"/api/haushalt/listen/{geheim}", json={"name": "Geheim", "members": [ben.user["id"]]}) lst = next(l for l in state(ben)["lists"] if l["id"] == geheim) assert lst["canManage"] is False assert ben.patch(f"/api/haushalt/listen/{geheim}", json={"name": "x"}).status_code == 403 assert ben.delete(f"/api/haushalt/listen/{geheim}").status_code == 403 def test_liste_loeschen_entfernt_eintraege(login, conn): anna = login("anna") urlaub = new_list(anna, "Urlaub") add(anna, urlaub, "Brot", area="vorrat") add(anna, urlaub, "Wasser") assert anna.delete(f"/api/haushalt/listen/{urlaub}").status_code == 200 assert conn.execute("SELECT COUNT(*) FROM household_items WHERE list_id = ?", (urlaub,)).fetchone()[0] == 0 def test_ungueltiges_mitglied(login): res = login("anna").post("/api/haushalt/listen", json={"name": "x", "members": [9999]}) assert res.status_code == 400 def test_abhaken_und_einkauf_beenden(login): anna = login("anna") home_id = home(anna) add(anna, home_id, "Milch", quantity=2) add(anna, home_id, "Brot") add(anna, home_id, "Milch", area="vorrat", quantity=1) milch = next(i for i in items(state(anna), home_id, "einkauf") if i["name"] == "Milch") data = anna.patch(f"/api/haushalt/items/{milch['id']}", json={"checked": True}).json() # Abgehakt bleibt auf der Einkaufsliste assert {i["name"]: i["checked"] for i in items(data, home_id, "einkauf")} == {"Milch": True, "Brot": False} res = anna.post(f"/api/haushalt/listen/{home_id}/einkauf-beenden") assert res.json()["moved"] == 1 data = res.json() assert [i["name"] for i in items(data, home_id, "einkauf")] == ["Brot"] assert [(i["name"], i["quantity"]) for i in items(data, home_id, "vorrat")] == [("Milch", 3)] # Nichts mehr abgehakt assert anna.post(f"/api/haushalt/listen/{home_id}/einkauf-beenden").status_code == 400 def test_vorrat_laesst_sich_nicht_abhaken(login): anna = login("anna") home_id = home(anna) vorrat = items(add(anna, home_id, "Reis", area="vorrat").json(), home_id, "vorrat")[0] assert anna.patch(f"/api/haushalt/items/{vorrat['id']}", json={"checked": True}).status_code == 400 def test_erneut_hinzufuegen_hebt_haken_auf(login): anna = login("anna") home_id = home(anna) milch = items(add(anna, home_id, "Milch").json(), home_id)[0] anna.patch(f"/api/haushalt/items/{milch['id']}", json={"checked": True}) data = add(anna, home_id, "Milch").json() assert items(data, home_id)[0]["checked"] is False def test_aufgebraucht_kommt_mit_menge_1_auf_einkauf(login): anna = login("anna") home_id = home(anna) reis = items(add(anna, home_id, "Reis", area="vorrat", quantity=4).json(), home_id)[0] data = anna.post(f"/api/haushalt/items/{reis['id']}/move").json() assert [(i["list"], i["quantity"]) for i in items(data, home_id)] == [("einkauf", 1)] def test_rezept_uebernehmen_in_gewaehlte_liste(login): anna = login("anna") urlaub = new_list(anna, "Urlaub") res = anna.post("/api/haushalt/rezept/uebernehmen", json={ "items": [{"name": "Mehl", "quantity": 0.5, "unit": "kg"}], "aliases": [], "listId": urlaub, }) assert res.status_code == 200 assert [(i["name"], i["quantity"], i["unit"]) for i in items(res.json(), urlaub, "einkauf")] == [("Mehl", 0.5, "kg")] def test_einheitenwechsel_fuehrt_zusammen(login): anna = login("anna") home_id = home(anna) add(anna, home_id, "Mehl", quantity=1, unit="kg") stk = items(add(anna, home_id, "Mehl", quantity=2).json(), home_id) stk = next(i for i in stk if i["unit"] == "stk") data = anna.patch(f"/api/haushalt/items/{stk['id']}", json={"unit": "kg"}).json() assert [(i["quantity"], i["unit"]) for i in items(data, home_id)] == [(3, "kg")]