Files
Anthias/tests
Viktor Petersson b28ce96095 feat(settings): add userspace timezone selection and a device clock (#3163)
* feat(settings): add userspace timezone selection and a device clock

- Add an operator-selectable Timezone in Settings, stored in
  anthias.conf and applied live per request (config -> TZ env ->
  /etc/timezone -> UTC), so scheduling and time display use local
  time with no host access — the only way to get non-UTC on balena.
- Activate the resolved zone in the viewer's scheduler on startup and
  every reload so play-windows track the server.
- Validate the zone on both write paths and in the serializer so a
  bad value can never crash-loop the settings module.
- Show a live device clock (seeded from the server instant) on System
  Info and expose a `time` object on /api/v2/info.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(system-info): polish timezone UI after review

- Pair Uptime + Device time in one grid row (and the two chart cards
  in theirs) so the short clock card no longer stretches to a chart
  card's height and leaves a dead vertical band.
- Humanise displayed IANA names (underscore -> space) in the timezone
  dropdown and the device-clock sub-label; stored value + Intl data
  attribute keep the real id.
- Refresh the Display & playback section blurb to mention timezone.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(timezone): type the middleware test's request/response for mypy

Use RequestFactory + HttpResponse instead of object()/str stubs so the
TimezoneActivationMiddleware test satisfies the CI mypy signature check.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(timezone): address Copilot review

- page_context: snapshot the local instant + zone name once so the
  clock's iso/offset can't straddle a second boundary.
- v2 serializer: drop the {!r} quoting in the invalid-timezone message
  so it matches the HTML-path wording.
- middleware test: compare the post-request zone to a captured
  baseline instead of a hardcoded name (robust when the host default
  is Europe/Stockholm).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(system-info): guard the device clock against missing performance.now()

Fall back to Date.now() for the tick baseline where performance.now()
is unavailable (older/embedded browsers), so the clock never throws.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(timezone): address Copilot review (iso precision, config path)

- Emit device time `iso` at seconds precision (page_context + v2 info)
  so microseconds can't make an older JS Date.parse() return NaN and
  stall the live clock.
- get_configured_time_zone(): build the default config path from the
  shared CONFIG_DIR / CONFIG_FILE constants instead of hard-coding it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(timezone): dedupe UTC-offset helper, sharpen "blank" wording

- Extract format_utc_offset() into anthias_server.lib.timezone and use
  it from both page_context and the /api/v2/info clock instead of
  duplicating the formatting.
- Reword the "follow the host" comments/docstrings to state the actual
  blank-value fallback: TZ env -> /etc/timezone -> UTC.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 20:31:03 +01:00
..