feat(tests): check every page of the default flow
What changed, and why it matters
This commit only adds a new testing helper that lets test code run an extra check on every screen page during automated button-press flows. It does not change the device firmware, wallet logic, or any production code. There is no security issue here.
No action required. This is a benign test-only feature commit.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change extends DebugUI.default_input_flow() and related test helpers with an optional on_page callback parameter. When provided, the callback is invoked with the current LayoutContent after each pagination step. This is purely test infrastructure in python/src/trezorlib/debuglink.py and tests/input_flows.py, enabling tests to inspect every page of a default confirmation flow. No cryptographic, UI, or firmware behavior is modified.
Changed components
python/src/trezorlib/debuglink.pytests/input_flows.pyInspect captured patch +38 / −8
diff --git a/python/src/trezorlib/debuglink.py b/python/src/trezorlib/debuglink.py
index 1de9f707..0fde0a21 100644
--- a/python/src/trezorlib/debuglink.py
+++ b/python/src/trezorlib/debuglink.py
@@ -1067,13 +1067,15 @@ class DebugUI:
self.input_flow: InputFlowType | object = self.default_input_flow()
next(self.input_flow) # start default input flow generator
- def default_input_flow(self) -> InputFlowType:
+ def default_input_flow(
+ self, on_page: t.Callable[["LayoutContent"], None] | None = None
+ ) -> InputFlowType:
while True:
br = yield
if br.code == messages.ButtonRequestType.PinEntry:
self.debuglink.input(self.get_pin())
else:
- self._paginate_and_confirm(br.pages)
+ self._paginate_and_confirm(br.pages, on_page=on_page)
def _visit_vertical_menu(
self, menu_layout: LayoutContent, gen: t.Generator[None, t.Any, None] | None
@@ -1179,13 +1181,19 @@ class DebugUI:
self.debuglink.click(self.debuglink.screen_buttons.menu())
return layout
- def _paginate_and_confirm(self, pages: int | None) -> None:
+ def _paginate_and_confirm(
+ self,
+ pages: int | None,
+ on_page: t.Callable[["LayoutContent"], None] | None = None,
+ ) -> None:
if pages is None:
pages = self.debuglink.read_layout().page_count()
# Paginating (going as further as possible)
for _ in range(pages - 1):
- self.visit_menu_items()
+ layout = self.visit_menu_items()
+ if on_page is not None:
+ on_page(layout)
if self.debuglink.model is models.T3W1:
self.debuglink.click(self.debuglink.screen_buttons.ok())
else:
@@ -1193,6 +1201,9 @@ class DebugUI:
layout = self.visit_menu_items()
+ if on_page is not None:
+ on_page(layout)
+
# Confirm current layout
if self.debuglink.model is models.T3T1:
if "PromptScreen" in layout.all_components():
diff --git a/tests/input_flows.py b/tests/input_flows.py
index bfb71ee3..4c606fef 100644
--- a/tests/input_flows.py
+++ b/tests/input_flows.py
@@ -3082,11 +3082,19 @@ class InputFlowResetSkipBackup(InputFlowBase):
class InputFlowConfirmAllWarnings(InputFlowBase):
+ def __init__(
+ self,
+ client: Client | DebugSession,
+ on_page: Callable[["LayoutContent"], None] | None = None,
+ ) -> None:
+ super().__init__(client)
+ self.on_page = on_page
+
def input_flow_bolt(self) -> BRGeneratorType:
- return self.client.ui.default_input_flow()
+ return self.client.ui.default_input_flow(on_page=self.on_page)
def input_flow_caesar(self) -> BRGeneratorType:
- return self.client.ui.default_input_flow()
+ return self.client.ui.default_input_flow(on_page=self.on_page)
def input_flow_delizia(self) -> BRGeneratorType:
br = yield
@@ -3094,11 +3102,16 @@ class InputFlowConfirmAllWarnings(InputFlowBase):
# Paginating (going as further as possible) and pressing Yes
if br.pages is not None:
for _ in range(br.pages - 1):
- self.client.ui.visit_menu_items()
+ layout = self.client.ui.visit_menu_items()
+ if self.on_page is not None:
+ self.on_page(layout)
self.debug.swipe_up()
layout = self.client.ui.visit_menu_items()
+ if self.on_page is not None:
+ self.on_page(layout)
+
text = layout.footer().lower()
# hi priority warning
hi_prio = (
@@ -3124,10 +3137,16 @@ class InputFlowConfirmAllWarnings(InputFlowBase):
# Paginating (going as further as possible) and pressing Yes
if br.pages is not None:
for _ in range(br.pages - 1):
- self.client.ui.visit_menu_items()
+ layout = self.client.ui.visit_menu_items()
+ if self.on_page is not None:
+ self.on_page(layout)
self.debug.click(self.debug.screen_buttons.ok())
layout = self.client.ui.visit_menu_items()
+
+ if self.on_page is not None:
+ self.on_page(layout)
+
text = layout.action_bar().lower()
# hi priority warning
hi_prio = (
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.