"""Dashboards over HTTP: creating one under an issued id, and saving it.""" from fastapi.testclient import TestClient from fluksio.core.config import settings from fluksio.flow.store import ISSUED_ID from tests.utils.flows import put_dashboard PREFIX = f"{settings.API_V1_STR}/dashboards" def a_dashboard(name: str) -> dict: return { "name": name, "title": "Hall", "icon": "gauge", "widgets": [ { "id": "temperature", "type": "stat", "title": "Temperature", "layout": {"lg": {"x": 0, "y": 0, "w": 3, "h": 2}}, "config": {"message": "house.temperature", "dtype": "float"}, } ], "settings": {"theme": {"value": "dark", "message": "", "dtype": "str"}}, "version": 0, } def test_a_dashboard_is_created_with_an_id_and_saved_by_it( client: TestClient, superuser_token_headers: dict[str, str] ) -> None: """A first draft under an id the server issues, which every path then names.""" created = client.post( f"{PREFIX}/", headers=superuser_token_headers, json={"name": "made_here"} ) assert created.status_code == 201, created.text made = created.json() assert ISSUED_ID.fullmatch(made["id"]) and made["name"] == "made_here" assert made["version"] == 1 and made["has_draft"] is True # A draft alone: nothing was published, so no panel can be shown it. assert ( client.get( f"{PREFIX}/{made['id']}", headers=superuser_token_headers ).status_code == 404 ) body = {**a_dashboard("made_here"), "version": made["version"]} saved = client.put( f"{PREFIX}/{made['id']}", headers=superuser_token_headers, json=body ) assert saved.status_code == 200, saved.text draft = client.get( f"{PREFIX}/{made['id']}?draft=true", headers=superuser_token_headers ) assert draft.json()["widgets"] == body["widgets"] (listed,) = client.get( f"{PREFIX}/?name=made_here", headers=superuser_token_headers ).json()["data"] assert listed["id"] == made["id"] copy = client.post( f"{PREFIX}/{made['id']}/duplicate", headers=superuser_token_headers ).json() assert copy["name"] == "made_here_copy" and copy["id"] != made["id"] for dashboard_id in (made["id"], copy["id"]): client.delete(f"{PREFIX}/{dashboard_id}", headers=superuser_token_headers) def test_a_save_neither_creates_nor_renames( client: TestClient, superuser_token_headers: dict[str, str] ) -> None: missing = client.put( f"{PREFIX}/nowhere", headers=superuser_token_headers, json={**a_dashboard("nowhere"), "version": 0}, ) assert missing.status_code == 404 saved = put_dashboard( client, superuser_token_headers, a_dashboard("put_fixed") ).json() renamed = client.put( f"{PREFIX}/put_fixed", headers=superuser_token_headers, json={**saved, "name": "renamed"}, ) assert renamed.status_code == 409 elsewhere = client.put( f"{PREFIX}/put_fixed", headers=superuser_token_headers, json={**saved, "id": "elsewhere"}, ) assert elsewhere.status_code == 422 client.delete(f"{PREFIX}/put_fixed", headers=superuser_token_headers) def test_a_save_of_an_existing_dashboard_keeps_what_it_did_not_change( client: TestClient, superuser_token_headers: dict[str, str] ) -> None: seeded = a_dashboard("put_updates") first = put_dashboard(client, superuser_token_headers, seeded).json() renamed = {**first, "widgets": [{**first["widgets"][0], "title": "Outside"}]} second = client.put( f"{PREFIX}/put_updates", headers=superuser_token_headers, json=renamed ) assert second.status_code == 200, second.text stored = second.json() assert stored["version"] == first["version"] + 1 assert stored["widgets"][0]["title"] == "Outside" # Everything the edit did not name is still what was first written. assert stored["icon"] == seeded["icon"] assert stored["settings"] == seeded["settings"] assert stored["widgets"][0]["layout"] == seeded["widgets"][0]["layout"] assert stored["widgets"][0]["config"] == seeded["widgets"][0]["config"] def test_a_save_based_on_a_version_someone_moved_past_is_refused( client: TestClient, superuser_token_headers: dict[str, str] ) -> None: body = a_dashboard("put_conflicts") put_dashboard(client, superuser_token_headers, body) stale = client.put( f"{PREFIX}/put_conflicts", headers=superuser_token_headers, json={**body, "version": 1}, ) assert stale.status_code == 409 assert stale.json()["detail"]["current_version"] == 2 def test_only_a_superuser_pins_a_dashboard_id( client: TestClient, superuser_token_headers: dict[str, str], normal_user_token_headers: dict[str, str], ) -> None: pinned = {"id": "pinned_hall", "name": "pinned_hall"} refused = client.post(f"{PREFIX}/", headers=normal_user_token_headers, json=pinned) assert refused.status_code == 403 made = client.post(f"{PREFIX}/", headers=superuser_token_headers, json=pinned) assert made.status_code == 201 and made.json()["id"] == "pinned_hall" again = client.post( f"{PREFIX}/", headers=superuser_token_headers, json={"id": "pinned_hall", "name": "other_hall"}, ) assert again.status_code == 409 # Anyone may make one under an id of the server's. issued = client.post( f"{PREFIX}/", headers=normal_user_token_headers, json={"name": "their_hall"} ) assert issued.status_code == 201 for dashboard_id in ("pinned_hall", issued.json()["id"]): client.delete(f"{PREFIX}/{dashboard_id}", headers=superuser_token_headers)