A "Lock this photo" button in the photos widget's dialog toggles PhotoWidgetConfig.locked, which suppresses both the timer-elapsed auto-advance and the advance/back button actions until unlocked. The Layout tab canvas shows a lock badge on any locked photo widget's box.
101 lines
4.3 KiB
Python
101 lines
4.3 KiB
Python
"""routers/api_widgets.py's POST .../lock endpoint (models.PhotoWidgetConfig.
|
|
locked) -- same permission shape as test_widget_border.py's own endpoint,
|
|
just for a photos-only field instead of a shared Widget-level one."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import time
|
|
|
|
from app.models import Frame, PhotoWidgetConfig, StaticWidgetConfig, Widget
|
|
|
|
from .conftest import csrf_headers, link_user, login, make_user
|
|
|
|
|
|
def _widget_id(db_session, widget_type="photos") -> int:
|
|
return db_session.query(Widget).filter_by(frame_id=1, widget_type=widget_type).one().id
|
|
|
|
|
|
def test_new_widget_defaults_to_unlocked(db_session):
|
|
widget_id = _widget_id(db_session)
|
|
assert db_session.get(PhotoWidgetConfig, widget_id).locked is False
|
|
|
|
|
|
def test_set_lock_persists(client, db_session):
|
|
client.post("/setup", data={"username": "alice", "password": "hunter22"})
|
|
widget_id = _widget_id(db_session)
|
|
resp = client.post(f"/api/frames/1/widgets/{widget_id}/lock",
|
|
json={"locked": True}, headers=csrf_headers(client))
|
|
assert resp.status_code == 200, resp.text
|
|
assert resp.json() == {"status": "saved", "locked": True}
|
|
assert db_session.get(PhotoWidgetConfig, widget_id).locked is True
|
|
|
|
resp = client.post(f"/api/frames/1/widgets/{widget_id}/lock",
|
|
json={"locked": False}, headers=csrf_headers(client))
|
|
assert resp.status_code == 200, resp.text
|
|
assert db_session.get(PhotoWidgetConfig, widget_id).locked is False
|
|
|
|
|
|
def test_set_lock_404s_for_unknown_widget(client, db_session):
|
|
client.post("/setup", data={"username": "alice", "password": "hunter22"})
|
|
resp = client.post("/api/frames/1/widgets/999999/lock",
|
|
json={"locked": True}, headers=csrf_headers(client))
|
|
assert resp.status_code == 404
|
|
|
|
|
|
def test_set_lock_rejects_non_photos_widget(client, db_session):
|
|
client.post("/setup", data={"username": "alice", "password": "hunter22"})
|
|
# Built directly rather than through the placement-validated create
|
|
# endpoint -- the default frame's photos widget already covers the
|
|
# whole grid, and overlap isn't the thing under test here.
|
|
static_widget = Widget(frame_id=1, widget_type="static", x=0, y=0, w=1, h=1,
|
|
sort_order=99, created_at=time.time())
|
|
db_session.add(static_widget)
|
|
db_session.flush()
|
|
db_session.add(StaticWidgetConfig(widget_id=static_widget.id))
|
|
db_session.commit()
|
|
|
|
resp = client.post(f"/api/frames/1/widgets/{static_widget.id}/lock",
|
|
json={"locked": True}, headers=csrf_headers(client))
|
|
assert resp.status_code == 400
|
|
|
|
|
|
def test_set_lock_unrelated_user_404s(client, db_session):
|
|
client.post("/setup", data={"username": "alice", "password": "hunter22"})
|
|
make_user(db_session, "mallory")
|
|
widget_id = _widget_id(db_session)
|
|
|
|
client.cookies.clear()
|
|
login(client, "mallory")
|
|
resp = client.post(f"/api/frames/1/widgets/{widget_id}/lock",
|
|
json={"locked": True}, headers=csrf_headers(client))
|
|
assert resp.status_code == 404
|
|
assert db_session.get(PhotoWidgetConfig, widget_id).locked is False
|
|
|
|
|
|
def test_set_lock_linked_but_not_controlling_user_409s(client, db_session):
|
|
client.post("/setup", data={"username": "alice", "password": "hunter22"})
|
|
bob = make_user(db_session, "bob")
|
|
frame = db_session.get(Frame, 1)
|
|
link_user(db_session, bob, frame)
|
|
widget_id = _widget_id(db_session)
|
|
|
|
client.cookies.clear()
|
|
login(client, "bob")
|
|
resp = client.post(f"/api/frames/1/widgets/{widget_id}/lock",
|
|
json={"locked": True}, headers=csrf_headers(client))
|
|
assert resp.status_code == 409
|
|
assert resp.json()["detail"]["error"] == "not_controller"
|
|
|
|
|
|
def test_widgets_list_reports_locked_state(client, db_session):
|
|
client.post("/setup", data={"username": "alice", "password": "hunter22"})
|
|
widget_id = _widget_id(db_session)
|
|
resp = client.get("/api/frames/1/widgets")
|
|
assert resp.status_code == 200, resp.text
|
|
assert next(w for w in resp.json()["widgets"] if w["id"] == widget_id)["locked"] is False
|
|
|
|
client.post(f"/api/frames/1/widgets/{widget_id}/lock",
|
|
json={"locked": True}, headers=csrf_headers(client))
|
|
resp = client.get("/api/frames/1/widgets")
|
|
assert next(w for w in resp.json()["widgets"] if w["id"] == widget_id)["locked"] is True
|