diff --git a/python/.changelog.d/4740.added b/python/.changelog.d/4740.added new file mode 100644 index 0000000000..f2f2328951 --- /dev/null +++ b/python/.changelog.d/4740.added @@ -0,0 +1 @@ +Add screen buttons and button actions to Debuglink. diff --git a/python/src/trezorlib/debuglink.py b/python/src/trezorlib/debuglink.py index 0a2096993b..75cb90bd46 100644 --- a/python/src/trezorlib/debuglink.py +++ b/python/src/trezorlib/debuglink.py @@ -59,6 +59,7 @@ if TYPE_CHECKING: ] AnyDict = Dict[str, Any] + Coords = Tuple[int, int] class InputFunc(Protocol): def __call__( @@ -470,6 +471,14 @@ class DebugLink: assert self.model is not None return LayoutType.from_model(self.model) + @property + def screen_buttons(self) -> ScreenButtons: + return ScreenButtons(self.layout_type) + + @property + def button_actions(self) -> ButtonActions: + return ButtonActions(self.layout_type) + def open(self) -> None: self.transport.begin_session() @@ -1385,3 +1394,303 @@ def _is_emulator(debug_client: "TrezorClientDebugLink") -> bool: def optiga_set_sec_max(client: "TrezorClient") -> None: client.call(messages.DebugLinkOptigaSetSecMax(), expect=messages.Success) + + +class ScreenButtons: + def __init__(self, layout_type: LayoutType): + assert layout_type in (LayoutType.Bolt, LayoutType.Delizia) + self.layout_type = layout_type + + def _width(self) -> int: + return 240 + + def _height(self) -> int: + return 240 + + def _grid(self, dim: int, grid_cells: int, cell: int) -> int: + assert cell < grid_cells + step = dim // grid_cells + ofs = step // 2 + return cell * step + ofs + + # 3 columns, 4 rows, 1st row is input area + def _grid35(self, x: int, y: int) -> Coords: + return self._grid(self._width(), 3, x), self._grid(self._height(), 5, y) + + # TODO: do not expose this + # 3 columns, 3 rows, 1st row is input area + def grid34(self, x: int, y: int) -> Coords: + return self._grid(self._width(), 3, x), self._grid(self._height(), 4, y) + + # Horizontal coordinates + def _left(self) -> int: + return self._grid(self._width(), 3, 0) + + def _mid(self) -> int: + return self._grid(self._width(), 3, 1) + + def _right(self) -> int: + return self._grid(self._width(), 3, 2) + + # Vertical coordinates + def _top(self) -> int: + return self._grid(self._height(), 6, 0) + + def _bottom(self) -> int: + return self._grid(self._height(), 6, 5) + + # Buttons + + # Right bottom + def ok(self) -> Coords: + return (self._right(), self._bottom()) + + # Left bottom + def cancel(self) -> Coords: + return (self._left(), self._bottom()) + + # Mid bottom + def info(self) -> Coords: + return (self._mid(), self._bottom()) + + # Menu/close menu button + def menu(self) -> Coords: + if self.layout_type in (LayoutType.Bolt, LayoutType.Delizia): + return (215, 25) + else: + raise ValueError("Wrong layout type") + + # Center of the screen + def tap_to_confirm(self) -> Coords: + assert self.layout_type is LayoutType.Delizia + return (self._grid(self._width(), 1, 0), self._grid(self._width(), 1, 0)) + + # Yes/No decision component + def ui_yes(self) -> Coords: + assert self.layout_type is LayoutType.Delizia + return self.grid34(2, 2) + + def ui_no(self) -> Coords: + assert self.layout_type is LayoutType.Delizia + return self.grid34(0, 2) + + # +/- buttons in number input component + def number_input_minus(self) -> Coords: + if self.layout_type is LayoutType.Bolt: + return (self._left(), self._grid(self._height(), 5, 1)) + elif self.layout_type is LayoutType.Delizia: + return (self._left(), self._grid(self._height(), 5, 3)) + else: + raise ValueError("Wrong layout type") + + def number_input_plus(self) -> Coords: + if self.layout_type is LayoutType.Bolt: + return (self._right(), self._grid(self._height(), 5, 1)) + elif self.layout_type is LayoutType.Delizia: + return (self._right(), self._grid(self._height(), 5, 3)) + else: + raise ValueError("Wrong layout type") + + def word_count_all_word(self, word_count: int) -> Coords: + assert word_count in (12, 18, 20, 24, 33) + if self.layout_type is LayoutType.Bolt: + coords_map = { + 12: self.grid34(0, 2), + 18: self.grid34(1, 2), + 20: self.grid34(2, 2), + 24: self.grid34(1, 3), + 33: self.grid34(2, 3), + } + elif self.layout_type is LayoutType.Delizia: + coords_map = { + 12: self.grid34(0, 1), + 18: self.grid34(2, 1), + 20: self.grid34(0, 2), + 24: self.grid34(2, 2), + 33: self.grid34(2, 3), + } + else: + raise ValueError("Wrong layout type") + + return coords_map[word_count] + + def word_count_all_cancel(self) -> Coords: + if self.layout_type is LayoutType.Bolt: + return self.grid34(0, 3) + + elif self.layout_type is LayoutType.Delizia: + return self.grid34(0, 3) + + else: + raise ValueError("Wrong layout type") + + def word_count_repeated_word(self, word_count: int) -> Coords: + assert word_count in (20, 33) + if self.layout_type is LayoutType.Bolt: + coords_map = { + 20: self.grid34(1, 2), + 33: self.grid34(2, 2), + } + elif self.layout_type is LayoutType.Delizia: + coords_map = { + 20: self.grid34(0, 1), + 33: self.grid34(2, 1), + } + else: + raise ValueError("Wrong layout type") + + return coords_map[word_count] + + def word_count_repeated_cancel(self) -> Coords: + if self.layout_type is LayoutType.Bolt: + return self.grid34(0, 2) + + elif self.layout_type is LayoutType.Delizia: + return self.grid34(0, 3) + + else: + raise ValueError("Wrong layout type") + + # select word component buttons + def word_check_words(self) -> "list[Coords]": + if self.layout_type in (LayoutType.Bolt, LayoutType.Delizia): + return [ + (self._mid(), self._grid(self._height(), 5, 2)), + (self._mid(), self._grid(self._height(), 5, 3)), + (self._mid(), self._grid(self._height(), 5, 4)), + ] + else: + raise ValueError("Wrong layout type") + + # vertical menu buttons + def vertical_menu_items(self) -> "list[Coords]": + assert self.layout_type is LayoutType.Delizia + + return [ + (self._mid(), self._grid(self._height(), 4, 1)), + (self._mid(), self._grid(self._height(), 4, 2)), + (self._mid(), self._grid(self._height(), 4, 3)), + ] + + # Pin/passphrase keyboards + def pin_passphrase_index(self, idx: int) -> Coords: + assert idx < 10 + if idx == 9: + idx = 10 # last digit is in the middle + return self.pin_passphrase_grid(idx % 3, idx // 3) + + def pin_passphrase_grid(self, x: int, y: int) -> Coords: + assert x < 3, y < 4 + y += 1 # first line is empty + return self._grid35(x, y) + + # PIN/passphrase input + def pin_passphrase_input(self) -> Coords: + return (self._mid(), self._top()) + + def pin_passphrase_erase(self) -> Coords: + return self.pin_passphrase_grid(0, 3) + + def passphrase_confirm(self) -> Coords: + if self.layout_type is LayoutType.Bolt: + return self.pin_passphrase_grid(2, 3) + elif self.layout_type is LayoutType.Delizia: + return (215, 25) + else: + raise ValueError("Wrong layout type") + + def pin_confirm(self) -> Coords: + return self.pin_passphrase_grid(2, 3) + + # Mnemonic keyboard + def mnemonic_from_index(self, idx: int) -> Coords: + return self.mnemonic_grid(idx) + + def mnemonic_grid(self, idx: int) -> Coords: + assert idx < 9 + grid_x = idx % 3 + grid_y = idx // 3 + 1 # first line is empty + return self.grid34(grid_x, grid_y) + + def mnemonic_erase(self) -> Coords: + return (self._left(), self._top()) + + def mnemonic_confirm(self) -> Coords: + return (self._mid(), self._top()) + + +BUTTON_LETTERS_BIP39 = ("abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "vwx", "yz") +BUTTON_LETTERS_SLIP39 = ("ab", "cd", "ef", "ghij", "klm", "nopq", "rs", "tuv", "wxyz") + +# fmt: off +PASSPHRASE_LOWERCASE_BOLT = (" ", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz", "*#") +PASSPHRASE_LOWERCASE_DELIZIA = ("abc", "def", "ghi", "jkl", "mno", "pq", "rst", "uvw", "xyz", " *#") +PASSPHRASE_UPPERCASE_BOLT = (" ", "ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ", "*#") +PASSPHRASE_UPPERCASE_DELIZIA = ("ABC", "DEF", "GHI", "JKL", "MNO", "PQ", "RST", "UVW", "XYZ", " *#") +PASSPHRASE_DIGITS = ("1", "2", "3", "4", "5", "6", "7", "8", "9", "0") +PASSPHRASE_SPECIAL = ("_<>", ".:@", "/|\\", "!()", "+%&", "-[]", "?{}", ",'`", ";\"~", "$^=") +# fmt: on + + +class ButtonActions: + def __init__(self, layout_type: LayoutType): + self.buttons = ScreenButtons(layout_type) + + def _passphrase_choices(self, char: str) -> "tuple[str, ...]": + if char in " *#" or char.islower(): + if self.buttons.layout_type is LayoutType.Bolt: + return PASSPHRASE_LOWERCASE_BOLT + elif self.buttons.layout_type is LayoutType.Delizia: + return PASSPHRASE_LOWERCASE_DELIZIA + else: + raise ValueError("Wrong layout type") + elif char.isupper(): + if self.buttons.layout_type is LayoutType.Bolt: + return PASSPHRASE_UPPERCASE_BOLT + elif self.buttons.layout_type is LayoutType.Delizia: + return PASSPHRASE_UPPERCASE_DELIZIA + else: + raise ValueError("Wrong layout type") + elif char.isdigit(): + return PASSPHRASE_DIGITS + else: + return PASSPHRASE_SPECIAL + + def passphrase(self, char: str) -> Tuple[Coords, int]: + choices = self._passphrase_choices(char) + idx = next(i for i, letters in enumerate(choices) if char in letters) + click_amount = choices[idx].index(char) + 1 + return self.buttons.pin_passphrase_index(idx), click_amount + + def type_word(self, word: str, is_slip39: bool = False) -> Iterator[Coords]: + if is_slip39: + yield from self._type_word_slip39(word) + else: + yield from self._type_word_bip39(word) + + def _type_word_slip39(self, word: str) -> Iterator[Coords]: + for l in word: + idx = next( + i for i, letters in enumerate(BUTTON_LETTERS_SLIP39) if l in letters + ) + yield self.buttons.mnemonic_from_index(idx) + + def _type_word_bip39(self, word: str) -> Iterator[Coords]: + coords_prev: Coords | None = None + for letter in word: + time.sleep(0.1) # not being so quick to miss something + coords, amount = self._letter_coords_and_amount(letter) + # If the button is the same as for the previous letter, + # waiting a second before pressing it again. + if coords == coords_prev: + time.sleep(1.1) + coords_prev = coords + for _ in range(amount): + yield coords + + def _letter_coords_and_amount(self, letter: str) -> Tuple[Coords, int]: + idx = next( + i for i, letters in enumerate(BUTTON_LETTERS_BIP39) if letter in letters + ) + click_amount = BUTTON_LETTERS_BIP39[idx].index(letter) + 1 + return self.buttons.mnemonic_from_index(idx), click_amount diff --git a/tests/buttons.py b/tests/buttons.py deleted file mode 100644 index 997a1d3da9..0000000000 --- a/tests/buttons.py +++ /dev/null @@ -1,306 +0,0 @@ -import time -from typing import Iterator, Tuple - -from trezorlib.debuglink import LayoutType - -Coords = Tuple[int, int] - - -class ScreenButtons: - def __init__(self, layout_type: LayoutType): - assert layout_type in (LayoutType.Bolt, LayoutType.Delizia) - self.layout_type = layout_type - - def _width(self) -> int: - return 240 - - def _height(self) -> int: - return 240 - - def _grid(self, dim: int, grid_cells: int, cell: int) -> int: - assert cell < grid_cells - step = dim // grid_cells - ofs = step // 2 - return cell * step + ofs - - # 3 columns, 4 rows, 1st row is input area - def _grid35(self, x: int, y: int) -> Coords: - return self._grid(self._width(), 3, x), self._grid(self._height(), 5, y) - - # TODO: do not expose this - # 3 columns, 3 rows, 1st row is input area - def grid34(self, x: int, y: int) -> Coords: - return self._grid(self._width(), 3, x), self._grid(self._height(), 4, y) - - # Horizontal coordinates - def _left(self) -> int: - return self._grid(self._width(), 3, 0) - - def _mid(self) -> int: - return self._grid(self._width(), 3, 1) - - def _right(self) -> int: - return self._grid(self._width(), 3, 2) - - # Vertical coordinates - def _top(self) -> int: - return self._grid(self._height(), 6, 0) - - def _bottom(self) -> int: - return self._grid(self._height(), 6, 5) - - # Buttons - - # Right bottom - def ok(self) -> Coords: - return (self._right(), self._bottom()) - - # Left bottom - def cancel(self) -> Coords: - return (self._left(), self._bottom()) - - # Mid bottom - def info(self) -> Coords: - return (self._mid(), self._bottom()) - - # Menu/close menu button - def menu(self) -> Coords: - if self.layout_type in (LayoutType.Bolt, LayoutType.Delizia): - return (215, 25) - else: - raise ValueError("Wrong layout type") - - # Center of the screen - def tap_to_confirm(self) -> Coords: - assert self.layout_type is LayoutType.Delizia - return (self._grid(self._width(), 1, 0), self._grid(self._width(), 1, 0)) - - # Yes/No decision component - def ui_yes(self) -> Coords: - assert self.layout_type is LayoutType.Delizia - return self.grid34(2, 2) - - def ui_no(self) -> Coords: - assert self.layout_type is LayoutType.Delizia - return self.grid34(0, 2) - - # +/- buttons in number input component - def number_input_minus(self) -> Coords: - if self.layout_type is LayoutType.Bolt: - return (self._left(), self._grid(self._height(), 5, 1)) - elif self.layout_type is LayoutType.Delizia: - return (self._left(), self._grid(self._height(), 5, 3)) - else: - raise ValueError("Wrong layout type") - - def number_input_plus(self) -> Coords: - if self.layout_type is LayoutType.Bolt: - return (self._right(), self._grid(self._height(), 5, 1)) - elif self.layout_type is LayoutType.Delizia: - return (self._right(), self._grid(self._height(), 5, 3)) - else: - raise ValueError("Wrong layout type") - - def word_count_all_word(self, word_count: int) -> Coords: - assert word_count in (12, 18, 20, 24, 33) - if self.layout_type is LayoutType.Bolt: - coords_map = { - 12: self.grid34(0, 2), - 18: self.grid34(1, 2), - 20: self.grid34(2, 2), - 24: self.grid34(1, 3), - 33: self.grid34(2, 3), - } - elif self.layout_type is LayoutType.Delizia: - coords_map = { - 12: self.grid34(0, 1), - 18: self.grid34(2, 1), - 20: self.grid34(0, 2), - 24: self.grid34(2, 2), - 33: self.grid34(2, 3), - } - else: - raise ValueError("Wrong layout type") - - return coords_map[word_count] - - def word_count_all_cancel(self) -> Coords: - if self.layout_type is LayoutType.Bolt: - return self.grid34(0, 3) - - elif self.layout_type is LayoutType.Delizia: - return self.grid34(0, 3) - - else: - raise ValueError("Wrong layout type") - - def word_count_repeated_word(self, word_count: int) -> Coords: - assert word_count in (20, 33) - if self.layout_type is LayoutType.Bolt: - coords_map = { - 20: self.grid34(1, 2), - 33: self.grid34(2, 2), - } - elif self.layout_type is LayoutType.Delizia: - coords_map = { - 20: self.grid34(0, 1), - 33: self.grid34(2, 1), - } - else: - raise ValueError("Wrong layout type") - - return coords_map[word_count] - - def word_count_repeated_cancel(self) -> Coords: - if self.layout_type is LayoutType.Bolt: - return self.grid34(0, 2) - - elif self.layout_type is LayoutType.Delizia: - return self.grid34(0, 3) - - else: - raise ValueError("Wrong layout type") - - # select word component buttons - def word_check_words(self) -> "list[Coords]": - if self.layout_type in (LayoutType.Bolt, LayoutType.Delizia): - return [ - (self._mid(), self._grid(self._height(), 5, 2)), - (self._mid(), self._grid(self._height(), 5, 3)), - (self._mid(), self._grid(self._height(), 5, 4)), - ] - else: - raise ValueError("Wrong layout type") - - # vertical menu buttons - def vertical_menu_items(self) -> "list[Coords]": - assert self.layout_type is LayoutType.Delizia - - return [ - (self._mid(), self._grid(self._height(), 4, 1)), - (self._mid(), self._grid(self._height(), 4, 2)), - (self._mid(), self._grid(self._height(), 4, 3)), - ] - - # Pin/passphrase keyboards - def pin_passphrase_index(self, idx: int) -> Coords: - assert idx < 10 - if idx == 9: - idx = 10 # last digit is in the middle - return self.pin_passphrase_grid(idx % 3, idx // 3) - - def pin_passphrase_grid(self, x: int, y: int) -> Coords: - assert x < 3, y < 4 - y += 1 # first line is empty - return self._grid35(x, y) - - # PIN/passphrase input - def pin_passphrase_input(self) -> Coords: - return (self._mid(), self._top()) - - def pin_passphrase_erase(self) -> Coords: - return self.pin_passphrase_grid(0, 3) - - def passphrase_confirm(self) -> Coords: - if self.layout_type is LayoutType.Bolt: - return self.pin_passphrase_grid(2, 3) - elif self.layout_type is LayoutType.Delizia: - return (215, 25) - else: - raise ValueError("Wrong layout type") - - def pin_confirm(self) -> Coords: - return self.pin_passphrase_grid(2, 3) - - # Mnemonic keyboard - def mnemonic_from_index(self, idx: int) -> Coords: - return self.mnemonic_grid(idx) - - def mnemonic_grid(self, idx: int) -> Coords: - assert idx < 9 - grid_x = idx % 3 - grid_y = idx // 3 + 1 # first line is empty - return self.grid34(grid_x, grid_y) - - def mnemonic_erase(self) -> Coords: - return (self._left(), self._top()) - - def mnemonic_confirm(self) -> Coords: - return (self._mid(), self._top()) - - -BUTTON_LETTERS_BIP39 = ("abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "vwx", "yz") -BUTTON_LETTERS_SLIP39 = ("ab", "cd", "ef", "ghij", "klm", "nopq", "rs", "tuv", "wxyz") - -# fmt: off -PASSPHRASE_LOWERCASE_BOLT = (" ", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz", "*#") -PASSPHRASE_LOWERCASE_DELIZIA = ("abc", "def", "ghi", "jkl", "mno", "pq", "rst", "uvw", "xyz", " *#") -PASSPHRASE_UPPERCASE_BOLT = (" ", "ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ", "*#") -PASSPHRASE_UPPERCASE_DELIZIA = ("ABC", "DEF", "GHI", "JKL", "MNO", "PQ", "RST", "UVW", "XYZ", " *#") -PASSPHRASE_DIGITS = ("1", "2", "3", "4", "5", "6", "7", "8", "9", "0") -PASSPHRASE_SPECIAL = ("_<>", ".:@", "/|\\", "!()", "+%&", "-[]", "?{}", ",'`", ";\"~", "$^=") -# fmt: on - - -class ButtonActions: - def __init__(self, layout_type: LayoutType): - self.buttons = ScreenButtons(layout_type) - - def _passphrase_choices(self, char: str) -> tuple[str, ...]: - if char in " *#" or char.islower(): - if self.layout_type is LayoutType.Bolt: - return PASSPHRASE_LOWERCASE_BOLT - elif self.layout_type is LayoutType.Delizia: - return PASSPHRASE_LOWERCASE_DELIZIA - else: - raise ValueError("Wrong layout type") - elif char.isupper(): - if self.layout_type is LayoutType.Bolt: - return PASSPHRASE_UPPERCASE_BOLT - elif self.layout_type is LayoutType.Delizia: - return PASSPHRASE_UPPERCASE_DELIZIA - else: - raise ValueError("Wrong layout type") - elif char.isdigit(): - return PASSPHRASE_DIGITS - else: - return PASSPHRASE_SPECIAL - - def passphrase(self, char: str) -> Tuple[Coords, int]: - choices = self._passphrase_choices(char) - idx = next(i for i, letters in enumerate(choices) if char in letters) - click_amount = choices[idx].index(char) + 1 - return self.buttons.pin_passphrase_index(idx), click_amount - - def type_word(self, word: str, is_slip39: bool = False) -> Iterator[Coords]: - if is_slip39: - yield from self._type_word_slip39(word) - else: - yield from self._type_word_bip39(word) - - def _type_word_slip39(self, word: str) -> Iterator[Coords]: - for l in word: - idx = next( - i for i, letters in enumerate(BUTTON_LETTERS_SLIP39) if l in letters - ) - yield self.buttons.mnemonic_from_index(idx) - - def _type_word_bip39(self, word: str) -> Iterator[Coords]: - coords_prev: Coords | None = None - for letter in word: - time.sleep(0.1) # not being so quick to miss something - coords, amount = self._letter_coords_and_amount(letter) - # If the button is the same as for the previous letter, - # waiting a second before pressing it again. - if coords == coords_prev: - time.sleep(1.1) - coords_prev = coords - for _ in range(amount): - yield coords - - def _letter_coords_and_amount(self, letter: str) -> Tuple[Coords, int]: - idx = next( - i for i, letters in enumerate(BUTTON_LETTERS_BIP39) if letter in letters - ) - click_amount = BUTTON_LETTERS_BIP39[idx].index(letter) + 1 - return self.buttons.mnemonic_from_index(idx), click_amount diff --git a/tests/click_tests/common.py b/tests/click_tests/common.py index 30ff151b54..869e847eea 100644 --- a/tests/click_tests/common.py +++ b/tests/click_tests/common.py @@ -5,7 +5,6 @@ from enum import Enum from trezorlib.debuglink import LayoutType -from .. import buttons from .. import translations as TR if t.TYPE_CHECKING: @@ -49,8 +48,7 @@ def get_char_category(char: str) -> PassphraseCategory: def go_next(debug: "DebugLink") -> LayoutContent: if debug.layout_type is LayoutType.Bolt: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.ok()) + debug.click(debug.screen_buttons.ok()) elif debug.layout_type is LayoutType.Caesar: debug.press_right() elif debug.layout_type is LayoutType.Delizia: @@ -62,8 +60,7 @@ def go_next(debug: "DebugLink") -> LayoutContent: def go_back(debug: "DebugLink", r_middle: bool = False) -> LayoutContent: if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia): - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.cancel()) + debug.click(debug.screen_buttons.cancel()) elif debug.layout_type is LayoutType.Caesar: if r_middle: debug.press_middle() @@ -118,13 +115,11 @@ def _carousel_steps(current_index: int, wanted_index: int, length: int) -> int: def unlock_gesture(debug: "DebugLink") -> LayoutContent: if debug.layout_type is LayoutType.Bolt: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.ok()) + debug.click(debug.screen_buttons.ok()) elif debug.layout_type is LayoutType.Caesar: debug.press_right() elif debug.layout_type is LayoutType.Delizia: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.tap_to_confirm()) + debug.click(debug.screen_buttons.tap_to_confirm()) else: raise RuntimeError("Unknown model") return debug.read_layout() diff --git a/tests/click_tests/record_layout.py b/tests/click_tests/record_layout.py index a640efb421..8f2ac79a7e 100644 --- a/tests/click_tests/record_layout.py +++ b/tests/click_tests/record_layout.py @@ -10,7 +10,6 @@ import inspect import sys import threading import time -from pathlib import Path import click @@ -35,12 +34,6 @@ from trezorlib.cli.trezorctl import cli as main from trezorlib import cli, debuglink, protobuf # isort:skip - -# make /tests part of sys.path so that we can import buttons.py as a module -ROOT = Path(__file__).resolve().parent.parent -sys.path.append(str(ROOT)) -import buttons # isort:skip - MODULES = ( binance, btc, @@ -142,34 +135,24 @@ def send_clicks(dest): elif key.startswith("m"): x, y = [int(s) - 1 for s in key[1:].split(",")] output = ( - f"debug.click(ScreenButtons(layout_type).mnemonic_grid({x}, {y}))" - ) - DEBUGLINK.click( - buttons.ScreenButtons(DEBUGLINK.layout_type).mnemonic_grid(x, y) + f"debug.click(DEBUGLINK.screen_buttons.mnemonic_grid({x}, {y}))" ) + DEBUGLINK.click(DEBUGLINK.screen_buttons.mnemonic_grid(x, y)) elif key.startswith("p"): x, y = [int(s) - 1 for s in key[1:].split(",")] - output = f"debug.click(ScreenButtons(layout_type).pin_passphrase_grid({x}, {y}))" - DEBUGLINK.click( - buttons.ScreenButtons(DEBUGLINK.layout_type).pin_passphrase_grid( - x, y - ) - ) + output = f"debug.click(DEBUGLINK.screen_buttons.pin_passphrase_grid({x}, {y}))" + DEBUGLINK.click(DEBUGLINK.screen_buttons.pin_passphrase_grid(x, y)) elif key == "y": - output = "debug.click(ScreenButtons(layout_type).ok())" - DEBUGLINK.click(buttons.ScreenButtons(DEBUGLINK.layout_type).ok()) + output = "debug.click(DEBUGLINK.screen_buttons.ok())" + DEBUGLINK.click(DEBUGLINK.screen_buttons.ok()) elif key == "n": - output = "debug.click(ScreenButtons(layout_type).cancel())" - DEBUGLINK.click(buttons.ScreenButtons(DEBUGLINK.layout_type).cancel()) + output = "debug.click(DEBUGLINK.screen_buttons.cancel())" + DEBUGLINK.click(DEBUGLINK.screen_buttons.cancel()) elif key in "0123456789": index = int(key) - output = f"debug.click(ScreenButtons(layout_type).pin_passphrase_index({index}))" - DEBUGLINK.click( - buttons.ScreenButtons(DEBUGLINK.layout_type).pin_passphrase_index( - index - ) - ) + output = f"debug.click(DEBUGLINK.screen_buttons.pin_passphrase_index({index}))" + DEBUGLINK.click(DEBUGLINK.screen_buttons.pin_passphrase_index(index)) elif key == "stop": return else: diff --git a/tests/click_tests/recovery.py b/tests/click_tests/recovery.py index e264a61e4f..6fd71b5550 100644 --- a/tests/click_tests/recovery.py +++ b/tests/click_tests/recovery.py @@ -2,7 +2,6 @@ from typing import TYPE_CHECKING from trezorlib.debuglink import LayoutType -from .. import buttons from .. import translations as TR from .common import go_next @@ -17,15 +16,13 @@ def enter_word( debug: "DebugLink", word: str, is_slip39: bool = False ) -> "LayoutContent": if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia): - btns = buttons.ScreenButtons(debug.layout_type) - actions = buttons.ButtonActions(debug.layout_type) typed_word = word[:4] - for coords in actions.type_word(typed_word, is_slip39=is_slip39): + for coords in debug.button_actions.type_word(typed_word, is_slip39=is_slip39): debug.click(coords) if debug.layout_type is LayoutType.Delizia and not is_slip39 and len(word) > 4: # T3T1 (delizia) BIP39 keyboard allows to "confirm" only if the word is fully written, you need to click the word to auto-complete - debug.click(btns.mnemonic_confirm()) - debug.click(btns.mnemonic_confirm()) + debug.click(debug.screen_buttons.mnemonic_confirm()) + debug.click(debug.screen_buttons.mnemonic_confirm()) return debug.read_layout() elif debug.layout_type is LayoutType.Caesar: letter_index = 0 @@ -57,8 +54,7 @@ def confirm_recovery(debug: "DebugLink", title: str = "recovery__title") -> None layout = debug.read_layout() assert TR.translate(title) == layout.title() if debug.layout_type is LayoutType.Bolt: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.ok()) + debug.click(debug.screen_buttons.ok()) elif debug.layout_type is LayoutType.Delizia: debug.swipe_up() elif debug.layout_type is LayoutType.Caesar: @@ -71,13 +67,12 @@ def cancel_select_number_of_words( unlock_repeated_backup=False, ) -> None: if debug.layout_type is LayoutType.Bolt: - btns = buttons.ScreenButtons(debug.layout_type) assert debug.read_layout().text_content() == TR.recovery__num_of_words # click the button from ValuePad if unlock_repeated_backup: - coords = btns.word_count_repeated_cancel() + coords = debug.screen_buttons.word_count_repeated_cancel() else: - coords = btns.word_count_all_cancel() + coords = debug.screen_buttons.word_count_all_cancel() debug.click(coords) elif debug.layout_type is LayoutType.Caesar: debug.press_right() @@ -86,12 +81,11 @@ def cancel_select_number_of_words( # navigate to the number and confirm it debug.press_left() elif debug.layout_type is LayoutType.Delizia: - btns = buttons.ScreenButtons(debug.layout_type) # click the button from ValuePad if unlock_repeated_backup: - coords = btns.word_count_repeated_cancel() + coords = debug.screen_buttons.word_count_repeated_cancel() else: - coords = btns.word_count_all_cancel() + coords = debug.screen_buttons.word_count_all_cancel() debug.click(coords) else: raise ValueError("Unknown model") @@ -106,12 +100,11 @@ def select_number_of_words( assert TR.recovery__num_of_words in layout.text_content() def select_bolt() -> "LayoutContent": - btns = buttons.ScreenButtons(debug.layout_type) # click the button from ValuePad if unlock_repeated_backup: - coords = btns.word_count_repeated_word(num_of_words) + coords = debug.screen_buttons.word_count_repeated_word(num_of_words) else: - coords = btns.word_count_all_word(num_of_words) + coords = debug.screen_buttons.word_count_all_word(num_of_words) debug.click(coords) return debug.read_layout() @@ -126,12 +119,11 @@ def select_number_of_words( return debug.read_layout() def select_delizia() -> "LayoutContent": - btns = buttons.ScreenButtons(debug.layout_type) # click the button from ValuePad if unlock_repeated_backup: - coords = btns.word_count_repeated_word(num_of_words) + coords = debug.screen_buttons.word_count_repeated_word(num_of_words) else: - coords = btns.word_count_all_word(num_of_words) + coords = debug.screen_buttons.word_count_all_word(num_of_words) debug.click(coords) return debug.read_layout() @@ -186,9 +178,8 @@ def enter_share( debug.swipe_up() layout = debug.read_layout() else: - btns = buttons.ScreenButtons(debug.layout_type) assert TR.translate(before_title) in debug.read_layout().title() - debug.click(btns.ok()) + debug.click(debug.screen_buttons.ok()) layout = debug.read_layout() assert "MnemonicKeyboard" in layout.all_components() @@ -263,10 +254,9 @@ def enter_seed_previous_correct( if go_back: go_back = False if debug.layout_type is LayoutType.Bolt: - btns = buttons.ScreenButtons(debug.layout_type) debug.swipe_right() for _ in range(len(bad_word)): - debug.click(btns.mnemonic_erase()) + debug.click(debug.screen_buttons.mnemonic_erase()) elif debug.layout_type is LayoutType.Caesar: layout = debug.read_layout() @@ -283,10 +273,9 @@ def enter_seed_previous_correct( debug.press_middle() layout = debug.read_layout() elif debug.layout_type is LayoutType.Delizia: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.mnemonic_erase()) # Top-left + debug.click(debug.screen_buttons.mnemonic_erase()) # Top-left for _ in range(len(bad_word)): - debug.click(btns.mnemonic_erase()) + debug.click(debug.screen_buttons.mnemonic_erase()) continue if i in bad_indexes: @@ -311,8 +300,7 @@ def prepare_enter_seed( or TR.translate(layout_text) in debug.read_layout().text_content() ) if debug.layout_type is LayoutType.Bolt: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.ok()) + debug.click(debug.screen_buttons.ok()) elif debug.layout_type is LayoutType.Delizia: debug.swipe_up() debug.swipe_up() @@ -338,11 +326,10 @@ def cancel_recovery(debug: "DebugLink", recovery_type: str = "dry_run") -> None: assert title in layout.title() if debug.layout_type is LayoutType.Bolt: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.cancel()) + debug.click(debug.screen_buttons.cancel()) layout = debug.read_layout() assert cancel_title in layout.title() - debug.click(btns.ok()) + debug.click(debug.screen_buttons.ok()) elif debug.layout_type is LayoutType.Caesar: debug.press_left() layout = debug.read_layout() @@ -350,14 +337,13 @@ def cancel_recovery(debug: "DebugLink", recovery_type: str = "dry_run") -> None: for _ in range(layout.page_count()): debug.press_right() elif debug.layout_type is LayoutType.Delizia: - btns = buttons.ScreenButtons(debug.layout_type) # go to menu - debug.click(btns.menu()) + debug.click(debug.screen_buttons.menu()) layout = debug.read_layout() assert ( TR.translate(f"recovery__cancel_{recovery_type}") in layout.text_content() ) - debug.click(btns.vertical_menu_items()[0]) + debug.click(debug.screen_buttons.vertical_menu_items()[0]) else: raise ValueError("Unknown model") diff --git a/tests/click_tests/reset.py b/tests/click_tests/reset.py index 446792fb7f..9978f33e5c 100644 --- a/tests/click_tests/reset.py +++ b/tests/click_tests/reset.py @@ -5,7 +5,6 @@ from shamir_mnemonic import shamir # type: ignore from trezorlib.debuglink import LayoutType -from .. import buttons from .. import translations as TR if TYPE_CHECKING: @@ -15,12 +14,10 @@ if TYPE_CHECKING: def confirm_new_wallet(debug: "DebugLink") -> None: assert debug.read_layout().title() == TR.reset__title_create_wallet if debug.layout_type is LayoutType.Bolt: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.ok()) + debug.click(debug.screen_buttons.ok()) elif debug.layout_type is LayoutType.Delizia: - btns = buttons.ScreenButtons(debug.layout_type) debug.swipe_up() - debug.click(btns.tap_to_confirm()) + debug.click(debug.screen_buttons.tap_to_confirm()) elif debug.layout_type is LayoutType.Caesar: debug.press_right() debug.press_right() @@ -34,8 +31,7 @@ def confirm_new_wallet(debug: "DebugLink") -> None: def confirm_read(debug: "DebugLink", middle_r: bool = False) -> None: if debug.layout_type is LayoutType.Bolt: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.ok()) + debug.click(debug.screen_buttons.ok()) elif debug.layout_type is LayoutType.Delizia: debug.swipe_up() elif debug.layout_type is LayoutType.Caesar: @@ -53,16 +49,14 @@ def cancel_backup( debug: "DebugLink", middle_r: bool = False, confirm: bool = False ) -> None: if debug.layout_type is LayoutType.Bolt: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.cancel()) - debug.click(btns.cancel()) + debug.click(debug.screen_buttons.cancel()) + debug.click(debug.screen_buttons.cancel()) elif debug.layout_type is LayoutType.Delizia: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.menu()) - debug.click(btns.vertical_menu_items()[0]) + debug.click(debug.screen_buttons.menu()) + debug.click(debug.screen_buttons.vertical_menu_items()[0]) if confirm: debug.swipe_up() - debug.click(btns.tap_to_confirm()) + debug.click(debug.screen_buttons.tap_to_confirm()) elif debug.layout_type is LayoutType.Caesar: debug.press_left() debug.press_left() @@ -70,16 +64,19 @@ def cancel_backup( def set_selection(debug: "DebugLink", diff: int) -> None: if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia): - btns = buttons.ScreenButtons(debug.layout_type) assert "NumberInputDialog" in debug.read_layout().all_components() - button = btns.number_input_minus() if diff < 0 else btns.number_input_plus() + button = ( + debug.screen_buttons.number_input_minus() + if diff < 0 + else debug.screen_buttons.number_input_plus() + ) diff = abs(diff) for _ in range(diff): debug.click(button) if debug.layout_type is LayoutType.Bolt: - debug.click(btns.ok()) + debug.click(debug.screen_buttons.ok()) else: debug.swipe_up() elif debug.layout_type is LayoutType.Caesar: @@ -125,11 +122,9 @@ def read_words(debug: "DebugLink", do_htc: bool = True) -> list[str]: # There is hold-to-confirm button if do_htc: if debug.layout_type is LayoutType.Bolt: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.ok(), hold_ms=1500) + debug.click(debug.screen_buttons.ok(), hold_ms=1500) elif debug.layout_type is LayoutType.Delizia: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.tap_to_confirm()) + debug.click(debug.screen_buttons.tap_to_confirm()) elif debug.layout_type is LayoutType.Caesar: debug.press_right(hold_ms=1200) else: @@ -146,7 +141,6 @@ def confirm_words(debug: "DebugLink", words: list[str]) -> None: layout = debug.read_layout() if debug.layout_type is LayoutType.Bolt: - btns = buttons.ScreenButtons(debug.layout_type) assert TR.regexp("reset__select_word_x_of_y_template").match( layout.text_content() ) @@ -162,10 +156,9 @@ def confirm_words(debug: "DebugLink", words: list[str]) -> None: ] wanted_word = words[word_pos - 1].lower() button_pos = btn_texts.index(wanted_word) - debug.click(btns.word_check_words()[button_pos]) + debug.click(debug.screen_buttons.word_check_words()[button_pos]) layout = debug.read_layout() elif debug.layout_type is LayoutType.Delizia: - btns = buttons.ScreenButtons(debug.layout_type) assert TR.regexp("reset__select_word_x_of_y_template").match(layout.subtitle()) for _ in range(3): # "Select word 3 of 20" @@ -179,7 +172,7 @@ def confirm_words(debug: "DebugLink", words: list[str]) -> None: ] wanted_word = words[word_pos - 1].lower() button_pos = btn_texts.index(wanted_word) - debug.click(btns.vertical_menu_items()[button_pos]) + debug.click(debug.screen_buttons.vertical_menu_items()[button_pos]) layout = debug.read_layout() elif debug.layout_type is LayoutType.Caesar: assert TR.reset__select_correct_word in layout.text_content() diff --git a/tests/click_tests/test_autolock.py b/tests/click_tests/test_autolock.py index db1ac31465..9de92b57ac 100644 --- a/tests/click_tests/test_autolock.py +++ b/tests/click_tests/test_autolock.py @@ -25,7 +25,7 @@ from trezorlib.debuglink import DebugLink, LayoutType from trezorlib.protobuf import MessageType from trezorlib.tools import parse_path -from .. import buttons, common +from .. import common from .. import translations as TR from ..device_tests.bitcoin.payment_req import make_coinjoin_request from ..tx_cache import TxCache @@ -54,16 +54,14 @@ PIN4 = "1234" def _passphrase_j(debug: DebugLink) -> Tuple[int, int]: - btns = buttons.ScreenButtons(debug.layout_type) if debug.layout_type is LayoutType.Bolt: - return btns.pin_passphrase_grid(1, 1) + return debug.screen_buttons.pin_passphrase_grid(1, 1) else: - return btns.pin_passphrase_grid(0, 1) + return debug.screen_buttons.pin_passphrase_grid(0, 1) def _center_button(debug: DebugLink) -> Tuple[int, int]: - btns = buttons.ScreenButtons(debug.layout_type) - return btns.pin_passphrase_grid(1, 1) + return debug.screen_buttons.pin_passphrase_grid(1, 1) def set_autolock_delay(device_handler: "BackgroundDeviceHandler", delay_ms: int): @@ -81,8 +79,7 @@ def set_autolock_delay(device_handler: "BackgroundDeviceHandler", delay_ms: int) layout = go_next(debug) if debug.layout_type is LayoutType.Delizia: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.tap_to_confirm()) + debug.click(debug.screen_buttons.tap_to_confirm()) layout = debug.read_layout() assert layout.main_component() == "Homescreen" device_handler.result() @@ -117,9 +114,8 @@ def test_autolock_interrupts_signing(device_handler: "BackgroundDeviceHandler"): ) if debug.layout_type is LayoutType.Bolt: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.ok()) - debug.click(btns.ok()) + debug.click(debug.screen_buttons.ok()) + debug.click(debug.screen_buttons.ok()) layout = debug.read_layout() assert TR.send__total_amount in layout.text_content() assert "0.0039 BTC" in layout.text_content() @@ -173,14 +169,12 @@ def test_autolock_does_not_interrupt_signing(device_handler: "BackgroundDeviceHa ) if debug.layout_type is LayoutType.Bolt: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.ok()) - debug.click(btns.ok()) + debug.click(debug.screen_buttons.ok()) + debug.click(debug.screen_buttons.ok()) layout = debug.read_layout() assert TR.send__total_amount in layout.text_content() assert "0.0039 BTC" in layout.text_content() elif debug.layout_type is LayoutType.Delizia: - btns = buttons.ScreenButtons(debug.layout_type) debug.swipe_up() debug.swipe_up() layout = debug.read_layout() @@ -203,9 +197,9 @@ def test_autolock_does_not_interrupt_signing(device_handler: "BackgroundDeviceHa device_handler.client.set_filter(messages.TxAck, sleepy_filter) # confirm transaction if debug.layout_type is LayoutType.Bolt: - debug.click(btns.ok()) + debug.click(debug.screen_buttons.ok()) elif debug.layout_type is LayoutType.Delizia: - debug.click(btns.tap_to_confirm()) + debug.click(debug.screen_buttons.tap_to_confirm()) elif debug.layout_type is LayoutType.Caesar: debug.press_middle() @@ -245,8 +239,7 @@ def test_autolock_passphrase_keyboard(device_handler: "BackgroundDeviceHandler") # Send the passphrase to the client (TT has it clicked already, TR needs to input it) if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia): - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.passphrase_confirm()) + debug.click(debug.screen_buttons.passphrase_confirm()) elif debug.layout_type is LayoutType.Caesar: debug.input("j" * 8) @@ -368,33 +361,29 @@ def test_dryrun_enter_word_slowly(device_handler: "BackgroundDeviceHandler"): recovery.select_number_of_words(debug, 20) if debug.layout_type is LayoutType.Bolt: - btns = buttons.ScreenButtons(debug.layout_type) - actions = buttons.ButtonActions(debug.layout_type) - debug.click(btns.ok()) + debug.click(debug.screen_buttons.ok()) layout = debug.read_layout() assert layout.main_component() == "MnemonicKeyboard" # type the word OCEAN slowly - for coords in actions.type_word("ocea", is_slip39=True): + for coords in debug.button_actions.type_word("ocea", is_slip39=True): time.sleep(9) debug.click(coords) - debug.click(btns.mnemonic_confirm()) + debug.click(debug.screen_buttons.mnemonic_confirm()) layout = debug.read_layout() # should not have locked, even though we took 9 seconds to type each letter assert layout.main_component() == "MnemonicKeyboard" elif debug.layout_type is LayoutType.Delizia: - btns = buttons.ScreenButtons(debug.layout_type) - actions = buttons.ButtonActions(debug.layout_type) debug.swipe_up() layout = debug.read_layout() assert layout.main_component() == "MnemonicKeyboard" # type the word OCEAN slowly - for coords in actions.type_word("ocea", is_slip39=True): + for coords in debug.button_actions.type_word("ocea", is_slip39=True): time.sleep(9) debug.click(coords) - debug.click(btns.mnemonic_confirm()) + debug.click(debug.screen_buttons.mnemonic_confirm()) layout = debug.read_layout() # should not have locked, even though we took 9 seconds to type each letter assert layout.main_component() == "MnemonicKeyboard" diff --git a/tests/click_tests/test_lock.py b/tests/click_tests/test_lock.py index 8d07b64c94..f8ddacec23 100644 --- a/tests/click_tests/test_lock.py +++ b/tests/click_tests/test_lock.py @@ -22,7 +22,7 @@ import pytest from trezorlib import models from trezorlib.debuglink import LayoutType -from .. import buttons, common +from .. import common if TYPE_CHECKING: from ..device_handler import BackgroundDeviceHandler @@ -81,8 +81,7 @@ def test_hold_to_lock(device_handler: "BackgroundDeviceHandler"): if debug.layout_type is LayoutType.Caesar: debug.press_right() else: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.info()) + debug.click(debug.screen_buttons.info()) layout = debug.read_layout() assert "PinKeyboard" in layout.all_components() debug.input("1234") diff --git a/tests/click_tests/test_passphrase_bolt_delizia.py b/tests/click_tests/test_passphrase_bolt_delizia.py index ba4a441a0b..f97cf12f1e 100644 --- a/tests/click_tests/test_passphrase_bolt_delizia.py +++ b/tests/click_tests/test_passphrase_bolt_delizia.py @@ -22,7 +22,6 @@ import pytest from trezorlib.debuglink import LayoutType -from .. import buttons from ..common import get_test_address from .common import CommonPass, PassphraseCategory, get_char_category @@ -50,7 +49,7 @@ KEYBOARD_CATEGORIES_DELIZIA = [ # TODO: better read this from the trace KEYBOARD_CATEGORY = PassphraseCategory.LOWERCASE -COORDS_PREV: buttons.Coords = (0, 0) +COORDS_PREV: tuple[int, int] = (0, 0) # Testing the maximum length is really 50 @@ -131,8 +130,7 @@ def press_char(debug: "DebugLink", char: str) -> None: go_to_category(debug, char_category) - actions = buttons.ButtonActions(debug.layout_type) - coords, amount = actions.passphrase(char) + coords, amount = debug.button_actions.passphrase(char) # If the button is the same as for the previous char, # waiting a second before pressing it again. # (not for a space in Bolt layout) @@ -158,16 +156,14 @@ def input_passphrase(debug: "DebugLink", passphrase: str, check: bool = True) -> def enter_passphrase(debug: "DebugLink") -> None: """Enter a passphrase""" is_empty: bool = len(debug.read_layout().passphrase()) == 0 - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.passphrase_confirm()) + debug.click(debug.screen_buttons.passphrase_confirm()) if is_empty and debug.layout_type is LayoutType.Delizia: - debug.click(btns.ui_yes()) + debug.click(debug.screen_buttons.ui_yes()) def delete_char(debug: "DebugLink") -> None: """Deletes the last char""" - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.pin_passphrase_erase()) + debug.click(debug.screen_buttons.pin_passphrase_erase()) VECTORS = ( # passphrase, address @@ -239,8 +235,7 @@ def test_passphrase_loop_all_characters(device_handler: "BackgroundDeviceHandler debug.read_layout() enter_passphrase(debug) - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.passphrase_confirm()) + debug.click(debug.screen_buttons.passphrase_confirm()) @pytest.mark.setup_client(passphrase=True) @@ -248,8 +243,7 @@ def test_passphrase_click_same_button_many_times( device_handler: "BackgroundDeviceHandler", ): with prepare_passphrase_dialogue(device_handler) as debug: - actions = buttons.ButtonActions(debug.layout_type) - a_coords, _ = actions.passphrase("a") + a_coords, _ = debug.button_actions.passphrase("a") for _ in range(10): debug.click(a_coords) diff --git a/tests/click_tests/test_pin.py b/tests/click_tests/test_pin.py index f8971d8745..b46cb32350 100644 --- a/tests/click_tests/test_pin.py +++ b/tests/click_tests/test_pin.py @@ -24,7 +24,6 @@ import pytest from trezorlib import device, exceptions from trezorlib.debuglink import LayoutType -from .. import buttons from .. import translations as TR from .common import go_back, go_next, navigate_to_action_and_press @@ -138,9 +137,8 @@ def prepare( yield debug if debug.layout_type is LayoutType.Delizia and tap: - btns = buttons.ScreenButtons(debug.layout_type) go_next(debug) - debug.click(btns.tap_to_confirm()) + debug.click(debug.screen_buttons.tap_to_confirm()) else: go_next(debug) @@ -156,11 +154,10 @@ def _input_pin(debug: "DebugLink", pin: str, check: bool = False) -> None: if check: before = debug.read_layout().pin() if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia): - btns = buttons.ScreenButtons(debug.layout_type) digits_order = debug.read_layout().tt_pin_digits_order() for digit in pin: digit_index = digits_order.index(digit) - coords = btns.pin_passphrase_index(digit_index) + coords = debug.screen_buttons.pin_passphrase_index(digit_index) debug.click(coords) elif debug.layout_type is LayoutType.Caesar: for digit in pin: @@ -174,8 +171,7 @@ def _input_pin(debug: "DebugLink", pin: str, check: bool = False) -> None: def _see_pin(debug: "DebugLink") -> None: """Navigate to "SHOW" and press it""" if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia): - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.pin_passphrase_input()) + debug.click(debug.screen_buttons.pin_passphrase_input()) elif debug.layout_type is LayoutType.Caesar: navigate_to_action_and_press(debug, SHOW, TR_PIN_ACTIONS) @@ -187,8 +183,7 @@ def _delete_pin(debug: "DebugLink", digits_to_delete: int, check: bool = True) - for _ in range(digits_to_delete): if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia): - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.pin_passphrase_erase()) + debug.click(debug.screen_buttons.pin_passphrase_erase()) elif debug.layout_type is LayoutType.Caesar: navigate_to_action_and_press(debug, DELETE, TR_PIN_ACTIONS) @@ -200,9 +195,8 @@ def _delete_pin(debug: "DebugLink", digits_to_delete: int, check: bool = True) - def _delete_all(debug: "DebugLink", check: bool = True) -> None: """Navigate to "DELETE" and hold it until all digits are deleted""" if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia): - btns = buttons.ScreenButtons(debug.layout_type) debug.click( - btns.pin_passphrase_erase(), + debug.screen_buttons.pin_passphrase_erase(), hold_ms=1500, ) elif debug.layout_type is LayoutType.Caesar: @@ -228,8 +222,7 @@ def _cancel_pin(debug: "DebugLink") -> None: def _confirm_pin(debug: "DebugLink") -> None: """Navigate to "ENTER" and press it""" if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia): - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.pin_confirm()) + debug.click(debug.screen_buttons.pin_confirm()) elif debug.layout_type is LayoutType.Caesar: navigate_to_action_and_press(debug, ENTER, TR_PIN_ACTIONS) diff --git a/tests/click_tests/test_tutorial_delizia.py b/tests/click_tests/test_tutorial_delizia.py index a463ed5de2..0f7912fc76 100644 --- a/tests/click_tests/test_tutorial_delizia.py +++ b/tests/click_tests/test_tutorial_delizia.py @@ -20,7 +20,6 @@ import pytest from trezorlib import device -from .. import buttons from .. import translations as TR if TYPE_CHECKING: @@ -36,11 +35,10 @@ pytestmark = [ def test_tutorial_ignore_menu(device_handler: "BackgroundDeviceHandler"): debug = device_handler.debuglink() - btns = buttons.ScreenButtons(debug.layout_type) device_handler.run(device.show_device_tutorial) assert debug.read_layout().title() == TR.tutorial__welcome_safe5 - debug.click(btns.tap_to_confirm()) + debug.click(debug.screen_buttons.tap_to_confirm()) assert debug.read_layout().title() == TR.tutorial__title_lets_begin debug.swipe_up() assert debug.read_layout().title() == TR.tutorial__title_easy_navigation @@ -48,7 +46,7 @@ def test_tutorial_ignore_menu(device_handler: "BackgroundDeviceHandler"): assert debug.read_layout().title() == TR.tutorial__title_handy_menu debug.swipe_up() assert debug.read_layout().title() == TR.tutorial__title_hold - debug.click(btns.tap_to_confirm()) + debug.click(debug.screen_buttons.tap_to_confirm()) assert debug.read_layout().title() == TR.tutorial__title_well_done debug.swipe_up() @@ -57,25 +55,24 @@ def test_tutorial_ignore_menu(device_handler: "BackgroundDeviceHandler"): def test_tutorial_menu_open_close(device_handler: "BackgroundDeviceHandler"): debug = device_handler.debuglink() - btns = buttons.ScreenButtons(debug.layout_type) device_handler.run(device.show_device_tutorial) assert debug.read_layout().title() == TR.tutorial__welcome_safe5 - debug.click(btns.tap_to_confirm()) + debug.click(debug.screen_buttons.tap_to_confirm()) assert debug.read_layout().title() == TR.tutorial__title_lets_begin debug.swipe_up() assert debug.read_layout().title() == TR.tutorial__title_easy_navigation debug.swipe_up() assert debug.read_layout().title() == TR.tutorial__title_handy_menu - debug.click(btns.menu()) + debug.click(debug.screen_buttons.menu()) assert TR.tutorial__did_you_know in debug.read_layout().text_content() - debug.click(btns.menu()) + debug.click(debug.screen_buttons.menu()) assert debug.read_layout().title() == TR.tutorial__title_handy_menu debug.swipe_up() assert debug.read_layout().title() == TR.tutorial__title_hold - debug.click(btns.tap_to_confirm()) + debug.click(debug.screen_buttons.tap_to_confirm()) assert debug.read_layout().title() == TR.tutorial__title_well_done debug.swipe_up() @@ -84,22 +81,21 @@ def test_tutorial_menu_open_close(device_handler: "BackgroundDeviceHandler"): def test_tutorial_menu_exit(device_handler: "BackgroundDeviceHandler"): debug = device_handler.debuglink() - btns = buttons.ScreenButtons(debug.layout_type) device_handler.run(device.show_device_tutorial) assert debug.read_layout().title() == TR.tutorial__welcome_safe5 - debug.click(btns.tap_to_confirm()) + debug.click(debug.screen_buttons.tap_to_confirm()) assert debug.read_layout().title() == TR.tutorial__title_lets_begin debug.swipe_up() assert debug.read_layout().title() == TR.tutorial__title_easy_navigation debug.swipe_up() assert debug.read_layout().title() == TR.tutorial__title_handy_menu - debug.click(btns.menu()) + debug.click(debug.screen_buttons.menu()) assert TR.tutorial__did_you_know in debug.read_layout().text_content() - debug.click(btns.vertical_menu_items()[2]) + debug.click(debug.screen_buttons.vertical_menu_items()[2]) assert TR.instructions__hold_to_exit_tutorial in debug.read_layout().footer() - debug.click(btns.tap_to_confirm()) + debug.click(debug.screen_buttons.tap_to_confirm()) assert debug.read_layout().title() == TR.tutorial__title_well_done debug.swipe_up() @@ -108,20 +104,19 @@ def test_tutorial_menu_exit(device_handler: "BackgroundDeviceHandler"): def test_tutorial_menu_repeat(device_handler: "BackgroundDeviceHandler"): debug = device_handler.debuglink() - btns = buttons.ScreenButtons(debug.layout_type) device_handler.run(device.show_device_tutorial) assert debug.read_layout().title() == TR.tutorial__welcome_safe5 - debug.click(btns.tap_to_confirm()) + debug.click(debug.screen_buttons.tap_to_confirm()) assert debug.read_layout().title() == TR.tutorial__title_lets_begin debug.swipe_up() assert debug.read_layout().title() == TR.tutorial__title_easy_navigation debug.swipe_up() assert debug.read_layout().title() == TR.tutorial__title_handy_menu - debug.click(btns.menu()) + debug.click(debug.screen_buttons.menu()) assert TR.tutorial__did_you_know in debug.read_layout().text_content() - debug.click(btns.vertical_menu_items()[1]) + debug.click(debug.screen_buttons.vertical_menu_items()[1]) assert debug.read_layout().title() == TR.tutorial__title_lets_begin debug.swipe_up() @@ -130,7 +125,7 @@ def test_tutorial_menu_repeat(device_handler: "BackgroundDeviceHandler"): assert debug.read_layout().title() == TR.tutorial__title_handy_menu debug.swipe_up() assert debug.read_layout().title() == TR.tutorial__title_hold - debug.click(btns.tap_to_confirm()) + debug.click(debug.screen_buttons.tap_to_confirm()) assert debug.read_layout().title() == TR.tutorial__title_well_done debug.swipe_up() @@ -139,32 +134,31 @@ def test_tutorial_menu_repeat(device_handler: "BackgroundDeviceHandler"): def test_tutorial_menu_funfact(device_handler: "BackgroundDeviceHandler"): debug = device_handler.debuglink() - btns = buttons.ScreenButtons(debug.layout_type) device_handler.run(device.show_device_tutorial) assert debug.read_layout().title() == TR.tutorial__welcome_safe5 - debug.click(btns.tap_to_confirm()) + debug.click(debug.screen_buttons.tap_to_confirm()) assert debug.read_layout().title() == TR.tutorial__title_lets_begin debug.swipe_up() assert debug.read_layout().title() == TR.tutorial__title_easy_navigation debug.swipe_up() assert debug.read_layout().title() == TR.tutorial__title_handy_menu - debug.click(btns.menu()) + debug.click(debug.screen_buttons.menu()) assert TR.tutorial__did_you_know in debug.read_layout().text_content() - debug.click(btns.vertical_menu_items()[0]) + debug.click(debug.screen_buttons.vertical_menu_items()[0]) assert debug.read_layout().text_content() in TR.tutorial__first_wallet.replace( "\n", " " ) - debug.click(btns.menu()) + debug.click(debug.screen_buttons.menu()) assert TR.tutorial__did_you_know in debug.read_layout().text_content() - debug.click(btns.menu()) + debug.click(debug.screen_buttons.menu()) assert debug.read_layout().title() == TR.tutorial__title_handy_menu debug.swipe_up() assert debug.read_layout().title() == TR.tutorial__title_hold - debug.click(btns.tap_to_confirm()) + debug.click(debug.screen_buttons.tap_to_confirm()) assert debug.read_layout().title() == TR.tutorial__title_well_done debug.swipe_up() diff --git a/tests/common.py b/tests/common.py index c82b25f444..61c51fb5d9 100644 --- a/tests/common.py +++ b/tests/common.py @@ -28,8 +28,6 @@ import pytest from trezorlib import btc, messages, models, tools from trezorlib.debuglink import LayoutType -from . import buttons - if TYPE_CHECKING: from _pytest.mark.structures import MarkDecorator @@ -323,13 +321,12 @@ def click_info_button_bolt(debug: "DebugLink") -> Generator[Any, Any, ButtonRequ def click_info_button_delizia(debug: "DebugLink"): """Click Shamir backup info button and return back.""" - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.menu()) + debug.click(debug.screen_buttons.menu()) layout = debug.read_layout() assert "VerticalMenu" in layout.all_components() - debug.click(btns.vertical_menu_items()[0]) - debug.click(btns.menu()) - debug.click(btns.menu()) + debug.click(debug.screen_buttons.vertical_menu_items()[0]) + debug.click(debug.screen_buttons.menu()) + debug.click(debug.screen_buttons.menu()) def check_pin_backoff_time(attempts: int, start: float) -> None: diff --git a/tests/device_tests/cardano/test_sign_tx.py b/tests/device_tests/cardano/test_sign_tx.py index 8131928477..5ea21449f8 100644 --- a/tests/device_tests/cardano/test_sign_tx.py +++ b/tests/device_tests/cardano/test_sign_tx.py @@ -21,7 +21,7 @@ from trezorlib.debuglink import LayoutType from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.exceptions import TrezorFailure -from ...common import buttons, parametrize_using_common_fixtures +from ...common import parametrize_using_common_fixtures from ...input_flows import InputFlowConfirmAllWarnings pytestmark = [ @@ -41,10 +41,9 @@ def show_details_input_flow(client: Client): # Caesar - right button for "Show all" client.debug.press_yes() elif client.layout_type is LayoutType.Delizia: - btns = buttons.ScreenButtons(client.layout_type) # Delizia - "Show all" button from context menu - client.debug.click(btns.menu()) - client.debug.click(btns.vertical_menu_items()[0]) + client.debug.click(client.debug.screen_buttons.menu()) + client.debug.click(client.debug.screen_buttons.vertical_menu_items()[0]) else: raise NotImplementedError # reset ui flow to continue "automatically" diff --git a/tests/device_tests/test_msg_changepin_t2.py b/tests/device_tests/test_msg_changepin_t2.py index 3f0e7d56d6..cda8df2f8a 100644 --- a/tests/device_tests/test_msg_changepin_t2.py +++ b/tests/device_tests/test_msg_changepin_t2.py @@ -22,7 +22,6 @@ from trezorlib.debuglink import LayoutType from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.exceptions import Cancelled, TrezorFailure -from .. import buttons from ..input_flows import ( InputFlowCodeChangeFail, InputFlowNewCodeMismatch, @@ -187,18 +186,17 @@ def test_change_invalid_current(client: Client): def test_pin_menu_cancel_setup(client: Client): def cancel_pin_setup_input_flow(): yield - btns = buttons.ScreenButtons(client.layout_type) # enter context menu - client.debug.click(btns.menu()) + client.debug.click(client.debug.screen_buttons.menu()) client.debug.synchronize_at("VerticalMenu") # click "Cancel PIN setup" - client.debug.click(btns.vertical_menu_items()[0]) + client.debug.click(client.debug.screen_buttons.vertical_menu_items()[0]) client.debug.synchronize_at("Paragraphs") # swipe through info screen client.debug.swipe_up() client.debug.synchronize_at("PromptScreen") # tap to confirm - client.debug.click(btns.tap_to_confirm()) + client.debug.click(client.debug.screen_buttons.tap_to_confirm()) with client, pytest.raises(Cancelled): client.set_input_flow(cancel_pin_setup_input_flow) diff --git a/tests/input_flows.py b/tests/input_flows.py index 8102dd84e5..86d538673d 100644 --- a/tests/input_flows.py +++ b/tests/input_flows.py @@ -19,7 +19,6 @@ from trezorlib.debuglink import DebugLink, LayoutContent, LayoutType from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.debuglink import multipage_content -from . import buttons from . import translations as TR from .common import ( BRGeneratorType, @@ -316,13 +315,12 @@ class InputFlowSignVerifyMessageLong(InputFlowBase): layouts: list[LayoutContent] = [] br = yield # confirm address - btns = buttons.ScreenButtons(self.client.layout_type) self.debug.read_layout() self.debug.press_yes() - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) self.debug.synchronize_at("VerticalMenu") - self.debug.click(btns.vertical_menu_items()[0]) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[0]) br = yield self.debug.read_layout() @@ -352,9 +350,8 @@ class InputFlowSignMessageInfo(InputFlowBase): def input_flow_bolt(self) -> BRGeneratorType: yield # signing address/message info - btns = buttons.ScreenButtons(self.client.layout_type) - self.debug.click(btns.menu()) - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) # signing address "x" self.debug.press_no() self.debug.synchronize_at("IconDialog") @@ -365,11 +362,10 @@ class InputFlowSignMessageInfo(InputFlowBase): def input_flow_delizia(self) -> BRGeneratorType: yield # show address/message info - btns = buttons.ScreenButtons(self.client.layout_type) - self.debug.click(btns.menu()) - self.debug.click(btns.vertical_menu_items()[0]) - self.debug.click(btns.menu()) - self.debug.click(btns.vertical_menu_items()[1]) + self.debug.click(self.client.debug.screen_buttons.menu()) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[0]) + self.debug.click(self.client.debug.screen_buttons.menu()) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[1]) # address mismatch? yes! self.debug.swipe_up() yield @@ -381,15 +377,14 @@ class InputFlowShowAddressQRCode(InputFlowBase): def input_flow_bolt(self) -> BRGeneratorType: yield - btns = buttons.ScreenButtons(self.client.layout_type) - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) # synchronize; TODO get rid of this once we have single-global-layout self.debug.synchronize_at("SimplePage") self.debug.swipe_left() self.debug.swipe_right() self.debug.swipe_left() - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) self.debug.press_no() self.debug.press_no() self.debug.press_yes() @@ -417,27 +412,26 @@ class InputFlowShowAddressQRCode(InputFlowBase): def input_flow_delizia(self) -> BRGeneratorType: yield - btns = buttons.ScreenButtons(self.client.layout_type) - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) # synchronize; TODO get rid of this once we have single-global-layout self.debug.synchronize_at("VerticalMenu") # menu - self.debug.click(btns.vertical_menu_items()[0]) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[0]) self.debug.synchronize_at("Qr") # qr code - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) # menu - self.debug.click(btns.vertical_menu_items()[1]) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[1]) # address details - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) # menu - self.debug.click(btns.vertical_menu_items()[2]) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[2]) # cancel self.debug.swipe_up() # really cancel - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) # menu - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) layout = self.debug.read_layout() while "PromptScreen" not in layout.all_components(): @@ -445,7 +439,7 @@ class InputFlowShowAddressQRCode(InputFlowBase): layout = self.debug.read_layout() self.debug.synchronize_at("PromptScreen") # tap to confirm - self.debug.click(btns.tap_to_confirm()) + self.debug.click(self.client.debug.screen_buttons.tap_to_confirm()) class InputFlowShowAddressQRCodeCancel(InputFlowBase): @@ -454,13 +448,12 @@ class InputFlowShowAddressQRCodeCancel(InputFlowBase): def input_flow_bolt(self) -> BRGeneratorType: yield - btns = buttons.ScreenButtons(self.client.layout_type) - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) # synchronize; TODO get rid of this once we have single-global-layout self.debug.synchronize_at("SimplePage") self.debug.swipe_left() - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) self.debug.press_no() self.debug.press_yes() @@ -481,26 +474,25 @@ class InputFlowShowAddressQRCodeCancel(InputFlowBase): def input_flow_delizia(self) -> BRGeneratorType: yield - btns = buttons.ScreenButtons(self.client.layout_type) - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) # synchronize; TODO get rid of this once we have single-global-layout self.debug.synchronize_at("VerticalMenu") # menu - self.debug.click(btns.vertical_menu_items()[0]) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[0]) self.debug.synchronize_at("Qr") # qr code - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) # menu - self.debug.click(btns.vertical_menu_items()[1]) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[1]) # address details - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) # menu - self.debug.click(btns.vertical_menu_items()[2]) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[2]) # cancel self.debug.swipe_up() self.debug.synchronize_at("PromptScreen") # really cancel - self.debug.click(btns.tap_to_confirm()) + self.debug.click(self.client.debug.screen_buttons.tap_to_confirm()) class InputFlowShowMultisigXPUBs(InputFlowBase): @@ -520,7 +512,6 @@ class InputFlowShowMultisigXPUBs(InputFlowBase): def input_flow_bolt(self) -> BRGeneratorType: yield # multisig address warning - btns = buttons.ScreenButtons(self.client.layout_type) self.debug.press_yes() yield # show address @@ -529,7 +520,7 @@ class InputFlowShowMultisigXPUBs(InputFlowBase): assert "(MULTISIG)" in layout.title() assert layout.text_content().replace(" ", "") == self.address - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) assert "Qr" in self.all_components() self.debug.swipe_left() @@ -546,7 +537,7 @@ class InputFlowShowMultisigXPUBs(InputFlowBase): content = layout.text_content().replace(" ", "") assert self.xpubs[xpub_num] in content - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) # show address self.debug.press_no() # address mismatch @@ -598,27 +589,26 @@ class InputFlowShowMultisigXPUBs(InputFlowBase): def input_flow_delizia(self) -> BRGeneratorType: yield # multisig address warning - btns = buttons.ScreenButtons(self.client.layout_type) - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) self.debug.synchronize_at("VerticalMenu") - self.debug.click(btns.vertical_menu_items()[1]) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[1]) yield # show address layout = self.debug.read_layout() assert TR.address__title_receive_address in layout.title() assert layout.text_content().replace(" ", "") == self.address - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) assert "VerticalMenu" in self.all_components() # menu - self.debug.click(btns.vertical_menu_items()[0]) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[0]) self.debug.synchronize_at("Qr") # qr code assert "Qr" in self.all_components() - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) # menu assert "VerticalMenu" in self.all_components() - self.debug.click(btns.vertical_menu_items()[1]) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[1]) layout = self.debug.synchronize_at("AddressDetails") # address details assert "Multisig 2 of 3" in layout.screen_content() @@ -629,17 +619,17 @@ class InputFlowShowMultisigXPUBs(InputFlowBase): self.debug.swipe_left() self.debug.swipe_left() - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) self.debug.synchronize_at("VerticalMenu") # menu - self.debug.click(btns.vertical_menu_items()[2]) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[2]) # cancel self.debug.swipe_up() # really cancel - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) self.debug.synchronize_at("VerticalMenu") # menu - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) layout = self.debug.synchronize_at("Paragraphs") # address while "PromptScreen" not in layout.all_components(): @@ -656,7 +646,6 @@ class InputFlowShowXpubQRCode(InputFlowBase): self.passphrase = passphrase def input_flow_bolt(self) -> BRGeneratorType: - btns = buttons.ScreenButtons(self.client.layout_type) if self.passphrase: yield self.debug.press_yes() @@ -669,14 +658,14 @@ class InputFlowShowXpubQRCode(InputFlowBase): self.debug.press_yes() br = yield - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) # synchronize; TODO get rid of this once we have single-global-layout self.debug.synchronize_at("SimplePage") self.debug.swipe_left() self.debug.swipe_right() self.debug.swipe_left() - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) self.debug.press_no() self.debug.press_no() for _ in range(br.pages - 1): @@ -711,7 +700,6 @@ class InputFlowShowXpubQRCode(InputFlowBase): self.debug.press_middle() def input_flow_delizia(self) -> BRGeneratorType: - btns = buttons.ScreenButtons(self.client.layout_type) if self.passphrase: yield self.debug.press_yes() @@ -727,32 +715,32 @@ class InputFlowShowXpubQRCode(InputFlowBase): assert layout.title() in (TR.address__public_key, "XPUB") - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) assert "VerticalMenu" in self.all_components() # menu - self.debug.click(btns.vertical_menu_items()[0]) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[0]) self.debug.synchronize_at("Qr") # qr code assert "Qr" in self.all_components() - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) # menu assert "VerticalMenu" in self.all_components() - self.debug.click(btns.vertical_menu_items()[1]) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[1]) layout = self.debug.synchronize_at("AddressDetails") # address details assert TR.address_details__derivation_path in layout.screen_content() - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) layout = self.debug.synchronize_at("VerticalMenu") # menu - self.debug.click(btns.vertical_menu_items()[2]) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[2]) # cancel self.debug.swipe_up() # really cancel - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) layout = self.debug.synchronize_at("VerticalMenu") # menu - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) layout = self.debug.synchronize_at("Paragraphs") # address while "PromptScreen" not in layout.all_components(): @@ -865,7 +853,6 @@ class InputFlowSignTxHighFee(InputFlowBase): def sign_tx_go_to_info(client: Client) -> Generator[None, messages.ButtonRequest, str]: - btns = buttons.ScreenButtons(client.layout_type) yield # confirm output client.debug.read_layout() client.debug.press_yes() @@ -880,7 +867,7 @@ def sign_tx_go_to_info(client: Client) -> Generator[None, messages.ButtonRequest layout = client.debug.read_layout() content = layout.text_content() - client.debug.click(btns.menu()) + client.debug.click(client.debug.screen_buttons.menu()) return content @@ -888,7 +875,6 @@ def sign_tx_go_to_info(client: Client) -> Generator[None, messages.ButtonRequest def sign_tx_go_to_info_t3t1( client: Client, multi_account: bool = False ) -> Generator[None, messages.ButtonRequest, str]: - btns = buttons.ScreenButtons(client.layout_type) yield # confirm output client.debug.read_layout() client.debug.swipe_up() @@ -903,22 +889,22 @@ def sign_tx_go_to_info_t3t1( yield # confirm transaction client.debug.read_layout() - client.debug.click(btns.menu()) + client.debug.click(client.debug.screen_buttons.menu()) client.debug.synchronize_at("VerticalMenu") - client.debug.click(btns.vertical_menu_items()[0]) + client.debug.click(client.debug.screen_buttons.vertical_menu_items()[0]) layout = client.debug.read_layout() content = layout.text_content() - client.debug.click(btns.menu()) + client.debug.click(client.debug.screen_buttons.menu()) client.debug.synchronize_at("VerticalMenu") - client.debug.click(btns.vertical_menu_items()[1]) + client.debug.click(client.debug.screen_buttons.vertical_menu_items()[1]) layout = client.debug.read_layout() content += " " + layout.text_content() - client.debug.click(btns.menu()) - client.debug.click(btns.menu()) + client.debug.click(client.debug.screen_buttons.menu()) + client.debug.click(client.debug.screen_buttons.menu()) return content @@ -1031,12 +1017,11 @@ class InputFlowSignTxInformationCancel(InputFlowBase): self.debug.press_left() def input_flow_delizia(self) -> BRGeneratorType: - btns = buttons.ScreenButtons(self.client.layout_type) yield from sign_tx_go_to_info_t3t1(self.client) - self.debug.click(btns.menu()) - self.debug.click(btns.vertical_menu_items()[2]) + self.debug.click(self.client.debug.screen_buttons.menu()) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[2]) self.debug.synchronize_at("PromptScreen") - self.debug.click(btns.tap_to_confirm()) + self.debug.click(self.client.debug.screen_buttons.tap_to_confirm()) class InputFlowSignTxInformationReplacement(InputFlowBase): @@ -1044,7 +1029,6 @@ class InputFlowSignTxInformationReplacement(InputFlowBase): super().__init__(client) def input_flow_bolt(self) -> BRGeneratorType: - btns = buttons.ScreenButtons(self.client.layout_type) yield # confirm txid self.debug.press_yes() yield # confirm address @@ -1058,8 +1042,8 @@ class InputFlowSignTxInformationReplacement(InputFlowBase): self.debug.press_yes() yield # transaction summary, press info - self.debug.click(btns.menu()) - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) self.debug.press_yes() def input_flow_caesar(self) -> BRGeneratorType: @@ -2341,18 +2325,17 @@ class InputFlowResetSkipBackup(InputFlowBase): self.debug.press_no() def input_flow_delizia(self) -> BRGeneratorType: - btns = buttons.ScreenButtons(self.client.layout_type) yield from self.BAK.confirm_new_wallet() yield # Skip Backup assert TR.backup__new_wallet_created in self.text_content() self.debug.swipe_up() yield - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) self.debug.synchronize_at("VerticalMenu") - self.debug.click(btns.vertical_menu_items()[0]) + self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[0]) self.debug.swipe_up() self.debug.synchronize_at("PromptScreen") - self.debug.click(btns.tap_to_confirm()) + self.debug.click(self.client.debug.screen_buttons.tap_to_confirm()) class InputFlowConfirmAllWarnings(InputFlowBase): @@ -2371,7 +2354,6 @@ class InputFlowConfirmAllWarnings(InputFlowBase): return self.input_flow_bolt() def input_flow_delizia(self) -> BRGeneratorType: - btns = buttons.ScreenButtons(self.client.layout_type) br = yield while True: # wait for homescreen to go away @@ -2389,9 +2371,11 @@ class InputFlowConfirmAllWarnings(InputFlowBase): TR.send__cancel_sign, ) if any(needle.lower() in text for needle in hi_prio): - self.debug.click(btns.menu()) + self.debug.click(self.client.debug.screen_buttons.menu()) self.debug.synchronize_at("VerticalMenu") - self.debug.click(btns.vertical_menu_items()[1]) + self.debug.click( + self.client.debug.screen_buttons.vertical_menu_items()[1] + ) elif "PromptScreen" in layout.all_components(): self.debug.press_yes() elif "SwipeContent" in layout.all_components(): @@ -2415,8 +2399,7 @@ class InputFlowFidoConfirm(InputFlowBase): yield from self.input_flow_bolt() def input_flow_delizia(self) -> BRGeneratorType: - btns = buttons.ScreenButtons(self.client.layout_type) while True: yield self.debug.swipe_up() - self.debug.click(btns.tap_to_confirm()) + self.debug.click(self.client.debug.screen_buttons.tap_to_confirm()) diff --git a/tests/input_flows_helpers.py b/tests/input_flows_helpers.py index dd0d5ae368..0e08631d5b 100644 --- a/tests/input_flows_helpers.py +++ b/tests/input_flows_helpers.py @@ -4,7 +4,6 @@ from trezorlib import messages from trezorlib.debuglink import LayoutType from trezorlib.debuglink import TrezorClientDebugLink as Client -from . import buttons from . import translations as TR from .click_tests.common import go_next from .common import BRGeneratorType, get_text_possible_pagination @@ -143,14 +142,13 @@ class RecoveryFlow: else: self.debug.press_no() elif self.client.layout_type is LayoutType.Delizia: - btns = buttons.ScreenButtons(self.client.layout_type) assert TR.recovery__enter_each_word in self._text_content() - self.debug.click(btns.menu()) + self.debug.click(self.debug.screen_buttons.menu()) self.debug.synchronize_at("VerticalMenu") if confirm: - self.debug.click(btns.vertical_menu_items()[0]) + self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0]) else: - self.debug.click(btns.menu()) + self.debug.click(self.debug.screen_buttons.menu()) else: assert TR.recovery__enter_any_share in self._text_content() self.debug.press_no() @@ -176,15 +174,14 @@ class RecoveryFlow: assert TR.regexp("recovery__x_of_y_entered_template").search( self._text_content() ) - btns = buttons.ScreenButtons(self.client.layout_type) - self.debug.click(btns.menu()) + self.debug.click(self.debug.screen_buttons.menu()) self.debug.synchronize_at("VerticalMenu") - self.debug.click(btns.vertical_menu_items()[0]) + self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0]) assert (yield).name == "abort_recovery" self.debug.swipe_up() layout = self.debug.read_layout() assert layout.title() == TR.recovery__title_cancel_recovery - self.debug.click(btns.tap_to_confirm()) + self.debug.click(self.debug.screen_buttons.tap_to_confirm()) else: assert TR.regexp("recovery__x_of_y_entered_template").search( self._text_content() @@ -339,17 +336,16 @@ class RecoveryFlow: self.debug.press_yes() def click_info_delizia(self) -> BRGeneratorType: - btns = buttons.ScreenButtons(self.client.layout_type) # Moving through the menu into the show_shares screen - self.debug.click(btns.menu()) + self.debug.click(self.debug.screen_buttons.menu()) self.debug.synchronize_at("VerticalMenu") - self.debug.click(btns.vertical_menu_items()[0]) + self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0]) br = yield assert br.name == "show_shares" assert br.code == B.Other # Getting back to the homepage - self.debug.click(btns.menu()) - self.debug.click(btns.menu()) + self.debug.click(self.debug.screen_buttons.menu()) + self.debug.click(self.debug.screen_buttons.menu()) class EthereumFlow: @@ -464,7 +460,6 @@ class EthereumFlow: def _confirm_tx_delizia( self, cancel: bool, info: bool, go_back_from_summary: bool ) -> BRGeneratorType: - btns = buttons.ScreenButtons(self.client.layout_type) assert (yield).name == "confirm_output" title = self.debug.read_layout().title() assert TR.words__address in title @@ -485,17 +480,17 @@ class EthereumFlow: self.debug.press_yes() assert (yield).name == "confirm_ethereum_tx" if info: - self.debug.click(btns.menu()) + self.debug.click(self.debug.screen_buttons.menu()) self.debug.synchronize_at("VerticalMenu") - self.debug.click(btns.vertical_menu_items()[0]) + self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0]) text = self.debug.read_layout().text_content() assert TR.ethereum__gas_limit in text assert TR.ethereum__gas_price in text - self.debug.click(btns.menu()) - self.debug.click(btns.menu()) + self.debug.click(self.debug.screen_buttons.menu()) + self.debug.click(self.debug.screen_buttons.menu()) self.debug.swipe_up() self.debug.read_layout() - self.debug.click(btns.tap_to_confirm()) + self.debug.click(self.debug.screen_buttons.tap_to_confirm()) assert (yield).name == "confirm_ethereum_tx" def confirm_tx( @@ -531,11 +526,10 @@ class EthereumFlow: TR.ethereum__staking_claim_intro, ) if self.client.layout_type is LayoutType.Bolt: - btns = buttons.ScreenButtons(self.client.layout_type) # confirm intro if info: self.debug.click( - btns.menu(), + self.debug.screen_buttons.menu(), ) assert self.debug.read_layout().title() in ( TR.ethereum__staking_stake_address, @@ -557,18 +551,17 @@ class EthereumFlow: self.debug.press_yes() elif self.client.layout_type is LayoutType.Delizia: - btns = buttons.ScreenButtons(self.client.layout_type) # confirm intro if info: - self.debug.click(btns.menu()) + self.debug.click(self.debug.screen_buttons.menu()) self.debug.synchronize_at("VerticalMenu") - self.debug.click(btns.vertical_menu_items()[0]) + self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0]) assert self.debug.read_layout().title() in ( TR.ethereum__staking_stake_address, TR.ethereum__staking_claim_address, ) - self.debug.click(btns.menu()) - self.debug.click(btns.menu()) + self.debug.click(self.debug.screen_buttons.menu()) + self.debug.click(self.debug.screen_buttons.menu()) self.debug.swipe_up() br = yield @@ -577,13 +570,13 @@ class EthereumFlow: # confirm summary if info: - self.debug.click(btns.menu()) + self.debug.click(self.debug.screen_buttons.menu()) self.debug.synchronize_at("VerticalMenu") - self.debug.click(btns.vertical_menu_items()[0]) + self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0]) assert TR.ethereum__gas_limit in self.debug.read_layout().text_content() assert TR.ethereum__gas_price in self.debug.read_layout().text_content() - self.debug.click(btns.menu()) - self.debug.click(btns.menu()) + self.debug.click(self.debug.screen_buttons.menu()) + self.debug.click(self.debug.screen_buttons.menu()) self.debug.swipe_up() # br = yield # FIXME: no BR on sign transaction diff --git a/tests/upgrade_tests/recovery_old.py b/tests/upgrade_tests/recovery_old.py index 338525f201..5f15713af7 100644 --- a/tests/upgrade_tests/recovery_old.py +++ b/tests/upgrade_tests/recovery_old.py @@ -1,7 +1,5 @@ from typing import TYPE_CHECKING -from .. import buttons - if TYPE_CHECKING: from trezorlib.debuglink import DebugLink, LayoutContent @@ -10,45 +8,41 @@ def _enter_word( debug: "DebugLink", word: str, is_slip39: bool = False ) -> "LayoutContent": typed_word = word[:4] - actions = buttons.ButtonActions(debug.layout_type) - btns = buttons.ScreenButtons(debug.layout_type) - for coords in actions.type_word(typed_word, is_slip39=is_slip39): + for coords in debug.button_actions.type_word(typed_word, is_slip39=is_slip39): debug.click(coords) debug.read_layout(wait=False) - debug.click(btns.mnemonic_confirm()) + debug.click(debug.screen_buttons.mnemonic_confirm()) return debug.read_layout(wait=True) def confirm_recovery(debug: "DebugLink") -> None: - btns = buttons.ScreenButtons(debug.layout_type) - debug.click(btns.ok()) + debug.click(debug.screen_buttons.ok()) debug.read_layout(wait=True) def select_number_of_words( debug: "DebugLink", tag_version: tuple | None, num_of_words: int = 20 ) -> None: - btns = buttons.ScreenButtons(debug.layout_type) if "SelectWordCount" not in debug.read_layout().all_components(): - debug.click(btns.ok()) + debug.click(debug.screen_buttons.ok()) debug.read_layout(wait=True) if tag_version is None or tag_version > (2, 8, 8): # layout changed after adding the cancel button - coords = btns.word_count_all_word(num_of_words) + coords = debug.screen_buttons.word_count_all_word(num_of_words) else: word_option_offset = 6 word_options = (12, 18, 20, 24, 33) index = word_option_offset + word_options.index( num_of_words ) # raises if num of words is invalid - coords = btns.grid34(index % 3, index // 3) + coords = debug.screen_buttons.grid34(index % 3, index // 3) debug.click(coords) debug.read_layout(wait=True) def enter_share(debug: "DebugLink", share: str) -> "LayoutContent": - debug.click(buttons.ScreenButtons(debug.layout_type).ok()) + debug.click(debug.screen_buttons.ok()) for word in share.split(" "): _enter_word(debug, word, is_slip39=True)