Fix saved layouts silently dropping weather widget settings
LAYOUT_CONFIG_FIELDS never had a "weather" entry, so saving a layout captured an empty config for any weather widget -- applying it back (including via hold-to-cycle) reset mode/provider/city/units/etc to defaults instead of restoring what was configured.
This commit is contained in:
@@ -63,6 +63,10 @@ LAYOUT_CONFIG_FIELDS: dict[str, tuple[str, ...]] = {
|
||||
"text": ("content", "font_size", "font_family", "align", "background_color"),
|
||||
"whiteboard": ("user_id", "url"),
|
||||
"battery": ("mode",),
|
||||
"weather": (
|
||||
"mode", "provider", "units", "city_label", "city_latitude", "city_longitude",
|
||||
"hourly_interval_hours", "daily_days", "cities",
|
||||
),
|
||||
}
|
||||
|
||||
# widget_type -> (FrameCalendar|FrameTaskList model, SavedLayoutSource.kind)
|
||||
|
||||
@@ -27,6 +27,7 @@ from app.models import (
|
||||
TaskWidgetConfig,
|
||||
User,
|
||||
Widget,
|
||||
WeatherWidgetConfig,
|
||||
)
|
||||
|
||||
from .conftest import csrf_headers, link_user, login, make_user
|
||||
@@ -56,6 +57,16 @@ def _add_tasks_widget(db_session, frame_id=1, x=3, y=0, w=2, h=2, sort_order=2)
|
||||
return widget
|
||||
|
||||
|
||||
def _add_weather_widget(db_session, frame_id=1, x=0, y=0, w=2, h=2, sort_order=1) -> Widget:
|
||||
widget = Widget(frame_id=frame_id, widget_type="weather", x=x, y=y, w=w, h=h,
|
||||
sort_order=sort_order, created_at=time.time())
|
||||
db_session.add(widget)
|
||||
db_session.flush()
|
||||
db_session.add(WeatherWidgetConfig(widget_id=widget.id))
|
||||
db_session.commit()
|
||||
return widget
|
||||
|
||||
|
||||
def _setup_alice(client) -> None:
|
||||
resp = client.post("/setup", data={"username": "alice", "password": "hunter22"})
|
||||
assert resp.status_code == 303, resp.text
|
||||
@@ -89,6 +100,48 @@ def test_save_captures_placement_and_photo_settings_but_not_queue_state(client,
|
||||
"queue_target_len": 30}
|
||||
|
||||
|
||||
def test_save_and_apply_round_trip_weather_settings(client, db_session):
|
||||
_setup_alice(client)
|
||||
weather = _add_weather_widget(db_session)
|
||||
with db_session.no_autoflush:
|
||||
wcfg = db_session.get(WeatherWidgetConfig, weather.id)
|
||||
wcfg.mode = "daily"
|
||||
wcfg.provider = "nws"
|
||||
wcfg.units = "celsius"
|
||||
wcfg.city_label = "Boston, MA"
|
||||
wcfg.city_latitude = 42.36
|
||||
wcfg.city_longitude = -71.06
|
||||
wcfg.hourly_interval_hours = 6
|
||||
wcfg.daily_days = 7
|
||||
wcfg.checked_at = 12345.0
|
||||
wcfg.cached = {"stale": "runtime state, not a setting"}
|
||||
db_session.commit()
|
||||
db_session.expunge(wcfg)
|
||||
|
||||
save_resp = client.post("/api/frames/1/layouts", json={"name": "Weather Layout"}, headers=csrf_headers(client))
|
||||
assert save_resp.status_code == 200, save_resp.text
|
||||
layout = db_session.query(SavedLayout).filter_by(user_id=1, name="Weather Layout").one()
|
||||
snap = db_session.query(SavedLayoutWidget).filter_by(saved_layout_id=layout.id, widget_type="weather").one()
|
||||
assert snap.config == {
|
||||
"mode": "daily", "provider": "nws", "units": "celsius", "city_label": "Boston, MA",
|
||||
"city_latitude": 42.36, "city_longitude": -71.06, "hourly_interval_hours": 6, "daily_days": 7,
|
||||
"cities": None,
|
||||
}
|
||||
|
||||
client.delete("/api/frames/1/widgets", headers=csrf_headers(client))
|
||||
apply_resp = client.post(f"/api/frames/1/layouts/{layout.id}/apply", headers=csrf_headers(client))
|
||||
assert apply_resp.status_code == 200, apply_resp.text
|
||||
|
||||
new_widget = db_session.query(Widget).filter_by(frame_id=1, widget_type="weather").one()
|
||||
new_cfg = db_session.get(WeatherWidgetConfig, new_widget.id)
|
||||
assert (new_cfg.mode, new_cfg.provider, new_cfg.units) == ("daily", "nws", "celsius")
|
||||
assert (new_cfg.city_label, new_cfg.city_latitude, new_cfg.city_longitude) == ("Boston, MA", 42.36, -71.06)
|
||||
assert (new_cfg.hourly_interval_hours, new_cfg.daily_days) == (6, 7)
|
||||
# Runtime fetch-cache state is never captured/restored by a saved layout.
|
||||
assert new_cfg.checked_at == 0.0
|
||||
assert new_cfg.cached is None
|
||||
|
||||
|
||||
def test_save_captures_calendar_sources_and_button_actions(client, db_session):
|
||||
_setup_alice(client)
|
||||
db_session.query(Widget).filter_by(frame_id=1, widget_type="photos").delete()
|
||||
|
||||
Reference in New Issue
Block a user