Files
personal-progress-monitor/tests/test_layouts.py
MobKBK bcc2abe623 feat: complete frozen MVP — period-aware stats, layout-driven UI, quick checkin
- Fix first daily record 422 (expectedVersion now accepts 0)
- Add period_window + summarize; /api/summary and /api/tasks/{id}/summary
  aggregate each metric inside its own day/week/month/lifetime window,
  reading raw facts only (never the rebuildable month archives)
- Drive frontend rendering from per-page layout JSON with a component
  registry; scope/cardinality enforced server-side, invalid layouts fall back
- Add quick checkin and duration input in H:M:S that round-trips integer seconds
- Fix heatmap/completedAt timezone drift to Asia/Shanghai
- Add server-side session TTL (30d) matching the login cookie
- Handle date.min/date.max boundaries without OverflowError
- Half-up rounding to match browser Math.round

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-24 07:15:50 +08:00

43 lines
1.6 KiB
Python

from app.layouts import load_layout, validate_layout
def _layout(page, main_components, sidebar=None):
return {
"schemaVersion": 1,
"page": page,
"regions": {
"sidebar": sidebar or ([{"component": "task-list"}] if page == "task-detail" else []),
"main": main_components,
},
}
def test_valid_home_layout():
assert validate_layout(_layout("home", [{"component": "overview-summary"}, {"component": "task-progress-grid"}]), "home")
def test_valid_task_detail_layout():
assert validate_layout(_layout("task-detail", [{"component": "task-header"}, {"component": "today-record"}, {"component": "metric-progress"}, {"component": "activity-heatmap"}, {"component": "task-settings"}]), "task-detail")
def test_rejects_component_on_wrong_page():
assert not validate_layout(_layout("home", [{"component": "today-record"}]), "home")
def test_rejects_component_in_wrong_region():
layout = _layout("task-detail", [{"component": "task-header"}], sidebar=[{"component": "task-header"}])
assert not validate_layout(layout, "task-detail")
def test_rejects_duplicate_component():
layout = _layout("task-detail", [{"component": "today-record"}, {"component": "today-record"}])
assert not validate_layout(layout, "task-detail")
def test_load_layout_falls_back_on_invalid(tmp_path):
import json
bad = tmp_path / "home.json"
bad.write_text(json.dumps(_layout("home", [{"component": "today-record"}])), encoding="utf-8")
loaded = load_layout(tmp_path, "home")
assert loaded["regions"]["main"] != [{"component": "today-record"}]