1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-15 20:19:23 +00:00

tests: fix small irregularities

This commit is contained in:
matejcik 2023-11-21 16:55:46 +01:00 committed by matejcik
parent cd25071a29
commit adc9b523be
19 changed files with 186 additions and 144 deletions

View File

@ -1151,6 +1151,7 @@ async def confirm_reenter_pin(is_wipe_code: bool = False) -> None:
def pin_mismatch_popup(is_wipe_code: bool = False) -> Awaitable[ui.UiResult]: def pin_mismatch_popup(is_wipe_code: bool = False) -> Awaitable[ui.UiResult]:
title = TR.wipe_code__mismatch if is_wipe_code else TR.pin__mismatch title = TR.wipe_code__mismatch if is_wipe_code else TR.pin__mismatch
description = TR.wipe_code__enter_new if is_wipe_code else TR.pin__reenter_new description = TR.wipe_code__enter_new if is_wipe_code else TR.pin__reenter_new
br_name = "wipe_code_mismatch" if is_wipe_code else "pin_mismatch"
return interact( return interact(
error_popup( error_popup(
@ -1158,7 +1159,7 @@ def pin_mismatch_popup(is_wipe_code: bool = False) -> Awaitable[ui.UiResult]:
description, description,
button=TR.buttons__try_again, button=TR.buttons__try_again,
), ),
"pin_mismatch", br_name,
BR_CODE_OTHER, BR_CODE_OTHER,
) )

View File

@ -1263,9 +1263,9 @@ def _confirm_multiple_pages_texts(
def pin_mismatch_popup(is_wipe_code: bool = False) -> Awaitable[None]: def pin_mismatch_popup(is_wipe_code: bool = False) -> Awaitable[None]:
description = TR.wipe_code__mismatch if is_wipe_code else TR.pin__mismatch description = TR.wipe_code__mismatch if is_wipe_code else TR.pin__mismatch
br_code = "wipe_code_mismatch" if is_wipe_code else "pin_mismatch" br_name = "wipe_code_mismatch" if is_wipe_code else "pin_mismatch"
layout = show_warning( layout = show_warning(
br_code, br_name,
description, description,
TR.pin__please_check_again, TR.pin__please_check_again,
TR.buttons__check_again, TR.buttons__check_again,

View File

@ -1213,6 +1213,7 @@ async def confirm_reenter_pin(is_wipe_code: bool = False) -> None:
def pin_mismatch_popup(is_wipe_code: bool = False) -> Awaitable[None]: def pin_mismatch_popup(is_wipe_code: bool = False) -> Awaitable[None]:
title = TR.wipe_code__wipe_code_mismatch if is_wipe_code else TR.pin__pin_mismatch title = TR.wipe_code__wipe_code_mismatch if is_wipe_code else TR.pin__pin_mismatch
br_name = "wipe_code_mismatch" if is_wipe_code else "pin_mismatch"
description = TR.wipe_code__mismatch if is_wipe_code else TR.pin__mismatch description = TR.wipe_code__mismatch if is_wipe_code else TR.pin__mismatch
return interact( return interact(
error_popup( error_popup(
@ -1220,7 +1221,7 @@ def pin_mismatch_popup(is_wipe_code: bool = False) -> Awaitable[None]:
description, description,
button=TR.buttons__try_again, button=TR.buttons__try_again,
), ),
"pin_mismatch", br_name,
BR_CODE_OTHER, BR_CODE_OTHER,
raise_on_cancel=None, raise_on_cancel=None,
) )

View File

@ -17,7 +17,7 @@ if TYPE_CHECKING:
async def request_word_count(recovery_type: RecoveryType) -> int: async def request_word_count(recovery_type: RecoveryType) -> int:
count = await interact( count = await interact(
trezorui2.select_word_count(recovery_type=recovery_type), trezorui2.select_word_count(recovery_type=recovery_type),
"word_count", "recovery_word_count",
ButtonRequestType.MnemonicWordCount, ButtonRequestType.MnemonicWordCount,
) )
return int(count) return int(count)

View File

@ -47,9 +47,9 @@ def get_char_category(char: str) -> PassphraseCategory:
def go_next(debug: "DebugLink") -> LayoutContent: def go_next(debug: "DebugLink") -> LayoutContent:
if debug.layout_type is LayoutType.TT: if debug.layout_type is LayoutType.TT:
return debug.click(buttons.OK) # type: ignore return debug.click(buttons.OK)
elif debug.layout_type is LayoutType.TR: elif debug.layout_type is LayoutType.TR:
return debug.press_right() # type: ignore return debug.press_right()
elif debug.layout_type is LayoutType.Mercury: elif debug.layout_type is LayoutType.Mercury:
return debug.swipe_up() return debug.swipe_up()
else: else:
@ -58,18 +58,18 @@ def go_next(debug: "DebugLink") -> LayoutContent:
def tap_to_confirm(debug: "DebugLink") -> LayoutContent: def tap_to_confirm(debug: "DebugLink") -> LayoutContent:
if debug.layout_type is LayoutType.TT: if debug.layout_type is LayoutType.TT:
return debug.read_layout() # type: ignore return debug.read_layout()
elif debug.layout_type is LayoutType.TR: elif debug.layout_type is LayoutType.TR:
return debug.read_layout() # type: ignore return debug.read_layout()
elif debug.layout_type is LayoutType.Mercury: elif debug.layout_type is LayoutType.Mercury:
return debug.click(buttons.TAP_TO_CONFIRM, ) return debug.click(buttons.TAP_TO_CONFIRM)
else: else:
raise RuntimeError("Unknown model") raise RuntimeError("Unknown model")
def go_back(debug: "DebugLink", r_middle: bool = False) -> LayoutContent: def go_back(debug: "DebugLink", r_middle: bool = False) -> LayoutContent:
if debug.layout_type in (LayoutType.TT, LayoutType.Mercury): if debug.layout_type in (LayoutType.TT, LayoutType.Mercury):
return debug.click(buttons.CANCEL) # type: ignore return debug.click(buttons.CANCEL)
elif debug.layout_type is LayoutType.TR: elif debug.layout_type is LayoutType.TR:
if r_middle: if r_middle:
return debug.press_middle() return debug.press_middle()

View File

@ -19,10 +19,15 @@ def confirm_new_wallet(debug: "DebugLink") -> None:
elif debug.layout_type is LayoutType.Mercury: elif debug.layout_type is LayoutType.Mercury:
debug.swipe_up() debug.swipe_up()
debug.click(buttons.TAP_TO_CONFIRM) debug.click(buttons.TAP_TO_CONFIRM)
debug.swipe_up() # Wallet created
elif debug.layout_type is LayoutType.TR: elif debug.layout_type is LayoutType.TR:
debug.press_right() debug.press_right()
debug.press_right() debug.press_right()
TR.assert_in_multiple(
debug.read_layout().text_content(),
["backup__new_wallet_successfully_created", "backup__new_wallet_created"],
)
if debug.layout_type is LayoutType.Mercury:
debug.swipe_up()
def confirm_read(debug: "DebugLink", middle_r: bool = False) -> None: def confirm_read(debug: "DebugLink", middle_r: bool = False) -> None:
@ -109,7 +114,7 @@ def read_words(debug: "DebugLink", do_htc: bool = True) -> list[str]:
if debug.layout_type is LayoutType.TT: if debug.layout_type is LayoutType.TT:
debug.click(buttons.OK, hold_ms=1500) debug.click(buttons.OK, hold_ms=1500)
elif debug.layout_type is LayoutType.Mercury: elif debug.layout_type is LayoutType.Mercury:
debug.click_hold(buttons.TAP_TO_CONFIRM, hold_ms=1500) debug.click(buttons.TAP_TO_CONFIRM, hold_ms=1500)
elif debug.layout_type is LayoutType.TR: elif debug.layout_type is LayoutType.TR:
debug.press_right(hold_ms=1200) debug.press_right(hold_ms=1200)
else: else:

View File

@ -22,6 +22,7 @@ from trezorlib import device, messages
from trezorlib.debuglink import LayoutType from trezorlib.debuglink import LayoutType
from ..common import EXTERNAL_ENTROPY, WITH_MOCK_URANDOM, generate_entropy from ..common import EXTERNAL_ENTROPY, WITH_MOCK_URANDOM, generate_entropy
from .. import translations as TR
from . import reset from . import reset
if TYPE_CHECKING: if TYPE_CHECKING:
@ -73,14 +74,16 @@ def test_backup_slip39_custom(
groups=[(share_threshold, share_count)], groups=[(share_threshold, share_count)],
) )
# confirm backup warning
reset.confirm_read(debug, middle_r=True)
# confirm backup configuration
if share_count > 1: if share_count > 1:
# confirm shamir warning TR.assert_template(debug.read_layout().text_content(), "reset__create_x_of_y_multi_share_backup_template")
reset.confirm_read(debug, middle_r=True)
else: else:
TR.assert_template(debug.read_layout().text_content(), "backup__info_single_share_backup")
reset.confirm_read(debug)
# confirm backup intro # confirm backup intro
TR.assert_in(debug.read_layout().text_content(), "reset__never_make_digital_copy")
reset.confirm_read(debug, middle_r=True) reset.confirm_read(debug, middle_r=True)
all_words: list[str] = [] all_words: list[str] = []

View File

@ -79,8 +79,7 @@ def test_hold_to_lock(device_handler: "BackgroundDeviceHandler"):
# unlock by touching # unlock by touching
if debug.layout_type is LayoutType.TR: if debug.layout_type is LayoutType.TR:
# Doing a short HTC to simulate a click layout = debug.press_right()
layout = debug.press_right(hold_ms=100)
else: else:
layout = debug.click(buttons.INFO) layout = debug.click(buttons.INFO)
assert "PinKeyboard" in layout.all_components() assert "PinKeyboard" in layout.all_components()

View File

@ -51,10 +51,8 @@ def test_repeated_backup(
# confirm new wallet # confirm new wallet
reset.confirm_new_wallet(debug) reset.confirm_new_wallet(debug)
# confirm back up # confirm back up
reset.confirm_read(debug) reset.confirm_read(debug)
# confirm backup intro # confirm backup intro
reset.confirm_read(debug) reset.confirm_read(debug)
@ -65,34 +63,24 @@ def test_repeated_backup(
# confirm checklist # confirm checklist
reset.confirm_read(debug) reset.confirm_read(debug)
# shares=1 # shares=1
reset.set_selection(debug, buttons.reset_minus(model_name), 5 - 1) reset.set_selection(debug, buttons.reset_minus(model_name), 5 - 1)
# confirm checklist # confirm checklist
reset.confirm_read(debug) reset.confirm_read(debug)
# threshold=1 # threshold=1
reset.set_selection(debug, buttons.reset_plus(model_name), 0) reset.set_selection(debug, buttons.reset_plus(model_name), 0)
# confirm checklist # confirm checklist
reset.confirm_read(debug) reset.confirm_read(debug)
# confirm backup warning # confirm backup warning
reset.confirm_read(debug, middle_r=True) reset.confirm_read(debug, middle_r=True)
# read words # read words
initial_backup_1_of_1 = reset.read_words(debug) initial_backup_1_of_1 = reset.read_words(debug)
# confirm words # confirm words
reset.confirm_words(debug, initial_backup_1_of_1) reset.confirm_words(debug, initial_backup_1_of_1)
# confirm share checked # confirm share checked
reset.confirm_read(debug) reset.confirm_read(debug)
# confirm backup done # confirm backup done
reset.confirm_read(debug) reset.confirm_read(debug)
# Your backup is done # Your backup is done
go_next(debug) go_next(debug)
@ -112,7 +100,6 @@ def test_repeated_backup(
) )
recovery.confirm_recovery(debug, "recovery__title_unlock_repeated_backup") recovery.confirm_recovery(debug, "recovery__title_unlock_repeated_backup")
recovery.select_number_of_words(debug, num_of_words=20, unlock_repeated_backup=True) recovery.select_number_of_words(debug, num_of_words=20, unlock_repeated_backup=True)
recovery.enter_seed( recovery.enter_seed(
debug, debug,
@ -123,8 +110,6 @@ def test_repeated_backup(
) )
# backup is enabled # backup is enabled
go_next(debug)
assert device_handler.result().message == "Backup unlocked" assert device_handler.result().message == "Backup unlocked"
# we are now in recovery mode # we are now in recovery mode
@ -136,29 +121,21 @@ def test_repeated_backup(
assert features.recovery_status == messages.RecoveryStatus.Backup assert features.recovery_status == messages.RecoveryStatus.Backup
# at this point, the backup is unlocked... # at this point, the backup is unlocked...
go_next(debug)
# ... so let's try to do a 2-of-3 backup # ... so let's try to do a 2-of-3 backup
debug.read_layout()
# confirm backup intro # confirm backup intro
reset.confirm_read(debug) reset.confirm_read(debug)
# confirm checklist # confirm checklist
reset.confirm_read(debug) reset.confirm_read(debug)
# shares=3 # shares=3
reset.set_selection(debug, buttons.reset_minus(model_name), 5 - 3) reset.set_selection(debug, buttons.reset_minus(model_name), 5 - 3)
# confirm checklist # confirm checklist
reset.confirm_read(debug) reset.confirm_read(debug)
# threshold=2 # threshold=2
reset.set_selection(debug, buttons.reset_minus(model_name), 1) reset.set_selection(debug, buttons.reset_minus(model_name), 1)
# confirm checklist # confirm checklist
reset.confirm_read(debug) reset.confirm_read(debug)
# confirm backup warning # confirm backup warning
reset.confirm_read(debug, middle_r=True) reset.confirm_read(debug, middle_r=True)

View File

@ -21,6 +21,7 @@ import pytest
from trezorlib import device, messages from trezorlib import device, messages
from ..common import WITH_MOCK_URANDOM from ..common import WITH_MOCK_URANDOM
from .. import translations as TR
from . import reset from . import reset
from .common import go_next from .common import go_next
@ -50,12 +51,21 @@ def test_reset_bip39(device_handler: "BackgroundDeviceHandler"):
reset.confirm_new_wallet(debug) reset.confirm_new_wallet(debug)
# confirm back up # confirm back up
TR.assert_in_multiple(
debug.read_layout().text_content(),
["backup__it_should_be_backed_up", "backup__it_should_be_backed_up_now"],
)
reset.confirm_read(debug) reset.confirm_read(debug)
# confirm backup intro # confirm backup intro
reset.confirm_read(debug, middle_r=True) # parametrized string
TR.assert_template(
debug.read_layout().text_content(), "backup__info_single_share_backup"
)
reset.confirm_read(debug)
# confirm backup warning # confirm backup warning
TR.assert_in(debug.read_layout().text_content(), "reset__never_make_digital_copy")
reset.confirm_read(debug, middle_r=True) reset.confirm_read(debug, middle_r=True)
# read words # read words

View File

@ -21,6 +21,7 @@ import pytest
from trezorlib import device, messages from trezorlib import device, messages
from .. import buttons from .. import buttons
from .. import translations as TR
from ..common import EXTERNAL_ENTROPY, WITH_MOCK_URANDOM, generate_entropy from ..common import EXTERNAL_ENTROPY, WITH_MOCK_URANDOM, generate_entropy
from . import reset from . import reset
@ -62,12 +63,20 @@ def test_reset_slip39_advanced(
reset.confirm_new_wallet(debug) reset.confirm_new_wallet(debug)
# confirm back up # confirm back up
TR.assert_in_multiple(
debug.read_layout().text_content(),
["backup__it_should_be_backed_up", "backup__it_should_be_backed_up_now"],
)
reset.confirm_read(debug) reset.confirm_read(debug)
# confirm backup intro # confirm backup intro
TR.assert_in(debug.read_layout().text_content(), "backup__info_multi_share_backup")
reset.confirm_read(debug) reset.confirm_read(debug)
# confirm checklist # confirm checklist
TR.assert_in(
debug.read_layout().text_content(), "reset__slip39_checklist_num_groups"
)
reset.confirm_read(debug) reset.confirm_read(debug)
# set num of groups - default is 5 # set num of groups - default is 5
@ -79,6 +88,9 @@ def test_reset_slip39_advanced(
reset.set_selection(debug, buttons.reset_plus(model_name), group_count - 5) reset.set_selection(debug, buttons.reset_plus(model_name), group_count - 5)
# confirm checklist # confirm checklist
TR.assert_in(
debug.read_layout().text_content(), "reset__slip39_checklist_set_threshold"
)
reset.confirm_read(debug) reset.confirm_read(debug)
# set group threshold # set group threshold
@ -91,6 +103,13 @@ def test_reset_slip39_advanced(
raise RuntimeError("not a supported combination") raise RuntimeError("not a supported combination")
# confirm checklist # confirm checklist
TR.assert_in_multiple(
debug.read_layout().text_content(),
[
"reset__slip39_checklist_set_sizes",
"reset__slip39_checklist_set_sizes_longer",
],
)
reset.confirm_read(debug) reset.confirm_read(debug)
# set share num and threshold for groups # set share num and threshold for groups
@ -111,6 +130,7 @@ def test_reset_slip39_advanced(
raise RuntimeError("not a supported combination") raise RuntimeError("not a supported combination")
# confirm backup warning # confirm backup warning
TR.assert_in(debug.read_layout().text_content(), "reset__never_make_digital_copy")
reset.confirm_read(debug, middle_r=True) reset.confirm_read(debug, middle_r=True)
all_words: list[str] = [] all_words: list[str] = []

View File

@ -21,6 +21,7 @@ import pytest
from trezorlib import device, messages from trezorlib import device, messages
from .. import buttons from .. import buttons
from .. import translations as TR
from ..common import EXTERNAL_ENTROPY, WITH_MOCK_URANDOM, generate_entropy from ..common import EXTERNAL_ENTROPY, WITH_MOCK_URANDOM, generate_entropy
from . import reset from . import reset
@ -59,12 +60,20 @@ def test_reset_slip39_basic(
reset.confirm_new_wallet(debug) reset.confirm_new_wallet(debug)
# confirm back up # confirm back up
TR.assert_in_multiple(
debug.read_layout().text_content(),
["backup__it_should_be_backed_up", "backup__it_should_be_backed_up_now"],
)
reset.confirm_read(debug) reset.confirm_read(debug)
# confirm backup intro # confirm backup intro
TR.assert_in(debug.read_layout().text_content(), "backup__info_multi_share_backup")
reset.confirm_read(debug) reset.confirm_read(debug)
# confirm checklist # confirm checklist
TR.assert_in(
debug.read_layout().text_content(), "reset__slip39_checklist_num_shares"
)
reset.confirm_read(debug) reset.confirm_read(debug)
# set num of shares - default is 5 # set num of shares - default is 5
@ -76,6 +85,9 @@ def test_reset_slip39_basic(
reset.set_selection(debug, buttons.reset_plus(model_name), num_of_shares - 5) reset.set_selection(debug, buttons.reset_plus(model_name), num_of_shares - 5)
# confirm checklist # confirm checklist
TR.assert_in(
debug.read_layout().text_content(), "reset__slip39_checklist_set_threshold"
)
reset.confirm_read(debug) reset.confirm_read(debug)
# set threshold # set threshold
@ -88,9 +100,17 @@ def test_reset_slip39_basic(
raise RuntimeError("not a supported combination") raise RuntimeError("not a supported combination")
# confirm checklist # confirm checklist
TR.assert_in_multiple(
debug.read_layout().text_content(),
[
"reset__slip39_checklist_write_down",
"reset__slip39_checklist_write_down_recovery",
],
)
reset.confirm_read(debug) reset.confirm_read(debug)
# confirm backup warning # confirm backup warning
TR.assert_in(debug.read_layout().text_content(), "reset__never_make_digital_copy")
reset.confirm_read(debug, middle_r=True) reset.confirm_read(debug, middle_r=True)
all_words: list[str] = [] all_words: list[str] = []

View File

@ -20,7 +20,7 @@ import json
import re import re
import time import time
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING, Generator, Optional from typing import TYPE_CHECKING, Any, Generator, Optional
from unittest import mock from unittest import mock
import pytest import pytest
@ -315,17 +315,17 @@ def check_share(
return True return True
def click_info_button_tt(debug: "DebugLink"): def click_info_button_tt(debug: "DebugLink") -> Generator[Any, Any, ButtonRequest]:
"""Click Shamir backup info button and return back.""" """Click Shamir backup info button and return back."""
debug.press_info() debug.press_info()
debug.press_yes() debug.press_yes()
yield return (yield)
def click_info_button_mercury(debug: "DebugLink"): def click_info_button_mercury(debug: "DebugLink"):
"""Click Shamir backup info button and return back.""" """Click Shamir backup info button and return back."""
debug.click(buttons.CORNER_BUTTON) layout = debug.click(buttons.CORNER_BUTTON)
debug.synchronize_at("VerticalMenu") assert "VerticalMenu" in layout.all_components()
debug.click(buttons.VERTICAL_MENU[0]) debug.click(buttons.VERTICAL_MENU[0])
debug.click(buttons.CORNER_BUTTON) debug.click(buttons.CORNER_BUTTON)
debug.click(buttons.CORNER_BUTTON) debug.click(buttons.CORNER_BUTTON)

View File

@ -75,6 +75,7 @@ def test_secret(client: Client, shares: list[str], secret: str):
@pytest.mark.parametrize("shares, secret", VECTORS) @pytest.mark.parametrize("shares, secret", VECTORS)
@pytest.mark.setup_client(uninitialized=True) @pytest.mark.setup_client(uninitialized=True)
@pytest.mark.models(skip="safe3", reason="safe3 does not have info button")
def test_secret_click_info_button(client: Client, shares: list[str], secret: str): def test_secret_click_info_button(client: Client, shares: list[str], secret: str):
_test_secret(client, shares, secret, click_info=True) _test_secret(client, shares, secret, click_info=True)

View File

@ -110,7 +110,7 @@ def test_set_remove_wipe_code(client: Client):
def test_set_wipe_code_mismatch(client: Client): def test_set_wipe_code_mismatch(client: Client):
with client, pytest.raises(TrezorFailure): with client, pytest.raises(TrezorFailure):
IF = InputFlowNewCodeMismatch(client, WIPE_CODE4, WIPE_CODE6) IF = InputFlowNewCodeMismatch(client, WIPE_CODE4, WIPE_CODE6, what="wipe_code")
client.set_input_flow(IF.get()) client.set_input_flow(IF.get())
device.change_wipe_code(client) device.change_wipe_code(client)

View File

@ -133,7 +133,7 @@ def test_set_failed(client: Client):
_check_no_pin(client) _check_no_pin(client)
with client, pytest.raises(TrezorFailure): with client, pytest.raises(TrezorFailure):
IF = InputFlowNewCodeMismatch(client, PIN4, PIN60) IF = InputFlowNewCodeMismatch(client, PIN4, PIN60, what="pin")
client.set_input_flow(IF.get()) client.set_input_flow(IF.get())
device.change_pin(client) device.change_pin(client)

View File

@ -115,13 +115,15 @@ class InputFlowNewCodeMismatch(InputFlowBase):
client: Client, client: Client,
first_code: str, first_code: str,
second_code: str, second_code: str,
what: str,
): ):
super().__init__(client) super().__init__(client)
self.first_code = first_code self.first_code = first_code
self.second_code = second_code self.second_code = second_code
self.what = what
def input_flow_common(self) -> BRGeneratorType: def input_flow_common(self) -> BRGeneratorType:
yield # do you want to set/change the pin/wipe code? assert (yield).name == f"set_{self.what}"
self.debug.press_yes() self.debug.press_yes()
if self.client.layout_type is LayoutType.TR: if self.client.layout_type is LayoutType.TR:
@ -129,19 +131,21 @@ class InputFlowNewCodeMismatch(InputFlowBase):
self.debug.press_yes() self.debug.press_yes()
def input_two_different_pins() -> BRGeneratorType: def input_two_different_pins() -> BRGeneratorType:
yield from self.PIN.setup_new_pin(self.first_code, self.second_code) yield from self.PIN.setup_new_pin(
self.first_code, self.second_code, what=self.what
)
yield from input_two_different_pins() yield from input_two_different_pins()
yield # PIN mismatch assert (yield).name == f"{self.what}_mismatch" # PIN mismatch
self.debug.press_yes() # try again self.debug.press_yes() # try again
yield from input_two_different_pins() yield from input_two_different_pins()
yield # PIN mismatch assert (yield).name == f"{self.what}_mismatch" # PIN mismatch
self.debug.press_yes() # try again self.debug.press_yes() # try again
yield # PIN entry again assert (yield).name == "pin_device" # PIN entry again
self.debug.press_no() # cancel self.debug.press_no() # cancel
@ -463,7 +467,7 @@ class InputFlowShowMultisigXPUBs(InputFlowBase):
# Three xpub pages with the same testing logic # Three xpub pages with the same testing logic
for xpub_num in range(3): for xpub_num in range(3):
expected_title = f"MULTISIG XPUB #{xpub_num + 1}\n" + ( expected_title = f"MULTISIG XPUB #{xpub_num + 1}\n" + (
"(YOURS)" if self.index == xpub_num else "(COSIGNER)" "(Yours)" if self.index == xpub_num else "(Cosigner)"
) )
layout = self.debug.swipe_left() layout = self.debug.swipe_left()
assert expected_title == layout.title() assert expected_title == layout.title()
@ -499,7 +503,7 @@ class InputFlowShowMultisigXPUBs(InputFlowBase):
# Three xpub pages with the same testing logic # Three xpub pages with the same testing logic
for xpub_num in range(3): for xpub_num in range(3):
expected_title = f"MULTISIG XPUB #{xpub_num + 1} " + ( expected_title = f"MULTISIG XPUB #{xpub_num + 1} " + (
"(YOURS)" if self.index == xpub_num else "(COSIGNER)" "(Yours)" if self.index == xpub_num else "(Cosigner)"
) )
layout = self.debug.press_right() layout = self.debug.press_right()
assert expected_title in layout.title() assert expected_title in layout.title()
@ -979,32 +983,17 @@ class InputFlowSignTxInformationReplacement(InputFlowBase):
yield # confirm txid yield # confirm txid
self.debug.press_right() self.debug.press_right()
self.debug.press_right() self.debug.press_right()
yield # confirm address yield # modify amount - address
self.debug.press_right()
self.debug.press_right()
yield # modify amount - amount
self.debug.press_right()
yield # modify fee
self.debug.press_right() self.debug.press_right()
self.debug.press_right() self.debug.press_right()
self.debug.press_right() self.debug.press_right()
yield # confirm amount
self.debug.press_right()
self.debug.press_right()
self.debug.press_right()
yield
def input_flow_t3t1(self) -> BRGeneratorType: input_flow_t3t1 = input_flow_tt
yield # confirm txid
self.debug.press_yes()
yield # confirm address
self.debug.press_yes()
# go back to address
self.debug.press_no()
# confirm address
self.debug.press_yes()
yield # confirm amount
self.debug.press_yes()
yield # transaction summary, press info
self.debug.click(buttons.CORNER_BUTTON)
self.debug.click(buttons.CORNER_BUTTON)
self.debug.press_yes()
def lock_time_input_flow_tt( def lock_time_input_flow_tt(
@ -1436,23 +1425,29 @@ class InputFlowSlip39BasicBackup(InputFlowBase):
self.repeated = repeated self.repeated = repeated
def input_flow_tt(self) -> BRGeneratorType: def input_flow_tt(self) -> BRGeneratorType:
yield # 1. Checklist if self.repeated:
assert (yield).name == "confirm_repeated_backup"
self.debug.press_yes() self.debug.press_yes()
yield # 2. Number of shares (5)
assert (yield).name == "backup_intro"
self.debug.press_yes()
assert (yield).name == "slip39_checklist"
self.debug.press_yes()
assert (yield).name == "slip39_shares"
if self.click_info: if self.click_info:
yield from click_info_button_tt(self.debug) br = yield from click_info_button_tt(self.debug)
yield # 3. Number of shares (5) assert br.name == "slip39_shares"
self.debug.press_yes() self.debug.press_yes()
yield # 4. Checklist assert (yield).name == "slip39_checklist"
self.debug.press_yes() self.debug.press_yes()
yield # 4. Threshold (3) assert (yield).name == "slip39_threshold"
if self.click_info: if self.click_info:
yield from click_info_button_tt(self.debug) br = yield from click_info_button_tt(self.debug)
yield # 5. Threshold (3) assert br.name == "slip39_threshold"
self.debug.press_yes() self.debug.press_yes()
yield # 6. Checklist assert (yield).name == "slip39_checklist"
self.debug.press_yes() self.debug.press_yes()
yield # 7. Confirm show seeds assert (yield).name == "backup_warning"
self.debug.press_yes() self.debug.press_yes()
# Mnemonic phrases # Mnemonic phrases
@ -1497,26 +1492,26 @@ class InputFlowSlip39BasicBackup(InputFlowBase):
def input_flow_t3t1(self) -> BRGeneratorType: def input_flow_t3t1(self) -> BRGeneratorType:
if self.repeated: if self.repeated:
# intro confirmation screen # intro confirmation screen
yield assert (yield).name == "confirm_repeated_backup"
self.debug.press_yes() self.debug.press_yes()
yield # 1. Backup intro assert (yield).name == "backup_intro"
self.debug.read_layout()
self.debug.swipe_up() self.debug.swipe_up()
yield # 2. Checklist assert (yield).name == "slip39_checklist"
self.debug.read_layout()
self.debug.swipe_up() self.debug.swipe_up()
assert (yield).name == "slip39_shares"
if self.click_info: if self.click_info:
click_info_button_mercury(self.debug) click_info_button_mercury(self.debug)
self.debug.swipe_up() self.debug.swipe_up()
yield # 4. Checklist assert (yield).name == "slip39_checklist"
self.debug.swipe_up() self.debug.swipe_up()
assert (yield).name == "slip39_threshold"
if self.click_info: if self.click_info:
click_info_button_mercury(self.debug) click_info_button_mercury(self.debug)
self.debug.swipe_up() self.debug.swipe_up()
yield # 6. Checklist assert (yield).name == "slip39_checklist"
self.debug.swipe_up() self.debug.swipe_up()
yield # 7. Confirm show seeds assert (yield).name == "backup_warning"
self.debug.swipe_up() self.debug.swipe_up()
# Mnemonic phrases # Mnemonic phrases
@ -1702,34 +1697,36 @@ class InputFlowSlip39AdvancedBackup(InputFlowBase):
self.click_info = click_info self.click_info = click_info
def input_flow_tt(self) -> BRGeneratorType: def input_flow_tt(self) -> BRGeneratorType:
yield # 1. Backup intro assert (yield).name == "backup_intro"
self.debug.press_yes() self.debug.press_yes()
yield # 2. Checklist assert (yield).name == "slip39_checklist"
self.debug.press_yes() self.debug.press_yes()
yield # 2. Set and confirm group count assert (yield).name == "slip39_groups"
if self.click_info: if self.click_info:
yield from click_info_button_tt(self.debug) br = yield from click_info_button_tt(self.debug)
yield # 3. Set and confirm group count assert br.name == "slip39_groups"
self.debug.press_yes() self.debug.press_yes()
yield # 4. Checklist assert (yield).name == "slip39_checklist"
self.debug.press_yes() self.debug.press_yes()
yield # 4. Set and confirm group threshold assert (yield).name == "slip39_group_threshold"
if self.click_info: if self.click_info:
yield from click_info_button_tt(self.debug) br = yield from click_info_button_tt(self.debug)
yield # 5. Set and confirm group threshold assert br.name == "slip39_group_threshold"
self.debug.press_yes() self.debug.press_yes()
yield # 6. Checklist assert (yield).name == "slip39_checklist"
self.debug.press_yes() self.debug.press_yes()
for _ in range(5): # for each of 5 groups for _ in range(5): # for each of 5 groups
yield # Set & Confirm number of shares assert (yield).name == "slip39_shares"
if self.click_info: if self.click_info:
yield from click_info_button_tt(self.debug) br = yield from click_info_button_tt(self.debug)
assert br.name == "slip39_shares"
self.debug.press_yes() self.debug.press_yes()
yield # Set & confirm share threshold value assert (yield).name == "slip39_threshold"
if self.click_info: if self.click_info:
yield from click_info_button_tt(self.debug) br = yield from click_info_button_tt(self.debug)
assert br.name == "slip39_threshold"
self.debug.press_yes() self.debug.press_yes()
yield # Confirm show seeds assert (yield).name == "backup_warning"
self.debug.press_yes() self.debug.press_yes()
# Mnemonic phrases - show & confirm shares for all groups # Mnemonic phrases - show & confirm shares for all groups
@ -2077,7 +2074,7 @@ class InputFlowSlip39BasicRecoveryDryRun(InputFlowBase):
yield from self.REC.input_all_slip39_shares(self.shares) yield from self.REC.input_all_slip39_shares(self.shares)
if self.mismatch: if self.mismatch:
yield from self.REC.warning_slip39_dryrun_mismatch() yield from self.REC.warning_slip39_dryrun_mismatch()
else: elif not self.unlock_repeated_backup:
yield from self.REC.success_slip39_dryrun_valid() yield from self.REC.success_slip39_dryrun_valid()

View File

@ -1,3 +1,5 @@
import typing as t
from trezorlib import messages from trezorlib import messages
from trezorlib.debuglink import LayoutType from trezorlib.debuglink import LayoutType
from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.debuglink import TrezorClientDebugLink as Client
@ -16,18 +18,21 @@ class PinFlow:
self.debug = self.client.debug self.debug = self.client.debug
def setup_new_pin( def setup_new_pin(
self, pin: str, second_different_pin: str | None = None self,
pin: str,
second_different_pin: str | None = None,
what: str = "pin",
) -> BRGeneratorType: ) -> BRGeneratorType:
yield # Enter PIN assert (yield).name == "pin_device" # Enter PIN
assert "PinKeyboard" in self.debug.read_layout().all_components() assert "PinKeyboard" in self.debug.read_layout().all_components()
self.debug.input(pin) self.debug.input(pin)
if self.client.layout_type is LayoutType.TR: if self.client.layout_type is LayoutType.TR:
yield # Reenter PIN assert (yield).name == f"reenter_{what}" # Reenter PIN
TR.assert_in( TR.assert_in(
self.debug.read_layout().text_content(), "pin__reenter_to_confirm" self.debug.read_layout().text_content(), f"{what}__reenter_to_confirm"
) )
self.debug.press_yes() self.debug.press_yes()
yield # Enter PIN again assert (yield).name == "pin_device" # Enter PIN again
assert "PinKeyboard" in self.debug.read_layout().all_components() assert "PinKeyboard" in self.debug.read_layout().all_components()
if second_different_pin is not None: if second_different_pin is not None:
self.debug.input(second_different_pin) self.debug.input(second_different_pin)
@ -58,14 +63,14 @@ class RecoveryFlow:
return layout.title() + " " + layout.text_content() return layout.title() + " " + layout.text_content()
def confirm_recovery(self) -> BRGeneratorType: def confirm_recovery(self) -> BRGeneratorType:
yield assert (yield).name == "recover_device"
TR.assert_in(self._text_content(), "reset__by_continuing") TR.assert_in(self._text_content(), "reset__by_continuing")
if self.client.layout_type is LayoutType.TR: if self.client.layout_type is LayoutType.TR:
self.debug.press_right() self.debug.press_right()
self.debug.press_yes() self.debug.press_yes()
def confirm_dry_run(self) -> BRGeneratorType: def confirm_dry_run(self) -> BRGeneratorType:
yield assert (yield).name == "confirm_seedcheck"
TR.assert_in(self._text_content(), "recovery__check_dry_run") TR.assert_in(self._text_content(), "recovery__check_dry_run")
self.debug.press_yes() self.debug.press_yes()
@ -93,7 +98,7 @@ class RecoveryFlow:
self.debug.press_yes() self.debug.press_yes()
def enter_your_backup(self) -> BRGeneratorType: def enter_your_backup(self) -> BRGeneratorType:
yield assert (yield).name == "recovery"
if self.debug.layout_type is LayoutType.Mercury: if self.debug.layout_type is LayoutType.Mercury:
TR.assert_in(self._text_content(), "recovery__enter_each_word") TR.assert_in(self._text_content(), "recovery__enter_each_word")
else: else:
@ -109,7 +114,7 @@ class RecoveryFlow:
self.debug.press_yes() self.debug.press_yes()
def enter_any_share(self) -> BRGeneratorType: def enter_any_share(self) -> BRGeneratorType:
yield assert (yield).name == "recovery"
TR.assert_in_multiple( TR.assert_in_multiple(
self._text_content(), self._text_content(),
["recovery__enter_any_share", "recovery__enter_each_word"], ["recovery__enter_any_share", "recovery__enter_each_word"],
@ -172,9 +177,9 @@ class RecoveryFlow:
self.debug.click(buttons.CORNER_BUTTON) self.debug.click(buttons.CORNER_BUTTON)
self.debug.synchronize_at("VerticalMenu") self.debug.synchronize_at("VerticalMenu")
self.debug.click(buttons.VERTICAL_MENU[0]) self.debug.click(buttons.VERTICAL_MENU[0])
self.debug.swipe_up()
assert (yield).name == "abort_recovery" assert (yield).name == "abort_recovery"
self.debug.synchronize_at("PromptScreen") layout = self.debug.swipe_up()
TR.assert_equals(layout.title(), "recovery__title_cancel_recovery")
self.debug.click(buttons.TAP_TO_CONFIRM) self.debug.click(buttons.TAP_TO_CONFIRM)
else: else:
TR.assert_template( TR.assert_template(
@ -188,6 +193,7 @@ class RecoveryFlow:
def input_number_of_words(self, num_words: int) -> BRGeneratorType: def input_number_of_words(self, num_words: int) -> BRGeneratorType:
br = yield br = yield
assert br.code == B.MnemonicWordCount assert br.code == B.MnemonicWordCount
assert br.name == "recovery_word_count"
if self.client.layout_type is LayoutType.TR: if self.client.layout_type is LayoutType.TR:
TR.assert_in(self.debug.read_layout().title(), "word_count__title") TR.assert_in(self.debug.read_layout().title(), "word_count__title")
else: else:
@ -227,7 +233,7 @@ class RecoveryFlow:
self.debug.press_yes() self.debug.press_yes()
def success_share_group_entered(self) -> BRGeneratorType: def success_share_group_entered(self) -> BRGeneratorType:
yield assert (yield).name == "share_success"
TR.assert_in(self._text_content(), "recovery__you_have_entered") TR.assert_in(self._text_content(), "recovery__you_have_entered")
self.debug.press_yes() self.debug.press_yes()
@ -274,17 +280,20 @@ class RecoveryFlow:
self.debug.press_yes() self.debug.press_yes()
def success_more_shares_needed( def success_more_shares_needed(
self, count_needed: int | None = None self, count_needed: int | None = None, click_ok: bool = True
) -> BRGeneratorType: ) -> BRGeneratorType:
br = yield br = yield
assert br.name == "recovery"
text = get_text_possible_pagination(self.debug, br) text = get_text_possible_pagination(self.debug, br)
if count_needed is not None: if count_needed is not None:
assert str(count_needed) in text assert str(count_needed) in text
if click_ok:
self.debug.press_yes() self.debug.press_yes()
def input_mnemonic(self, mnemonic: list[str]) -> BRGeneratorType: def input_mnemonic(self, mnemonic: list[str]) -> BRGeneratorType:
br = yield br = yield
assert br.code == B.MnemonicInput assert br.code == B.MnemonicInput
assert br.name == "mnemonic"
assert "MnemonicKeyboard" in self.debug.read_layout().all_components() assert "MnemonicKeyboard" in self.debug.read_layout().all_components()
for _, word in enumerate(mnemonic): for _, word in enumerate(mnemonic):
self.debug.input(word) self.debug.input(word)
@ -302,27 +311,26 @@ class RecoveryFlow:
if index < len(shares) - 1: if index < len(shares) - 1:
if has_groups: if has_groups:
yield from self.success_share_group_entered() yield from self.success_share_group_entered()
yield from self.success_more_shares_needed(click_ok=not click_info)
if click_info: if click_info:
if self.client.layout_type is LayoutType.TT: if self.client.layout_type is LayoutType.TT:
yield from self.tt_click_info() yield from self.tt_click_info()
elif self.client.layout_type is LayoutType.Mercury: elif self.client.layout_type is LayoutType.Mercury:
yield from self.mercury_click_info() yield from self.mercury_click_info()
else:
raise ValueError("Unknown model!")
yield from self.success_more_shares_needed() yield from self.success_more_shares_needed()
def tt_click_info( def tt_click_info(self) -> t.Generator[t.Any, t.Any, None]:
self,
) -> BRGeneratorType:
# Moving through the INFO button
yield
self.debug.press_info() self.debug.press_info()
br = yield
assert br.name == "show_shares"
for _ in range(br.pages):
self.debug.swipe_up() self.debug.swipe_up()
self.debug.press_yes() self.debug.press_yes()
def mercury_click_info(self) -> BRGeneratorType: def mercury_click_info(self) -> BRGeneratorType:
# Starting on the homepage, handle the repeated button request
br = yield
assert br.name == "recovery"
assert br.code == B.RecoveryHomepage
# Moving through the menu into the show_shares screen # Moving through the menu into the show_shares screen
self.debug.click(buttons.CORNER_BUTTON) self.debug.click(buttons.CORNER_BUTTON)
self.debug.synchronize_at("VerticalMenu") self.debug.synchronize_at("VerticalMenu")

View File

@ -1,5 +1,6 @@
from trezorlib import debuglink, device, messages from trezorlib import debuglink, device, messages
from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.debuglink import message_filters
from ..common import MNEMONIC12 from ..common import MNEMONIC12
from ..emulators import Emulator, EmulatorWrapper from ..emulators import Emulator, EmulatorWrapper
@ -48,9 +49,8 @@ def test_wipe_code_activate_core(core_emulator: Emulator):
ret = core_emulator.client.call_raw(messages.ButtonAck()) ret = core_emulator.client.call_raw(messages.ButtonAck())
# Enter the wipe code instead of the current PIN # Enter the wipe code instead of the current PIN
assert ret == messages.ButtonRequest( expected = message_filters.ButtonRequest(code=messages.ButtonRequestType.PinEntry)
code=messages.ButtonRequestType.PinEntry, name="pin_device" assert expected.match(ret)
)
core_emulator.client._raw_write(messages.ButtonAck()) core_emulator.client._raw_write(messages.ButtonAck())
core_emulator.client.debug.input(WIPE_CODE) core_emulator.client.debug.input(WIPE_CODE)