Files
MeshTerm/tests/test_lane_decks.py
Jean-Pierre MartineauandClaude Opus 5.5 11b5274b31 Docstrings and comments of the tests are in ASD-STE100
Each test docstring states the behaviour that the test proves, in the
simple present. No assertion message, test id, or other string literal
changed. Four statements now agree with the code: the Trace highlight
stays on the last row, a menu count, and two others.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-06 21:36:50 -04:00

151 lines
6.3 KiB
Python

# SPDX-License-Identifier: Apache-2.0
"""Each handheld has its own F-key lane: its keys, its chips, and its lane definitions."""
from __future__ import annotations
from prompt_toolkit.keys import Keys
from rich.cells import cell_len
from meshterm.platforms import CARDPUTER_ZERO, PICOCALC_LYRA, REGULAR, resolve, set_platform
from meshterm.services import modifier_watch
from meshterm.ui.tui import session
from meshterm.ui.tui.fkeys import (
CARDPUTER_ZERO_DECK,
DECKS,
DEFAULT_LANE,
EMPTY_LANE,
PICOCALC_LYRA_DECK,
FPair,
active_deck,
)
from meshterm.ui.tui.screen import ScrollScreen
class _OwnCardputerLane(ScrollScreen):
"""A screen that has its own lane for the Cardputer."""
@property
def cardputer_zero_lane(self):
return (FPair("Mine", "mine"), None, None, None, None)
def test_every_handheld_names_a_deck_of_its_own() -> None:
"""A platform with a lane names a deck that exists. The desktop names no deck."""
assert (
PICOCALC_LYRA.lane_deck == "picocalc-lyra" and CARDPUTER_ZERO.lane_deck == "cardputer-zero"
)
assert all(DECKS[p.lane_deck].name == p.lane_deck for p in (PICOCALC_LYRA, CARDPUTER_ZERO))
assert REGULAR.lane_deck == "" and not REGULAR.footer_fkeys
assert PICOCALC_LYRA.footer_fkeys and CARDPUTER_ZERO.footer_fkeys
def test_the_active_deck_follows_the_platform() -> None:
"""MeshTerm binds the deck when the platform changes.
It never looks up the deck for each frame.
"""
assert active_deck() is None
set_platform(PICOCALC_LYRA)
assert active_deck() is PICOCALC_LYRA_DECK
set_platform(CARDPUTER_ZERO)
assert active_deck() is CARDPUTER_ZERO_DECK
def test_the_cardputer_deals_the_picocalc_lanes_until_a_screen_says_otherwise() -> None:
"""JP, 2026-09-30: same entries for now, and each platform reads its own definition."""
screen = ScrollScreen("body")
assert screen.cardputer_zero_lane == screen.picocalc_lyra_lane
own = _OwnCardputerLane("body")
set_platform(CARDPUTER_ZERO)
assert own.fkey_lane[0].label == "Mine"
set_platform(PICOCALC_LYRA)
assert own.fkey_lane == own.picocalc_lyra_lane # the PicoCalc never uses the Cardputer lane
set_platform(REGULAR)
assert own.fkey_lane == EMPTY_LANE # the desktop has no lane
def test_cardputer_keys_are_fn_4_to_8_with_their_shift_bank() -> None:
"""Fn+4..8 arrive as F4-F8, and Shift with them arrives as F16-F20.
No other key belongs to the lane.
"""
lane = DEFAULT_LANE
assert CARDPUTER_ZERO_DECK.action_for(lane, 7) == "pagedown"
assert CARDPUTER_ZERO_DECK.action_for(lane, 8) == "pageup"
assert CARDPUTER_ZERO_DECK.action_for(lane, 19) == "end"
assert CARDPUTER_ZERO_DECK.action_for(lane, 20) == "home"
assert all(CARDPUTER_ZERO_DECK.action_for(lane, n) is None for n in (1, 2, 3, 9, 10, 11, 12))
assert CARDPUTER_ZERO_DECK.is_shift_key(16) and not CARDPUTER_ZERO_DECK.is_shift_key(6)
# The same lane on the keys of the PicoCalc. The keys of the Cardputer do not change it.
assert PICOCALC_LYRA_DECK.action_for(lane, 4) == "pagedown"
assert PICOCALC_LYRA_DECK.action_for(lane, 10) == "home"
assert PICOCALC_LYRA_DECK.action_for(lane, 16) is None
def test_the_session_binds_every_key_a_deck_can_use() -> None:
"""The deck decides which F-keys drive the lane, so all 24 keys reach _dispatch."""
for deck in DECKS.values():
for number in deck.keys + deck.shift_keys:
assert session._KEY_ACTIONS[getattr(Keys, f"F{number}")] == f"f{number}"
def test_cardputer_chips_are_laid_out_as_the_picocalcs() -> None:
"""The chips of the Cardputer have the layout of the PicoCalc.
A chip has a caption and a width of 9 cells. The gaps are 2 cells.
"""
assert CARDPUTER_ZERO_DECK.columns == PICOCALC_LYRA_DECK.columns
assert CARDPUTER_ZERO_DECK.chip_width == PICOCALC_LYRA_DECK.chip_width
lane = (FPair("Region", "home"), FPair("You", "locate", enabled=False), None, *DEFAULT_LANE[3:])
row = CARDPUTER_ZERO_DECK.lane_text(lane)
assert cell_len(row.plain) == CARDPUTER_ZERO.readable_cols
chips = [row.plain[c : c + CARDPUTER_ZERO_DECK.chip_width] for c in CARDPUTER_ZERO_DECK.columns]
assert chips == ["F4 Region", "F5 You ", "F6 ", "F7 Page ↓", "F8 Page ↑"]
styles = {row.plain[s.start : s.end].strip(): str(s.style) for s in row.spans}
assert styles["F4 Region"] == "fkey.chip.cardputer_zero"
assert styles["F5 You"] == "muted" and styles["F6"] == "muted"
def test_cardputer_shift_bank_draws_in_its_own_fill() -> None:
"""When Shift is held, the opposite chips show in the Shift fill.
They have the same key captions.
"""
row = CARDPUTER_ZERO_DECK.lane_text(DEFAULT_LANE, shifted=True)
styles = {row.plain[s.start : s.end].strip(): str(s.style) for s in row.spans}
assert styles["F7 Bottom"] == "fkey.chip.cardputer_zero.shift"
assert styles["F8 Top"] == "fkey.chip.cardputer_zero.shift"
assert styles["F4"] == "muted"
def test_the_picocalc_row_is_unchanged() -> None:
"""The row has five chips, each with a caption and 9 cells, and gaps of 2 cells.
This is exactly the 53 columns of the console.
"""
row = PICOCALC_LYRA_DECK.lane_text(DEFAULT_LANE)
assert cell_len(row.plain) == PICOCALC_LYRA.readable_cols
assert row.plain.startswith("F1 ")
assert row.plain.endswith("F5 Page ↑")
def test_the_platform_resolves_by_name() -> None:
"""Only a flag or the environment chooses this platform.
MeshTerm does not know a device-tree model for it yet.
"""
assert resolve("cardputer-zero").platform is CARDPUTER_ZERO
assert CARDPUTER_ZERO.readable_cols == 53 and CARDPUTER_ZERO.readable_rows == 14
def test_the_shift_watcher_looks_for_the_platforms_keyboard(tmp_path, monkeypatch) -> None:
"""The watcher finds the keyboard that the platform names, with the name of its input device."""
for event, name in (("event0", "gpio-keys"), ("event1", "tca8418c")):
device = tmp_path / event / "device"
device.mkdir(parents=True)
(device / "name").write_text(f"{name}\n")
monkeypatch.setattr(modifier_watch, "_SYS_INPUT", tmp_path)
assert modifier_watch._find_keyboard(CARDPUTER_ZERO.modifier_watch).name == "event1"
assert modifier_watch._find_keyboard(PICOCALC_LYRA.modifier_watch) is None