Files
MeshTerm/tests/test_config.py
T
Jean-Pierre MartineauandClaude Opus 5 cef7a764af How MeshTerm behaves gets a page of its own
Three kinds of "setting" were tangled into two files and one of them had no
screen at all. The radio's settings live on the radio and are edited on Device
config. Machine setup -- where the database is, which companion to talk to --
stays in config.toml, a text editor's job. Everything in between was app
behaviour: six keys sitting in config.toml with nothing to open them, and a
dozen more that were only module constants a reader could never reach.

Those are preferences now, and they have a page. core/preferences.py is a
PrefSpec registry in the shape of the device-config one -- group, type, bounds,
help, and a default -- and the page is built from the same parts as the device
editor, deliberately: one grouped lane-aligned list, current -> new staged in
warn, Apply/Back appearing only once something is staged, the shared discard
confirm on the way out. Two editors that stage values should not be two screens
to learn. What it adds is a Defaults section holding one row that stages every
changed preference back to its built-in value; it is drawn only while a reset
would do something, and it stages rather than writes, so it is as reviewable and
as Esc-discardable as any other change and the file is still only ever written
by the one action at the bottom. Its rows scroll sideways where the device
editor's don't: the explanation is the widest thing on the row and the only part
that runs past the edge, so <-> slide it under a pinned setting and value.

The file is preferences.yaml and holds only the values you disagree with the
code about -- grouped and commented, each entry above its help and its default.
That is what lets a later change to a default reach an install that never asked
to be exempt; delete a line and the code takes over again. A hand edit gone
wrong costs that line, never the session.

Every preference is wired to something that reads it. ctx.preferences is the
explicit path; preferences.current() is for the render layer, which has no
context to reach through, the same reason get_platform() exists.

The About pages come along into a This app section, the third scope after this
node and other nodes, with Preferences leading it -- the one row there that
changes MeshTerm rather than describing it. A section of one would have broken
the menu's own no-bucket-of-one rule, and the app's scope is the honest home for
both halves anyway.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-05 15:36:40 -04:00

49 lines
1.8 KiB
Python

"""Tests for machine-setup loading (where things live, and which device to talk to).
MeshTerm's *behaviour* settings are preferences and live in ``tests/test_preferences.py``;
this file is only what ``config.toml`` still answers for.
"""
from __future__ import annotations
from pathlib import Path
from meshterm.core.config import Settings
def test_connect_on_start_defaults_true() -> None:
"""Eager connect-at-launch is the default when nothing is configured."""
assert Settings().connect_on_start is True
def test_connect_on_start_loads_from_toml(tmp_path: Path) -> None:
"""Whether the session opens the radio link at launch round-trips from the config file."""
config = tmp_path / "config.toml"
config.write_text("connect_on_start = false\n", encoding="utf-8")
assert Settings.load(config).connect_on_start is False
def test_tcp_profile_inferred_and_loaded(tmp_path: Path) -> None:
"""A profile with a ``host`` loads as a TCP profile and exposes its host:port endpoint."""
config = tmp_path / "config.toml"
config.write_text(
"[profiles.wifi]\n"
'host = "192.168.1.50"\n'
"tcp_port = 6000\n",
encoding="utf-8",
)
profile = Settings.load(config).profiles["wifi"]
assert profile.is_tcp and profile.transport == "tcp"
assert profile.host == "192.168.1.50" and profile.tcp_port == 6000
assert profile.tcp_endpoint == "192.168.1.50:6000"
def test_tcp_profile_defaults_port(tmp_path: Path) -> None:
"""A TCP profile naming only a host takes the default port in its endpoint."""
config = tmp_path / "config.toml"
config.write_text(
'[profiles.wifi]\nhost = "meshcore.local"\n', encoding="utf-8"
)
profile = Settings.load(config).profiles["wifi"]
assert profile.is_tcp and profile.tcp_endpoint == "meshcore.local:5000"