From 892111abb7876eecc2f227cc78e640a476b0bbd6 Mon Sep 17 00:00:00 2001 From: Codex Date: Sun, 4 Oct 2026 12:49:33 -0500 Subject: [PATCH] test: Align GUI card checks with wrapping The Tails field-test change in #77 lets card groups wrap according to available space, but the headless walkthrough and developer guide still required a fixed four-column layout. Verify reading order and actual wrapping at the clamped content width instead. Remove the resize assertion, which cannot reliably resize an already mapped window in this headless run. No GUI runtime behavior changes. Refs #72. --- docs/developer/gui.md | 5 +++-- tools/gui_walkthrough.py | 44 +++++++++++++++++++--------------------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/docs/developer/gui.md b/docs/developer/gui.md index 413ea47..5bf16da 100644 --- a/docs/developer/gui.md +++ b/docs/developer/gui.md @@ -54,8 +54,9 @@ The entry widget has three internal modes: - **Read-back:** starts empty, normalizes only spacing and ASCII case, and never reveals expected text after a mismatch. -Enter activates the enabled primary action. Card displays use four -four-character groups per row, matching `docs/user/recovery-card.html`. +Enter activates the enabled primary action. Card displays use uppercase +four-character groups in reading order, on one line when space permits and +wrapping when needed; the paper layout remains in `docs/user/recovery-card.html`. Ordinary repair suggestions are unmarked; explicit correction may mark changed groups, which are described as changes rather than known error locations. diff --git a/tools/gui_walkthrough.py b/tools/gui_walkthrough.py index 8c68ba9..4826fb2 100644 --- a/tools/gui_walkthrough.py +++ b/tools/gui_walkthrough.py @@ -13,6 +13,7 @@ from __future__ import annotations from collections.abc import Callable, Iterator +from itertools import pairwise from typing import Any import gi @@ -294,38 +295,35 @@ def short_repair_candidate(self) -> bool: groups = [item for item in walk(page) if "card-group" in item.get_css_classes()] flow = next(item for item in walk(page) if isinstance(item, Gtk.FlowBox)) - def row_positions() -> list[float]: + def group_positions() -> list[tuple[float, float]]: children = [flow.get_child_at_index(index) for index in range(len(groups))] - return [child.compute_bounds(flow)[1].origin.y for child in children] - - def four_columns(rows_y: list[float]) -> bool: - return len(set(rows_y)) == (len(groups) + 3) // 4 and all( - rows_y[index] == rows_y[(index // 4) * 4] for index in range(len(rows_y)) + positions = [] + for child in children: + valid, bounds = child.compute_bounds(flow) + if not valid: + return [] + positions.append((bounds.origin.x, bounds.origin.y)) + return positions + + def aligned_rows(positions: list[tuple[float, float]]) -> bool: + return len(positions) == len(groups) and all( + next_y > this_y or (next_y == this_y and next_x > this_x) + for (this_x, this_y), (next_x, next_y) in pairwise(positions) ) - rows_y = row_positions() + positions = group_positions() check("Enter invokes repair for short input", "".join(item.get_label() for item in groups) == SHARE_C) check( "ordinary repair does not claim where the error was", not any("guessed" in item.get_css_classes() for item in groups), ) check( - "card display uses four aligned groups per row", - flow.get_min_children_per_line() == 4 - and flow.get_max_children_per_line() == 4 - and four_columns(rows_y), - rows_y, - ) - window = self.get_active_window() - window.set_default_size(640, 620) - settle() - narrow = row_positions() - window.set_default_size(1100, 620) - settle() - wide = row_positions() - check( - "card columns stay aligned when the window is resized", - four_columns(narrow) and four_columns(wide), + "card display wraps groups in reading order", + flow.get_min_children_per_line() == 1 + and flow.get_max_children_per_line() == len(groups) + and aligned_rows(positions) + and len({y for _, y in positions}) > 1, + positions, ) press(page, "It does not match my card") settle()