"""app.widgets.calendar -- unit-level, no HTTP: constructs Widget/ CalendarWidgetConfig rows directly and monkeypatches the underlying fetch calls (get_or_refresh_*_for_widget), which have their own dedicated fetch/merge test coverage elsewhere (test_calendar_feed.py etc.) -- this file is about the widget wiring itself: does render() produce a correctly-sized image, do advance/back move browse_offset.""" from __future__ import annotations import time from app import widgets from app.db import widget_locked from app.models import CalendarWidgetConfig, Frame, Widget def _make_widget(db_session, **cfg_kwargs) -> tuple[Frame, Widget]: frame = db_session.get(Frame, 1) widget = Widget(frame_id=frame.id, widget_type="calendar", x=0, y=0, w=8, h=5, sort_order=0, created_at=time.time()) db_session.add(widget) db_session.flush() db_session.add(CalendarWidgetConfig(widget_id=widget.id, **cfg_kwargs)) db_session.commit() return frame, widget def _stub_fetches(monkeypatch, events=None, weather=None, tasks=None): monkeypatch.setattr(widgets.calendar, "get_or_refresh_calendar_events_for_widget", lambda db, frame, widget: (events or [], "")) monkeypatch.setattr(widgets.calendar, "get_or_refresh_weather_for_widget", lambda db, frame, widget: weather or []) monkeypatch.setattr(widgets.calendar, "get_or_refresh_tasks_for_widget", lambda db, frame, widget: tasks or []) def test_render_produces_a_correctly_sized_image(db_session, monkeypatch): frame, widget = _make_widget(db_session, view="agenda") _stub_fetches(monkeypatch) img = widgets.calendar.render(db_session, frame, widget, 400, 300) assert img.size == (400, 300) assert img.mode == "RGB" def test_render_resizes_when_target_differs_from_full_panel(db_session, monkeypatch): """Phase-1 calendar widgets are still full-panel-layout internally (see app/widgets/calendar.py's own module docstring) -- resizing to fit whatever target box is asked for keeps render_panel's contract (exact target_w x target_h) satisfied even before real small-widget layout support lands.""" frame, widget = _make_widget(db_session, view="week") _stub_fetches(monkeypatch) img = widgets.calendar.render(db_session, frame, widget, 250, 150) assert img.size == (250, 150) def test_weather_only_fetched_when_enabled(db_session, monkeypatch): frame, widget = _make_widget(db_session, view="agenda", weather_enabled=False) calls = [] monkeypatch.setattr(widgets.calendar, "get_or_refresh_calendar_events_for_widget", lambda db, frame, widget: ([], "")) monkeypatch.setattr(widgets.calendar, "get_or_refresh_weather_for_widget", lambda db, frame, widget: calls.append(1) or []) monkeypatch.setattr(widgets.calendar, "get_or_refresh_tasks_for_widget", lambda db, frame, widget: []) widgets.calendar.render(db_session, frame, widget, 400, 300) assert calls == [] def test_tasks_only_fetched_for_week_view_when_enabled(db_session, monkeypatch): frame, widget = _make_widget(db_session, view="agenda", tasks_enabled=True) # not week view calls = [] monkeypatch.setattr(widgets.calendar, "get_or_refresh_calendar_events_for_widget", lambda db, frame, widget: ([], "")) monkeypatch.setattr(widgets.calendar, "get_or_refresh_weather_for_widget", lambda db, frame, widget: []) monkeypatch.setattr(widgets.calendar, "get_or_refresh_tasks_for_widget", lambda db, frame, widget: calls.append(1) or []) widgets.calendar.render(db_session, frame, widget, 400, 300) assert calls == [] # agenda view -- tasks never shown, so never fetched def test_advance_action_increments_browse_offset(db_session): frame, widget = _make_widget(db_session, view="week", browse_offset=0) widgets.calendar.ACTIONS["advance"](db_session, frame, widget) cfg = db_session.get(CalendarWidgetConfig, widget.id) assert cfg.browse_offset == 1 widgets.calendar.ACTIONS["advance"](db_session, frame, widget) cfg = db_session.get(CalendarWidgetConfig, widget.id) assert cfg.browse_offset == 2 # accumulates, doesn't reset-then-increment def test_back_action_decrements_browse_offset(db_session): frame, widget = _make_widget(db_session, view="week", browse_offset=3) widgets.calendar.ACTIONS["back"](db_session, frame, widget) cfg = db_session.get(CalendarWidgetConfig, widget.id) assert cfg.browse_offset == 2