Files
app/backend/tests/api/routes/test_dashboards.py
T

159 lines
5.7 KiB
Python

"""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)