mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-30 10:28:14 +00:00
tests: use read_layout everywhere
This commit is contained in:
parent
e2547db43d
commit
162f13c6ea
@ -42,25 +42,23 @@ def get_char_category(char: str) -> PassphraseCategory:
|
||||
return PassphraseCategory.SPECIAL
|
||||
|
||||
|
||||
def go_next(debug: "DebugLink", wait: bool = False) -> "LayoutContent" | None:
|
||||
def go_next(debug: "DebugLink") -> "LayoutContent":
|
||||
if debug.model == "T":
|
||||
return debug.click(buttons.OK, wait=wait) # type: ignore
|
||||
return debug.click(buttons.OK)
|
||||
elif debug.model == "Safe 3":
|
||||
return debug.press_right(wait=wait) # type: ignore
|
||||
return debug.press_right()
|
||||
else:
|
||||
raise RuntimeError("Unknown model")
|
||||
|
||||
|
||||
def go_back(
|
||||
debug: "DebugLink", wait: bool = False, r_middle: bool = False
|
||||
) -> "LayoutContent" | None:
|
||||
def go_back(debug: "DebugLink", r_middle: bool = False) -> "LayoutContent":
|
||||
if debug.model == "T":
|
||||
return debug.click(buttons.CANCEL, wait=wait) # type: ignore
|
||||
return debug.click(buttons.CANCEL)
|
||||
elif debug.model == "Safe 3":
|
||||
if r_middle:
|
||||
return debug.press_middle(wait=wait) # type: ignore
|
||||
return debug.press_middle()
|
||||
else:
|
||||
return debug.press_left(wait=wait) # type: ignore
|
||||
return debug.press_left()
|
||||
else:
|
||||
raise RuntimeError("Unknown model")
|
||||
|
||||
@ -101,10 +99,7 @@ def navigate_to_action_and_press(
|
||||
)
|
||||
|
||||
# Press or hold
|
||||
if hold_ms:
|
||||
debug.press_middle_htc(1000)
|
||||
else:
|
||||
debug.press_middle(wait=True)
|
||||
debug.press_middle(hold_ms=hold_ms)
|
||||
|
||||
|
||||
def _get_action_index(wanted_action: str, all_actions: list[str]) -> int:
|
||||
@ -136,14 +131,14 @@ def _move_one_closer(
|
||||
if not is_carousel:
|
||||
# Simply move according to the index in a closed list
|
||||
if index_diff > 0:
|
||||
return debug.press_right(wait=True)
|
||||
return debug.press_right()
|
||||
else:
|
||||
return debug.press_left(wait=True)
|
||||
return debug.press_left()
|
||||
else:
|
||||
# Carousel can move in a circle - over the edges
|
||||
# Always move the shortest way
|
||||
action_half = len(all_actions) // 2
|
||||
if index_diff > action_half or -action_half < index_diff < 0:
|
||||
return debug.press_left(wait=True)
|
||||
return debug.press_left()
|
||||
else:
|
||||
return debug.press_right(wait=True)
|
||||
return debug.press_right()
|
||||
|
@ -15,7 +15,7 @@ def enter_word(
|
||||
for coords in buttons.type_word(typed_word, is_slip39=is_slip39):
|
||||
debug.click(coords)
|
||||
|
||||
return debug.click(buttons.CONFIRM_WORD, wait=True)
|
||||
return debug.click(buttons.CONFIRM_WORD)
|
||||
elif debug.model == "Safe 3":
|
||||
letter_index = 0
|
||||
layout = debug.read_layout()
|
||||
@ -24,36 +24,32 @@ def enter_word(
|
||||
while layout.find_values_by_key("letter_choices"):
|
||||
letter = word[letter_index]
|
||||
while not layout.get_middle_choice() == letter:
|
||||
layout = debug.press_right(wait=True)
|
||||
layout = debug.press_right()
|
||||
|
||||
layout = debug.press_middle(wait=True)
|
||||
layout = debug.press_middle()
|
||||
letter_index += 1
|
||||
|
||||
# Word choices
|
||||
while not layout.get_middle_choice() == word:
|
||||
layout = debug.press_right(wait=True)
|
||||
layout = debug.press_right()
|
||||
|
||||
return debug.press_middle(wait=True)
|
||||
return debug.press_middle()
|
||||
else:
|
||||
raise ValueError("Unknown model")
|
||||
|
||||
|
||||
def confirm_recovery(debug: "DebugLink") -> None:
|
||||
layout = debug.wait_layout()
|
||||
layout = debug.read_layout()
|
||||
if debug.model == "T":
|
||||
assert layout.title().startswith(("RECOVER WALLET", "BACKUP CHECK"))
|
||||
debug.click(buttons.OK, wait=True)
|
||||
debug.click(buttons.OK)
|
||||
elif debug.model == "Safe 3":
|
||||
assert layout.title() == "RECOVER WALLET"
|
||||
debug.press_right(wait=True)
|
||||
debug.press_right()
|
||||
debug.press_right()
|
||||
|
||||
|
||||
def select_number_of_words(
|
||||
debug: "DebugLink", num_of_words: int = 20, wait: bool = True
|
||||
) -> None:
|
||||
if wait:
|
||||
debug.wait_layout()
|
||||
def select_number_of_words(debug: "DebugLink", num_of_words: int = 20) -> None:
|
||||
if debug.model == "T":
|
||||
assert "number of words" in debug.read_layout().text_content()
|
||||
assert debug.read_layout().title() in (
|
||||
@ -68,10 +64,10 @@ def select_number_of_words(
|
||||
num_of_words
|
||||
) # raises if num of words is invalid
|
||||
coords = buttons.grid34(index % 3, index // 3)
|
||||
layout = debug.click(coords, wait=True)
|
||||
layout = debug.click(coords)
|
||||
elif debug.model == "Safe 3":
|
||||
assert "number of words" in debug.read_layout().text_content()
|
||||
layout = debug.press_right(wait=True)
|
||||
layout = debug.press_right()
|
||||
|
||||
assert layout.title() == "NUMBER OF WORDS"
|
||||
|
||||
@ -79,8 +75,8 @@ def select_number_of_words(
|
||||
word_options = (12, 18, 20, 24, 33)
|
||||
index = word_options.index(num_of_words)
|
||||
for _ in range(index):
|
||||
debug.press_right(wait=True)
|
||||
layout = debug.press_middle(wait=True)
|
||||
debug.press_right()
|
||||
layout = debug.press_middle()
|
||||
else:
|
||||
raise ValueError("Unknown model")
|
||||
|
||||
@ -94,7 +90,7 @@ def enter_share(
|
||||
debug: "DebugLink", share: str, is_first: bool = True
|
||||
) -> "LayoutContent":
|
||||
if debug.model == "T":
|
||||
layout = debug.click(buttons.OK, wait=True)
|
||||
layout = debug.click(buttons.OK)
|
||||
|
||||
assert layout.main_component() == "MnemonicKeyboard"
|
||||
for word in share.split(" "):
|
||||
@ -102,12 +98,12 @@ def enter_share(
|
||||
|
||||
return layout
|
||||
elif debug.model == "Safe 3":
|
||||
assert "RECOVER WALLET" in debug.wait_layout().title()
|
||||
layout = debug.press_right(wait=True)
|
||||
assert "RECOVER WALLET" in debug.read_layout().title()
|
||||
layout = debug.press_right()
|
||||
if is_first:
|
||||
# Word entering info
|
||||
debug.press_right()
|
||||
layout = debug.press_right(wait=True)
|
||||
layout = debug.press_right()
|
||||
assert "MnemonicKeyboard" in layout.all_components()
|
||||
|
||||
for word in share.split(" "):
|
||||
@ -132,14 +128,14 @@ def enter_shares(debug: "DebugLink", shares: list[str]) -> None:
|
||||
def enter_seed(debug: "DebugLink", seed_words: list[str]) -> None:
|
||||
assert "Enter" in debug.read_layout().text_content()
|
||||
if debug.model == "T":
|
||||
layout = debug.click(buttons.OK, wait=True)
|
||||
layout = debug.click(buttons.OK)
|
||||
assert layout.main_component() == "MnemonicKeyboard"
|
||||
elif debug.model == "Safe 3":
|
||||
layout = debug.press_right(wait=True)
|
||||
layout = debug.press_right()
|
||||
assert "RECOVER WALLET" in layout.title()
|
||||
debug.press_right()
|
||||
|
||||
layout = debug.press_right(wait=True)
|
||||
layout = debug.press_right()
|
||||
assert "MnemonicKeyboard" in layout.all_components()
|
||||
|
||||
for word in seed_words:
|
||||
@ -149,6 +145,6 @@ def enter_seed(debug: "DebugLink", seed_words: list[str]) -> None:
|
||||
|
||||
|
||||
def finalize(debug: "DebugLink") -> None:
|
||||
layout = go_next(debug, wait=True)
|
||||
layout = go_next(debug)
|
||||
assert layout is not None
|
||||
assert layout.main_component() == "Homescreen"
|
||||
|
@ -11,13 +11,13 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
def confirm_new_wallet(debug: "DebugLink") -> None:
|
||||
layout = debug.wait_layout()
|
||||
layout = debug.read_layout()
|
||||
assert layout.title().startswith("CREATE WALLET")
|
||||
if debug.model == "T":
|
||||
debug.click(buttons.OK, wait=True)
|
||||
debug.click(buttons.OK)
|
||||
elif debug.model == "Safe 3":
|
||||
debug.press_right(wait=True)
|
||||
debug.press_right(wait=True)
|
||||
debug.press_right()
|
||||
debug.press_right()
|
||||
|
||||
|
||||
def confirm_read(debug: "DebugLink", title: str, middle_r: bool = False) -> None:
|
||||
@ -42,14 +42,14 @@ def confirm_read(debug: "DebugLink", title: str, middle_r: bool = False) -> None
|
||||
assert title.upper() in layout.title()
|
||||
|
||||
if debug.model == "T":
|
||||
debug.click(buttons.OK, wait=True)
|
||||
debug.click(buttons.OK)
|
||||
elif debug.model == "Safe 3":
|
||||
if layout.page_count() > 1:
|
||||
debug.press_right(wait=True)
|
||||
debug.press_right()
|
||||
if middle_r:
|
||||
debug.press_middle(wait=True)
|
||||
debug.press_middle()
|
||||
else:
|
||||
debug.press_right(wait=True)
|
||||
debug.press_right()
|
||||
|
||||
|
||||
def set_selection(debug: "DebugLink", button: tuple[int, int], diff: int) -> None:
|
||||
@ -57,20 +57,20 @@ def set_selection(debug: "DebugLink", button: tuple[int, int], diff: int) -> Non
|
||||
assert "NumberInputDialog" in debug.read_layout().all_components()
|
||||
for _ in range(diff):
|
||||
debug.click(button)
|
||||
debug.click(buttons.OK, wait=True)
|
||||
debug.click(buttons.OK)
|
||||
elif debug.model == "Safe 3":
|
||||
layout = debug.read_layout()
|
||||
if layout.title() in ("NUMBER OF SHARES", "THRESHOLD"):
|
||||
# Special info screens
|
||||
layout = debug.press_right(wait=True)
|
||||
layout = debug.press_right()
|
||||
assert "NumberInput" in layout.all_components()
|
||||
if button == buttons.RESET_MINUS:
|
||||
for _ in range(diff):
|
||||
debug.press_left(wait=True)
|
||||
debug.press_left()
|
||||
else:
|
||||
for _ in range(diff):
|
||||
debug.press_right(wait=True)
|
||||
debug.press_middle(wait=True)
|
||||
debug.press_right()
|
||||
debug.press_middle()
|
||||
|
||||
|
||||
def read_words(
|
||||
@ -95,12 +95,12 @@ def read_words(
|
||||
assert layout.title() == "STANDARD BACKUP"
|
||||
|
||||
assert "Write down" in layout.text_content()
|
||||
layout = debug.press_right(wait=True)
|
||||
layout = debug.press_right()
|
||||
|
||||
# Swiping through all the pages and loading the words
|
||||
for _ in range(layout.page_count() - 1):
|
||||
words.extend(layout.seed_words())
|
||||
layout = debug.swipe_up(wait=True)
|
||||
layout = debug.swipe_up()
|
||||
assert layout is not None
|
||||
if debug.model == "T":
|
||||
words.extend(layout.seed_words())
|
||||
@ -108,9 +108,9 @@ def read_words(
|
||||
# There is hold-to-confirm button
|
||||
if do_htc:
|
||||
if debug.model == "T":
|
||||
debug.click_hold(buttons.OK, hold_ms=1500)
|
||||
debug.click(buttons.OK, hold_ms=1500)
|
||||
elif debug.model == "Safe 3":
|
||||
debug.press_right_htc(1200)
|
||||
debug.press_right(hold_ms=1200)
|
||||
else:
|
||||
# It would take a very long time to test 16-of-16 with doing 1500 ms HTC after
|
||||
# each word set
|
||||
@ -120,7 +120,7 @@ def read_words(
|
||||
|
||||
|
||||
def confirm_words(debug: "DebugLink", words: list[str]) -> None:
|
||||
layout = debug.wait_layout()
|
||||
layout = debug.read_layout()
|
||||
if debug.model == "T":
|
||||
assert "Select word" in layout.text_content()
|
||||
for _ in range(3):
|
||||
@ -133,10 +133,10 @@ def confirm_words(debug: "DebugLink", words: list[str]) -> None:
|
||||
]
|
||||
wanted_word = words[word_pos - 1].lower()
|
||||
button_pos = btn_texts.index(wanted_word)
|
||||
layout = debug.click(buttons.RESET_WORD_CHECK[button_pos], wait=True)
|
||||
layout = debug.click(buttons.RESET_WORD_CHECK[button_pos])
|
||||
elif debug.model == "Safe 3":
|
||||
assert "Select the correct word" in layout.text_content()
|
||||
layout = debug.press_right(wait=True)
|
||||
layout = debug.press_right()
|
||||
for _ in range(3):
|
||||
# "SELECT 2ND WORD"
|
||||
# ^
|
||||
@ -144,9 +144,9 @@ def confirm_words(debug: "DebugLink", words: list[str]) -> None:
|
||||
wanted_word = words[word_pos - 1].lower()
|
||||
|
||||
while not layout.get_middle_choice() == wanted_word:
|
||||
layout = debug.press_right(wait=True)
|
||||
layout = debug.press_right()
|
||||
|
||||
layout = debug.press_middle(wait=True)
|
||||
layout = debug.press_middle()
|
||||
|
||||
|
||||
def validate_mnemonics(mnemonics: list[str], expected_ems: bytes) -> None:
|
||||
|
@ -59,15 +59,15 @@ def set_autolock_delay(device_handler: "BackgroundDeviceHandler", delay_ms: int)
|
||||
|
||||
device_handler.run(device.apply_settings, auto_lock_delay_ms=delay_ms) # type: ignore
|
||||
|
||||
assert "PinKeyboard" in debug.wait_layout().all_components()
|
||||
assert "PinKeyboard" in debug.read_layout().all_components()
|
||||
|
||||
debug.input("1234")
|
||||
|
||||
assert (
|
||||
f"Auto-lock your Trezor after {delay_ms // 1000} seconds"
|
||||
in debug.wait_layout().text_content()
|
||||
in debug.read_layout().text_content()
|
||||
)
|
||||
layout = go_next(debug, wait=True)
|
||||
layout = go_next(debug)
|
||||
assert layout.main_component() == "Homescreen"
|
||||
assert device_handler.result() == "Settings applied"
|
||||
|
||||
@ -97,16 +97,16 @@ def test_autolock_interrupts_signing(device_handler: "BackgroundDeviceHandler"):
|
||||
|
||||
assert (
|
||||
"1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1"
|
||||
in debug.wait_layout().text_content().replace(" ", "")
|
||||
in debug.read_layout().text_content().replace(" ", "")
|
||||
)
|
||||
|
||||
if debug.model == "T":
|
||||
debug.click(buttons.OK, wait=True)
|
||||
layout = debug.click(buttons.OK, wait=True)
|
||||
debug.click(buttons.OK)
|
||||
layout = debug.click(buttons.OK)
|
||||
assert "Total amount: 0.0039 BTC" in layout.text_content()
|
||||
elif debug.model == "Safe 3":
|
||||
debug.press_right(wait=True)
|
||||
layout = debug.press_right(wait=True)
|
||||
debug.press_right()
|
||||
layout = debug.press_right()
|
||||
assert "Total amount: 0.0039 BTC" in layout.text_content()
|
||||
|
||||
# wait for autolock to kick in
|
||||
@ -142,16 +142,16 @@ def test_autolock_does_not_interrupt_signing(device_handler: "BackgroundDeviceHa
|
||||
|
||||
assert (
|
||||
"1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1"
|
||||
in debug.wait_layout().text_content().replace(" ", "")
|
||||
in debug.read_layout().text_content().replace(" ", "")
|
||||
)
|
||||
|
||||
if debug.model == "T":
|
||||
debug.click(buttons.OK, wait=True)
|
||||
layout = debug.click(buttons.OK, wait=True)
|
||||
debug.click(buttons.OK)
|
||||
layout = debug.click(buttons.OK)
|
||||
assert "Total amount: 0.0039 BTC" in layout.text_content()
|
||||
elif debug.model == "Safe 3":
|
||||
debug.press_right(wait=True)
|
||||
layout = debug.press_right(wait=True)
|
||||
debug.press_right()
|
||||
layout = debug.press_right()
|
||||
assert "Total amount: 0.0039 BTC" in layout.text_content()
|
||||
|
||||
def sleepy_filter(msg: MessageType) -> MessageType:
|
||||
@ -163,9 +163,9 @@ def test_autolock_does_not_interrupt_signing(device_handler: "BackgroundDeviceHa
|
||||
device_handler.client.set_filter(messages.TxAck, sleepy_filter)
|
||||
# confirm transaction
|
||||
if debug.model == "T":
|
||||
debug.click(buttons.OK)
|
||||
debug.click(buttons.OK, wait=False)
|
||||
elif debug.model == "Safe 3":
|
||||
debug.press_middle()
|
||||
debug.press_middle(wait=False)
|
||||
|
||||
signatures, tx = device_handler.result()
|
||||
assert len(signatures) == 1
|
||||
@ -182,7 +182,7 @@ def test_autolock_passphrase_keyboard(device_handler: "BackgroundDeviceHandler")
|
||||
# get address
|
||||
device_handler.run(common.get_test_address) # type: ignore
|
||||
|
||||
assert "PassphraseKeyboard" in debug.wait_layout().all_components()
|
||||
assert "PassphraseKeyboard" in debug.read_layout().all_components()
|
||||
|
||||
if debug.model == "Safe 3":
|
||||
# Going into the selected character category
|
||||
@ -203,9 +203,9 @@ 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.model == "T":
|
||||
debug.click(buttons.OK, wait=True)
|
||||
debug.click(buttons.OK)
|
||||
elif debug.model == "Safe 3":
|
||||
debug.input("j" * 8, wait=True)
|
||||
debug.input("j" * 8)
|
||||
|
||||
# address corresponding to "jjjjjjjj" passphrase
|
||||
assert device_handler.result() == "mnF4yRWJXmzRB6EuBzuVigqeqTqirQupxJ"
|
||||
@ -219,7 +219,7 @@ def test_autolock_interrupts_passphrase(device_handler: "BackgroundDeviceHandler
|
||||
# get address
|
||||
device_handler.run(common.get_test_address) # type: ignore
|
||||
|
||||
assert "PassphraseKeyboard" in debug.wait_layout().all_components()
|
||||
assert "PassphraseKeyboard" in debug.read_layout().all_components()
|
||||
|
||||
if debug.model == "Safe 3":
|
||||
# Going into the selected character category
|
||||
@ -236,17 +236,17 @@ def test_autolock_interrupts_passphrase(device_handler: "BackgroundDeviceHandler
|
||||
|
||||
# wait for autolock to kick in
|
||||
time.sleep(10.1)
|
||||
assert debug.wait_layout().main_component() == "Lockscreen"
|
||||
assert debug.read_layout().main_component() == "Lockscreen"
|
||||
with pytest.raises(exceptions.Cancelled):
|
||||
device_handler.result()
|
||||
|
||||
|
||||
def unlock_dry_run(debug: "DebugLink") -> "LayoutContent":
|
||||
assert "Check your backup?" in debug.wait_layout().text_content()
|
||||
layout = go_next(debug, wait=True)
|
||||
assert "Check your backup?" in debug.read_layout().text_content()
|
||||
layout = go_next(debug)
|
||||
assert "PinKeyboard" in layout.all_components()
|
||||
|
||||
layout = debug.input(PIN4, wait=True)
|
||||
layout = debug.input(PIN4)
|
||||
assert layout is not None
|
||||
return layout
|
||||
|
||||
@ -262,20 +262,20 @@ def test_dryrun_locks_at_number_of_words(device_handler: "BackgroundDeviceHandle
|
||||
assert "number of words" in layout.text_content()
|
||||
|
||||
if debug.model == "Safe 3":
|
||||
debug.press_right(wait=True)
|
||||
debug.press_right()
|
||||
|
||||
# wait for autolock to trigger
|
||||
time.sleep(10.1)
|
||||
assert debug.wait_layout().main_component() == "Lockscreen"
|
||||
assert debug.read_layout().main_component() == "Lockscreen"
|
||||
with pytest.raises(exceptions.Cancelled):
|
||||
device_handler.result()
|
||||
|
||||
# unlock
|
||||
# lockscreen triggered automatically
|
||||
debug.wait_layout(wait_for_external_change=True)
|
||||
layout = go_next(debug, wait=True)
|
||||
# debug.wait_layout()
|
||||
layout = go_next(debug)
|
||||
assert "PinKeyboard" in layout.all_components()
|
||||
layout = debug.input(PIN4, wait=True)
|
||||
layout = debug.input(PIN4)
|
||||
assert layout is not None
|
||||
|
||||
# we are back at homescreen
|
||||
@ -295,15 +295,15 @@ def test_dryrun_locks_at_word_entry(device_handler: "BackgroundDeviceHandler"):
|
||||
recovery.select_number_of_words(debug, 20)
|
||||
|
||||
if debug.model == "T":
|
||||
layout = debug.click(buttons.OK, wait=True)
|
||||
layout = debug.click(buttons.OK)
|
||||
assert layout.main_component() == "MnemonicKeyboard"
|
||||
elif debug.model == "Safe 3":
|
||||
layout = debug.press_right(wait=True)
|
||||
layout = debug.press_right()
|
||||
assert "MnemonicKeyboard" in layout.all_components()
|
||||
|
||||
# make sure keyboard locks
|
||||
time.sleep(10.1)
|
||||
assert debug.wait_layout().main_component() == "Lockscreen"
|
||||
assert debug.read_layout().main_component() == "Lockscreen"
|
||||
with pytest.raises(exceptions.Cancelled):
|
||||
device_handler.result()
|
||||
|
||||
@ -321,25 +321,25 @@ def test_dryrun_enter_word_slowly(device_handler: "BackgroundDeviceHandler"):
|
||||
recovery.select_number_of_words(debug, 20)
|
||||
|
||||
if debug.model == "T":
|
||||
layout = debug.click(buttons.OK, wait=True)
|
||||
layout = debug.click(buttons.OK)
|
||||
assert layout.main_component() == "MnemonicKeyboard"
|
||||
|
||||
# type the word OCEAN slowly
|
||||
for coords in buttons.type_word("ocea", is_slip39=True):
|
||||
time.sleep(9)
|
||||
debug.click(coords)
|
||||
layout = debug.click(buttons.CONFIRM_WORD, wait=True)
|
||||
layout = debug.click(buttons.CONFIRM_WORD)
|
||||
# should not have locked, even though we took 9 seconds to type each letter
|
||||
assert layout.main_component() == "MnemonicKeyboard"
|
||||
elif debug.model == "Safe 3":
|
||||
layout = debug.press_right(wait=True)
|
||||
layout = debug.press_right()
|
||||
assert "MnemonicKeyboard" in layout.all_components()
|
||||
|
||||
# pressing middle button three times
|
||||
for _ in range(3):
|
||||
time.sleep(9)
|
||||
debug.press_middle()
|
||||
layout = debug.wait_layout()
|
||||
layout = debug.read_layout()
|
||||
# should not have locked, even though we took 9 seconds to type each letter
|
||||
assert "MnemonicKeyboard" in layout.all_components()
|
||||
|
||||
@ -367,7 +367,7 @@ def test_autolock_does_not_interrupt_preauthorized(
|
||||
coin_name="Testnet",
|
||||
script_type=messages.InputScriptType.SPENDTAPROOT,
|
||||
)
|
||||
debug.press_yes(wait=True)
|
||||
debug.press_yes()
|
||||
device_handler.result()
|
||||
|
||||
inputs = [
|
||||
|
@ -37,17 +37,17 @@ def test_hold_to_lock(device_handler: "BackgroundDeviceHandler"):
|
||||
|
||||
def hold(duration: int, wait: bool = True) -> None:
|
||||
if debug.model == "Safe 3":
|
||||
debug.press_right_htc(hold_ms=duration)
|
||||
debug.press_right(hold_ms=duration)
|
||||
else:
|
||||
debug.input(x=13, y=37, hold_ms=duration, wait=wait)
|
||||
debug.click((13, 37), hold_ms=duration, wait=wait)
|
||||
|
||||
assert device_handler.features().unlocked is False
|
||||
|
||||
# unlock with message
|
||||
device_handler.run(common.get_test_address)
|
||||
|
||||
assert "PinKeyboard" in debug.wait_layout().all_components()
|
||||
debug.input("1234", wait=True)
|
||||
assert "PinKeyboard" in debug.read_layout().all_components()
|
||||
debug.input("1234")
|
||||
assert device_handler.result()
|
||||
|
||||
assert device_handler.features().unlocked is True
|
||||
@ -65,12 +65,11 @@ def test_hold_to_lock(device_handler: "BackgroundDeviceHandler"):
|
||||
# unlock by touching
|
||||
if debug.model == "Safe 3":
|
||||
# Doing a short HTC to simulate a click
|
||||
debug.press_right_htc(hold_ms=100)
|
||||
layout = debug.wait_layout()
|
||||
layout = debug.press_right(hold_ms=100)
|
||||
else:
|
||||
layout = debug.click(buttons.INFO, wait=True)
|
||||
layout = debug.click(buttons.INFO)
|
||||
assert "PinKeyboard" in layout.all_components()
|
||||
debug.input("1234", wait=True)
|
||||
debug.input("1234")
|
||||
|
||||
assert device_handler.features().unlocked is True
|
||||
|
||||
|
@ -88,7 +88,7 @@ def prepare_passphrase_dialogue(
|
||||
) -> Generator["DebugLink", None, None]:
|
||||
debug = device_handler.debuglink()
|
||||
device_handler.run(get_test_address) # type: ignore
|
||||
layout = debug.wait_layout()
|
||||
layout = debug.read_layout()
|
||||
assert "PassphraseKeyboard" in layout.all_components()
|
||||
assert layout.passphrase() == ""
|
||||
assert _current_category(debug) == PassphraseCategory.MENU
|
||||
|
@ -70,7 +70,7 @@ def prepare_passphrase_dialogue(
|
||||
) -> Generator["DebugLink", None, None]:
|
||||
debug = device_handler.debuglink()
|
||||
device_handler.run(get_test_address) # type: ignore
|
||||
assert debug.wait_layout().main_component() == "PassphraseKeyboard"
|
||||
assert debug.read_layout().main_component() == "PassphraseKeyboard"
|
||||
|
||||
# Resetting the category as it could have been changed by previous tests
|
||||
global TT_CATEGORY
|
||||
@ -96,10 +96,10 @@ def go_to_category(debug: "DebugLink", category: PassphraseCategory) -> None:
|
||||
target_index = TT_CATEGORIES.index(category)
|
||||
if target_index > current_index:
|
||||
for _ in range(target_index - current_index):
|
||||
debug.swipe_left(wait=True)
|
||||
debug.swipe_left()
|
||||
else:
|
||||
for _ in range(current_index - target_index):
|
||||
debug.swipe_right(wait=True)
|
||||
debug.swipe_right()
|
||||
TT_CATEGORY = category # type: ignore
|
||||
# Category changed, reset coordinates
|
||||
TT_COORDS_PREV = (0, 0) # type: ignore
|
||||
@ -125,7 +125,7 @@ def press_char(debug: "DebugLink", char: str) -> None:
|
||||
time.sleep(1.1)
|
||||
TT_COORDS_PREV = coords # type: ignore
|
||||
for _ in range(amount):
|
||||
debug.click(coords, wait=True)
|
||||
debug.click(coords)
|
||||
|
||||
|
||||
def input_passphrase(debug: "DebugLink", passphrase: str, check: bool = True) -> None:
|
||||
@ -142,13 +142,13 @@ def input_passphrase(debug: "DebugLink", passphrase: str, check: bool = True) ->
|
||||
def enter_passphrase(debug: "DebugLink") -> None:
|
||||
"""Enter a passphrase"""
|
||||
coords = buttons.pin_passphrase_grid(11)
|
||||
debug.click(coords, wait=True)
|
||||
debug.click(coords)
|
||||
|
||||
|
||||
def delete_char(debug: "DebugLink") -> None:
|
||||
"""Deletes the last char"""
|
||||
coords = buttons.pin_passphrase_grid(9)
|
||||
debug.click(coords, wait=True)
|
||||
debug.click(coords)
|
||||
|
||||
|
||||
VECTORS = ( # passphrase, address
|
||||
@ -185,7 +185,6 @@ def test_passphrase_delete(device_handler: "BackgroundDeviceHandler"):
|
||||
|
||||
for _ in range(4):
|
||||
delete_char(debug)
|
||||
debug.wait_layout()
|
||||
|
||||
input_passphrase(debug, CommonPass.SHORT[8 - 4 :])
|
||||
enter_passphrase(debug)
|
||||
@ -215,7 +214,6 @@ def test_passphrase_loop_all_characters(device_handler: "BackgroundDeviceHandler
|
||||
PassphraseCategory.SPECIAL,
|
||||
):
|
||||
go_to_category(debug, category)
|
||||
debug.wait_layout()
|
||||
|
||||
enter_passphrase(debug)
|
||||
coords = buttons.pin_passphrase_grid(11)
|
||||
|
@ -84,37 +84,35 @@ def prepare(
|
||||
elif situation == Situation.PIN_SETUP:
|
||||
# Set new PIN
|
||||
device_handler.run(device.change_pin) # type: ignore
|
||||
assert "Turn on" in debug.wait_layout().text_content()
|
||||
assert "Turn on" in debug.read_layout().text_content()
|
||||
if debug.model == "T":
|
||||
go_next(debug)
|
||||
elif debug.model == "Safe 3":
|
||||
go_next(debug, wait=True)
|
||||
go_next(debug, wait=True)
|
||||
go_next(debug, wait=True)
|
||||
go_next(debug, wait=True)
|
||||
go_next(debug)
|
||||
go_next(debug)
|
||||
go_next(debug)
|
||||
go_next(debug)
|
||||
elif situation == Situation.PIN_CHANGE:
|
||||
# Change PIN
|
||||
device_handler.run(device.change_pin) # type: ignore
|
||||
_input_see_confirm(debug, old_pin)
|
||||
assert "Change PIN" in debug.read_layout().text_content()
|
||||
go_next(debug, wait=True)
|
||||
go_next(debug)
|
||||
_input_see_confirm(debug, old_pin)
|
||||
elif situation == Situation.WIPE_CODE_SETUP:
|
||||
# Set wipe code
|
||||
device_handler.run(device.change_wipe_code) # type: ignore
|
||||
if old_pin:
|
||||
_input_see_confirm(debug, old_pin)
|
||||
assert "Turn on" in debug.wait_layout().text_content()
|
||||
go_next(debug, wait=True)
|
||||
assert "Turn on" in debug.read_layout().text_content()
|
||||
go_next(debug)
|
||||
if debug.model == "Safe 3":
|
||||
go_next(debug, wait=True)
|
||||
go_next(debug, wait=True)
|
||||
go_next(debug, wait=True)
|
||||
go_next(debug)
|
||||
go_next(debug)
|
||||
go_next(debug)
|
||||
if old_pin:
|
||||
debug.wait_layout()
|
||||
_input_see_confirm(debug, old_pin)
|
||||
|
||||
debug.wait_layout()
|
||||
_assert_pin_entry(debug)
|
||||
yield debug
|
||||
go_next(debug)
|
||||
@ -135,7 +133,7 @@ def _input_pin(debug: "DebugLink", pin: str, check: bool = False) -> None:
|
||||
for digit in pin:
|
||||
digit_index = digits_order.index(digit)
|
||||
coords = buttons.pin_passphrase_index(digit_index)
|
||||
debug.click(coords, wait=True)
|
||||
debug.click(coords)
|
||||
elif debug.model == "Safe 3":
|
||||
for digit in pin:
|
||||
navigate_to_action_and_press(debug, digit, TR_PIN_ACTIONS)
|
||||
@ -148,7 +146,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.model == "T":
|
||||
debug.click(buttons.TOP_ROW, wait=True)
|
||||
debug.click(buttons.TOP_ROW)
|
||||
elif debug.model == "Safe 3":
|
||||
navigate_to_action_and_press(debug, "SHOW", TR_PIN_ACTIONS)
|
||||
|
||||
@ -160,7 +158,7 @@ def _delete_pin(debug: "DebugLink", digits_to_delete: int, check: bool = True) -
|
||||
|
||||
for _ in range(digits_to_delete):
|
||||
if debug.model == "T":
|
||||
debug.click(buttons.pin_passphrase_grid(9), wait=True)
|
||||
debug.click(buttons.pin_passphrase_grid(9))
|
||||
elif debug.model == "Safe 3":
|
||||
navigate_to_action_and_press(debug, "DELETE", TR_PIN_ACTIONS)
|
||||
|
||||
@ -172,7 +170,7 @@ 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.model == "T":
|
||||
debug.click_hold(buttons.pin_passphrase_grid(9), hold_ms=1500)
|
||||
debug.click(buttons.pin_passphrase_grid(9), hold_ms=1500)
|
||||
elif debug.model == "Safe 3":
|
||||
navigate_to_action_and_press(debug, "DELETE", TR_PIN_ACTIONS, hold_ms=1000)
|
||||
|
||||
@ -191,7 +189,7 @@ def _cancel_pin(debug: "DebugLink") -> None:
|
||||
def _confirm_pin(debug: "DebugLink") -> None:
|
||||
"""Navigate to "ENTER" and press it"""
|
||||
if debug.model == "T":
|
||||
debug.click(buttons.pin_passphrase_grid(11), wait=True)
|
||||
debug.click(buttons.pin_passphrase_grid(11))
|
||||
elif debug.model == "Safe 3":
|
||||
navigate_to_action_and_press(debug, "ENTER", TR_PIN_ACTIONS)
|
||||
|
||||
@ -207,7 +205,7 @@ def _enter_two_times(debug: "DebugLink", pin1: str, pin2: str) -> None:
|
||||
|
||||
if debug.model == "Safe 3":
|
||||
# Please re-enter
|
||||
go_next(debug, wait=True)
|
||||
go_next(debug)
|
||||
|
||||
_input_see_confirm(debug, pin2)
|
||||
|
||||
@ -331,7 +329,7 @@ def test_wipe_code_same_as_pin(device_handler: "BackgroundDeviceHandler"):
|
||||
with prepare(device_handler, Situation.WIPE_CODE_SETUP, old_pin="1") as debug:
|
||||
_input_see_confirm(debug, "1")
|
||||
# Try again
|
||||
go_next(debug, wait=True)
|
||||
go_next(debug)
|
||||
_enter_two_times(debug, "2", "2")
|
||||
|
||||
|
||||
|
@ -49,12 +49,12 @@ def prepare_tutorial_and_cancel_after_it(
|
||||
|
||||
|
||||
def go_through_tutorial(debug: "DebugLink") -> None:
|
||||
debug.press_right(wait=True)
|
||||
debug.press_right(wait=True)
|
||||
debug.press_right_htc(hold_ms=1000)
|
||||
debug.press_right(wait=True)
|
||||
debug.press_right(wait=True)
|
||||
layout = debug.press_middle(wait=True)
|
||||
debug.press_right()
|
||||
debug.press_right()
|
||||
debug.press_right(hold_ms=1000)
|
||||
debug.press_right()
|
||||
debug.press_right()
|
||||
layout = debug.press_middle()
|
||||
assert layout.title() == "TUTORIAL COMPLETE"
|
||||
|
||||
|
||||
@ -65,15 +65,15 @@ def test_tutorial_finish(device_handler: "BackgroundDeviceHandler"):
|
||||
go_through_tutorial(debug)
|
||||
|
||||
# FINISH
|
||||
debug.press_right(wait=True)
|
||||
debug.press_right()
|
||||
|
||||
|
||||
@pytest.mark.setup_client(uninitialized=True)
|
||||
def test_tutorial_skip(device_handler: "BackgroundDeviceHandler"):
|
||||
with prepare_tutorial_and_cancel_after_it(device_handler, cancelled=True) as debug:
|
||||
# SKIP
|
||||
debug.press_left(wait=True)
|
||||
debug.press_right(wait=True)
|
||||
debug.press_left()
|
||||
debug.press_right()
|
||||
|
||||
|
||||
@pytest.mark.setup_client(uninitialized=True)
|
||||
@ -83,8 +83,8 @@ def test_tutorial_again_and_skip(device_handler: "BackgroundDeviceHandler"):
|
||||
go_through_tutorial(debug)
|
||||
|
||||
# AGAIN
|
||||
debug.press_left(wait=True)
|
||||
debug.press_left()
|
||||
|
||||
# SKIP
|
||||
debug.press_left(wait=True)
|
||||
debug.press_right(wait=True)
|
||||
debug.press_left()
|
||||
debug.press_right()
|
||||
|
@ -188,10 +188,8 @@ def read_and_confirm_mnemonic_tt(
|
||||
br = yield
|
||||
assert br.pages is not None
|
||||
|
||||
debug.wait_layout()
|
||||
|
||||
for i in range(br.pages):
|
||||
words = debug.wait_layout().seed_words()
|
||||
words = debug.read_layout().seed_words()
|
||||
mnemonic.extend(words)
|
||||
# Not swiping on the last page
|
||||
if i < br.pages - 1:
|
||||
@ -201,7 +199,9 @@ def read_and_confirm_mnemonic_tt(
|
||||
|
||||
# check share
|
||||
for _ in range(3):
|
||||
word_pos = int(debug.wait_layout().text_content().split()[2])
|
||||
text_content = debug.read_layout().text_content()
|
||||
assert text_content.startswith("Select word ")
|
||||
word_pos = int(text_content.split()[2])
|
||||
index = word_pos - 1
|
||||
if choose_wrong:
|
||||
debug.input(mnemonic[(index + 1) % len(mnemonic)])
|
||||
@ -221,7 +221,7 @@ def read_and_confirm_mnemonic_tr(
|
||||
br = yield
|
||||
assert br.pages is not None
|
||||
for _ in range(br.pages - 1):
|
||||
layout = debug.wait_layout()
|
||||
layout = debug.read_layout()
|
||||
words = layout.seed_words()
|
||||
mnemonic.extend(words)
|
||||
debug.press_right()
|
||||
@ -232,7 +232,7 @@ def read_and_confirm_mnemonic_tr(
|
||||
|
||||
# check share
|
||||
for _ in range(3):
|
||||
word_pos_match = re.search(r"\d+", debug.wait_layout().title())
|
||||
word_pos_match = re.search(r"\d+", debug.read_layout().title())
|
||||
assert word_pos_match is not None
|
||||
word_pos = int(word_pos_match.group(0))
|
||||
index = word_pos - 1
|
||||
@ -248,8 +248,8 @@ def read_and_confirm_mnemonic_tr(
|
||||
def click_info_button_tt(debug: "DebugLink"):
|
||||
"""Click Shamir backup info button and return back."""
|
||||
debug.press_info()
|
||||
yield # Info screen with text
|
||||
debug.press_yes()
|
||||
yield
|
||||
|
||||
|
||||
def check_pin_backoff_time(attempts: int, start: float) -> None:
|
||||
|
@ -46,6 +46,8 @@ HERE = Path(__file__).resolve().parent
|
||||
|
||||
# So that we see details of failed asserts from this module
|
||||
pytest.register_assert_rewrite("tests.common")
|
||||
pytest.register_assert_rewrite("tests.input_flows")
|
||||
pytest.register_assert_rewrite("tests.input_flows_helpers")
|
||||
|
||||
|
||||
def _emulator_wrapper_main_args() -> list[str]:
|
||||
|
@ -31,7 +31,7 @@ pytestmark = [
|
||||
|
||||
def show_details_input_flow(client: Client):
|
||||
yield
|
||||
client.debug.wait_layout()
|
||||
client.debug.read_layout()
|
||||
# Clicking for model T, pressing right for model R
|
||||
if client.features.model == "T":
|
||||
SHOW_ALL_BUTTON_POSITION = (143, 167)
|
||||
|
@ -63,17 +63,23 @@ def test_busy_state(client: Client):
|
||||
|
||||
@pytest.mark.flaky(max_runs=5)
|
||||
def test_busy_expiry(client: Client):
|
||||
WAIT_TIME_MS = 1500
|
||||
TOLERANCE = 1000
|
||||
|
||||
_assert_busy(client, False)
|
||||
# Start a timer
|
||||
start = time.monotonic()
|
||||
# Show the busy dialog.
|
||||
device.set_busy(client, expiry_ms=1500)
|
||||
device.set_busy(client, expiry_ms=WAIT_TIME_MS)
|
||||
_assert_busy(client, True)
|
||||
|
||||
# Hasn't expired yet.
|
||||
time.sleep(0.1)
|
||||
_assert_busy(client, True)
|
||||
# Wait until the layout changes
|
||||
client.debug.wait_layout()
|
||||
end = time.monotonic()
|
||||
|
||||
# Wait for it to expire. Add some tolerance to account for CI/hardware slowness.
|
||||
time.sleep(4.0)
|
||||
# Check that the busy dialog was shown for at least WAIT_TIME_MS.
|
||||
duration = (end - start) * 1000
|
||||
assert WAIT_TIME_MS <= duration <= WAIT_TIME_MS + TOLERANCE
|
||||
|
||||
# Check that the device is no longer busy.
|
||||
# Also needs to come back to Homescreen (for UI tests).
|
||||
|
@ -49,7 +49,7 @@ def test_sd_no_format(client: Client):
|
||||
@pytest.mark.sd_card
|
||||
@pytest.mark.setup_client(pin="1234")
|
||||
def test_sd_protect_unlock(client: Client):
|
||||
layout = client.debug.wait_layout
|
||||
layout = client.debug.read_layout
|
||||
|
||||
def input_flow_enable_sd_protect():
|
||||
yield # Enter PIN to unlock device
|
||||
|
@ -395,7 +395,7 @@ def test_hide_passphrase_from_host(client: Client):
|
||||
|
||||
def input_flow():
|
||||
yield
|
||||
layout = client.debug.wait_layout()
|
||||
layout = client.debug.read_layout()
|
||||
if client.debug.model == "T":
|
||||
assert (
|
||||
"Passphrase provided by host will be used but will not be displayed due to the device settings."
|
||||
@ -403,7 +403,7 @@ def test_hide_passphrase_from_host(client: Client):
|
||||
)
|
||||
client.debug.press_yes()
|
||||
elif client.debug.model == "Safe 3":
|
||||
layout = client.debug.wait_layout()
|
||||
layout = client.debug.read_layout()
|
||||
assert "will not be displayed" in layout.text_content()
|
||||
client.debug.press_right()
|
||||
client.debug.press_right()
|
||||
@ -433,12 +433,12 @@ def test_hide_passphrase_from_host(client: Client):
|
||||
|
||||
def input_flow():
|
||||
yield
|
||||
layout = client.debug.wait_layout()
|
||||
layout = client.debug.read_layout()
|
||||
assert "Next screen will show the passphrase" in layout.text_content()
|
||||
client.debug.press_yes()
|
||||
|
||||
yield
|
||||
layout = client.debug.wait_layout()
|
||||
layout = client.debug.read_layout()
|
||||
assert "confirm passphrase" in layout.title().lower()
|
||||
|
||||
assert passphrase in layout.text_content()
|
||||
|
@ -75,16 +75,16 @@ class InputFlowBase:
|
||||
raise NotImplementedError
|
||||
|
||||
def text_content(self) -> str:
|
||||
return self.debug.wait_layout().text_content()
|
||||
return self.debug.read_layout().text_content()
|
||||
|
||||
def main_component(self) -> str:
|
||||
return self.debug.wait_layout().main_component()
|
||||
return self.debug.read_layout().main_component()
|
||||
|
||||
def all_components(self) -> list[str]:
|
||||
return self.debug.wait_layout().all_components()
|
||||
return self.debug.read_layout().all_components()
|
||||
|
||||
def title(self) -> str:
|
||||
return self.debug.wait_layout().title()
|
||||
return self.debug.read_layout().title()
|
||||
|
||||
|
||||
class InputFlowSetupDevicePINWIpeCode(InputFlowBase):
|
||||
@ -215,13 +215,13 @@ class InputFlowSignMessagePagination(InputFlowBase):
|
||||
layouts: list[LayoutContent] = []
|
||||
|
||||
br = yield # confirm address
|
||||
self.debug.wait_layout()
|
||||
self.debug.read_layout()
|
||||
self.debug.press_yes()
|
||||
|
||||
br = yield
|
||||
assert br.pages is not None
|
||||
for i in range(br.pages):
|
||||
layout = self.debug.wait_layout()
|
||||
layout = self.debug.read_layout()
|
||||
layouts.append(layout)
|
||||
|
||||
if i < br.pages - 1:
|
||||
@ -261,9 +261,9 @@ class InputFlowSignMessageInfo(InputFlowBase):
|
||||
def input_flow_tt(self) -> BRGeneratorType:
|
||||
yield
|
||||
# show address/message info
|
||||
self.debug.click(buttons.CORNER_BUTTON, wait=True)
|
||||
self.debug.click(buttons.CORNER_BUTTON, wait=True)
|
||||
self.debug.press_no(wait=True)
|
||||
self.debug.click(buttons.CORNER_BUTTON)
|
||||
self.debug.click(buttons.CORNER_BUTTON)
|
||||
self.debug.press_no()
|
||||
self.debug.synchronize_at("mismatch")
|
||||
# address mismatch?
|
||||
self.debug.press_no()
|
||||
@ -272,8 +272,8 @@ class InputFlowSignMessageInfo(InputFlowBase):
|
||||
yield
|
||||
self.debug.press_no()
|
||||
yield
|
||||
self.debug.press_no(wait=True)
|
||||
self.debug.press_yes(wait=True)
|
||||
self.debug.press_no()
|
||||
self.debug.press_yes()
|
||||
|
||||
|
||||
class InputFlowShowAddressQRCode(InputFlowBase):
|
||||
@ -282,16 +282,16 @@ class InputFlowShowAddressQRCode(InputFlowBase):
|
||||
|
||||
def input_flow_tt(self) -> BRGeneratorType:
|
||||
yield
|
||||
self.debug.click(buttons.CORNER_BUTTON, wait=True)
|
||||
self.debug.click(buttons.CORNER_BUTTON)
|
||||
# synchronize; TODO get rid of this once we have single-global-layout
|
||||
self.debug.synchronize_at("SimplePage")
|
||||
|
||||
self.debug.swipe_left(wait=True)
|
||||
self.debug.swipe_right(wait=True)
|
||||
self.debug.swipe_left(wait=True)
|
||||
self.debug.click(buttons.CORNER_BUTTON, wait=True)
|
||||
self.debug.press_no(wait=True)
|
||||
self.debug.press_no(wait=True)
|
||||
self.debug.swipe_left()
|
||||
self.debug.swipe_right()
|
||||
self.debug.swipe_left()
|
||||
self.debug.click(buttons.CORNER_BUTTON)
|
||||
self.debug.press_no()
|
||||
self.debug.press_no()
|
||||
self.debug.press_yes()
|
||||
|
||||
def input_flow_tr(self) -> BRGeneratorType:
|
||||
@ -322,13 +322,13 @@ class InputFlowShowAddressQRCodeCancel(InputFlowBase):
|
||||
|
||||
def input_flow_tt(self) -> BRGeneratorType:
|
||||
yield
|
||||
self.debug.click(buttons.CORNER_BUTTON, wait=True)
|
||||
self.debug.click(buttons.CORNER_BUTTON)
|
||||
# synchronize; TODO get rid of this once we have single-global-layout
|
||||
self.debug.synchronize_at("SimplePage")
|
||||
|
||||
self.debug.swipe_left(wait=True)
|
||||
self.debug.click(buttons.CORNER_BUTTON, wait=True)
|
||||
self.debug.press_no(wait=True)
|
||||
self.debug.swipe_left()
|
||||
self.debug.click(buttons.CORNER_BUTTON)
|
||||
self.debug.press_no()
|
||||
self.debug.press_yes()
|
||||
|
||||
def input_flow_tr(self) -> BRGeneratorType:
|
||||
@ -357,14 +357,14 @@ class InputFlowShowMultisigXPUBs(InputFlowBase):
|
||||
self.debug.press_yes()
|
||||
|
||||
yield # show address
|
||||
layout = self.debug.wait_layout()
|
||||
layout = self.debug.read_layout()
|
||||
assert "RECEIVE ADDRESS\n(MULTISIG)" == layout.title()
|
||||
assert layout.text_content().replace(" ", "") == self.address
|
||||
|
||||
self.debug.click(buttons.CORNER_BUTTON)
|
||||
assert "Qr" in self.all_components()
|
||||
|
||||
layout = self.debug.swipe_left(wait=True)
|
||||
layout = self.debug.swipe_left()
|
||||
# address details
|
||||
assert "Multisig 2 of 3" in layout.screen_content()
|
||||
assert "Derivation path:" in layout.screen_content()
|
||||
@ -374,16 +374,16 @@ class InputFlowShowMultisigXPUBs(InputFlowBase):
|
||||
expected_title = f"MULTISIG XPUB #{xpub_num + 1}\n" + (
|
||||
"(YOURS)" if self.index == xpub_num else "(COSIGNER)"
|
||||
)
|
||||
layout = self.debug.swipe_left(wait=True)
|
||||
layout = self.debug.swipe_left()
|
||||
assert expected_title == layout.title()
|
||||
content = layout.text_content().replace(" ", "")
|
||||
assert self.xpubs[xpub_num] in content
|
||||
|
||||
self.debug.click(buttons.CORNER_BUTTON, wait=True)
|
||||
self.debug.click(buttons.CORNER_BUTTON)
|
||||
# show address
|
||||
self.debug.press_no(wait=True)
|
||||
self.debug.press_no()
|
||||
# address mismatch
|
||||
self.debug.press_no(wait=True)
|
||||
self.debug.press_no()
|
||||
# show address
|
||||
self.debug.press_yes()
|
||||
|
||||
@ -392,14 +392,14 @@ class InputFlowShowMultisigXPUBs(InputFlowBase):
|
||||
self.debug.press_middle()
|
||||
|
||||
yield # show address
|
||||
layout = self.debug.wait_layout()
|
||||
layout = self.debug.read_layout()
|
||||
assert "RECEIVE ADDRESS (MULTISIG)" in layout.title()
|
||||
assert layout.text_content().replace(" ", "") == self.address
|
||||
|
||||
self.debug.press_right()
|
||||
assert "Qr" in self.all_components()
|
||||
|
||||
layout = self.debug.press_right(wait=True)
|
||||
layout = self.debug.press_right()
|
||||
# address details
|
||||
# TODO: locate it more precisely
|
||||
assert "Multisig 2 of 3" in layout.json_str
|
||||
@ -409,14 +409,14 @@ class InputFlowShowMultisigXPUBs(InputFlowBase):
|
||||
expected_title = f"MULTISIG XPUB #{xpub_num + 1} " + (
|
||||
"(YOURS)" if self.index == xpub_num else "(COSIGNER)"
|
||||
)
|
||||
layout = self.debug.press_right(wait=True)
|
||||
layout = self.debug.press_right()
|
||||
assert expected_title in layout.title()
|
||||
xpub_part_1 = layout.text_content().replace(" ", "")
|
||||
# Press "SHOW MORE"
|
||||
layout = self.debug.press_middle(wait=True)
|
||||
layout = self.debug.press_middle()
|
||||
xpub_part_2 = layout.text_content().replace(" ", "")
|
||||
# Go back
|
||||
self.debug.press_left(wait=True)
|
||||
self.debug.press_left()
|
||||
assert self.xpubs[xpub_num] == xpub_part_1 + xpub_part_2
|
||||
|
||||
for _ in range(5):
|
||||
@ -442,23 +442,23 @@ class InputFlowShowXpubQRCode(InputFlowBase):
|
||||
self.debug.press_yes()
|
||||
|
||||
br = yield
|
||||
layout = self.debug.wait_layout()
|
||||
layout = self.debug.read_layout()
|
||||
if "coinjoin" in layout.title().lower() or br.code == B.UnknownDerivationPath:
|
||||
self.debug.press_yes()
|
||||
br = yield
|
||||
|
||||
self.debug.click(buttons.CORNER_BUTTON, wait=True)
|
||||
self.debug.click(buttons.CORNER_BUTTON)
|
||||
# synchronize; TODO get rid of this once we have single-global-layout
|
||||
self.debug.synchronize_at("SimplePage")
|
||||
|
||||
self.debug.swipe_left(wait=True)
|
||||
self.debug.swipe_right(wait=True)
|
||||
self.debug.swipe_left(wait=True)
|
||||
self.debug.click(buttons.CORNER_BUTTON, wait=True)
|
||||
self.debug.press_no(wait=True)
|
||||
self.debug.press_no(wait=True)
|
||||
self.debug.swipe_left()
|
||||
self.debug.swipe_right()
|
||||
self.debug.swipe_left()
|
||||
self.debug.click(buttons.CORNER_BUTTON)
|
||||
self.debug.press_no()
|
||||
self.debug.press_no()
|
||||
for _ in range(br.pages - 1):
|
||||
self.debug.swipe_up(wait=True)
|
||||
self.debug.swipe_up()
|
||||
self.debug.press_yes()
|
||||
|
||||
def input_flow_tr(self) -> BRGeneratorType:
|
||||
@ -469,18 +469,18 @@ class InputFlowShowXpubQRCode(InputFlowBase):
|
||||
self.debug.press_right()
|
||||
|
||||
br = yield
|
||||
layout = self.debug.wait_layout()
|
||||
layout = self.debug.read_layout()
|
||||
if "coinjoin" in layout.title().lower() or br.code == B.UnknownDerivationPath:
|
||||
self.debug.press_yes()
|
||||
br = yield
|
||||
|
||||
# Go into details
|
||||
self.debug.press_right(wait=True)
|
||||
self.debug.press_right()
|
||||
# Go through details and back
|
||||
self.debug.press_right(wait=True)
|
||||
self.debug.press_right(wait=True)
|
||||
self.debug.press_left(wait=True)
|
||||
self.debug.press_left(wait=True)
|
||||
self.debug.press_right()
|
||||
self.debug.press_right()
|
||||
self.debug.press_left()
|
||||
self.debug.press_left()
|
||||
assert br.pages is not None
|
||||
for _ in range(br.pages - 1):
|
||||
self.debug.press_right()
|
||||
@ -495,21 +495,21 @@ class InputFlowPaymentRequestDetails(InputFlowBase):
|
||||
|
||||
def input_flow_tt(self) -> BRGeneratorType:
|
||||
yield # request to see details
|
||||
self.debug.wait_layout()
|
||||
self.debug.read_layout()
|
||||
self.debug.press_info()
|
||||
|
||||
yield # confirm first output
|
||||
assert self.outputs[0].address[:16] in self.text_content() # type: ignore
|
||||
self.debug.press_yes()
|
||||
yield # confirm first output
|
||||
self.debug.wait_layout()
|
||||
self.debug.read_layout()
|
||||
self.debug.press_yes()
|
||||
|
||||
yield # confirm second output
|
||||
assert self.outputs[1].address[:16] in self.text_content() # type: ignore
|
||||
self.debug.press_yes()
|
||||
yield # confirm second output
|
||||
self.debug.wait_layout()
|
||||
self.debug.read_layout()
|
||||
self.debug.press_yes()
|
||||
|
||||
yield # confirm transaction
|
||||
@ -543,20 +543,20 @@ class InputFlowSignTxHighFee(InputFlowBase):
|
||||
|
||||
def sign_tx_go_to_info(client: Client) -> Generator[None, None, str]:
|
||||
yield # confirm output
|
||||
client.debug.wait_layout()
|
||||
client.debug.read_layout()
|
||||
client.debug.press_yes()
|
||||
yield # confirm output
|
||||
client.debug.wait_layout()
|
||||
client.debug.read_layout()
|
||||
client.debug.press_yes()
|
||||
|
||||
yield # confirm transaction
|
||||
client.debug.wait_layout()
|
||||
client.debug.read_layout()
|
||||
client.debug.press_info()
|
||||
|
||||
layout = client.debug.wait_layout()
|
||||
layout = client.debug.read_layout()
|
||||
content = layout.text_content().lower()
|
||||
|
||||
client.debug.click(buttons.CORNER_BUTTON, wait=True)
|
||||
client.debug.click(buttons.CORNER_BUTTON)
|
||||
|
||||
return content
|
||||
|
||||
@ -565,24 +565,24 @@ def sign_tx_go_to_info_tr(
|
||||
client: Client,
|
||||
) -> Generator[None, None, str]:
|
||||
yield # confirm address
|
||||
client.debug.wait_layout()
|
||||
client.debug.read_layout()
|
||||
client.debug.press_yes() # CONTINUE
|
||||
yield # confirm amount
|
||||
client.debug.wait_layout()
|
||||
client.debug.read_layout()
|
||||
client.debug.press_yes() # CONFIRM
|
||||
|
||||
screen_texts: list[str] = []
|
||||
|
||||
yield # confirm total
|
||||
layout = client.debug.wait_layout()
|
||||
layout = client.debug.read_layout()
|
||||
if "multiple accounts" in layout.text_content().lower():
|
||||
client.debug.press_middle()
|
||||
yield
|
||||
|
||||
layout = client.debug.press_right(wait=True)
|
||||
layout = client.debug.press_right()
|
||||
screen_texts.append(layout.text_content())
|
||||
|
||||
layout = client.debug.press_right(wait=True)
|
||||
layout = client.debug.press_right()
|
||||
screen_texts.append(layout.text_content())
|
||||
|
||||
client.debug.press_left()
|
||||
@ -660,15 +660,16 @@ class InputFlowSignTxInformationReplacement(InputFlowBase):
|
||||
yield # confirm address
|
||||
self.debug.press_yes()
|
||||
# go back to address
|
||||
yield
|
||||
self.debug.press_no()
|
||||
# confirm address
|
||||
self.debug.press_yes()
|
||||
yield # confirm amount
|
||||
# confirm amount
|
||||
self.debug.press_yes()
|
||||
|
||||
yield # transaction summary, press info
|
||||
self.debug.click(buttons.CORNER_BUTTON, wait=True)
|
||||
self.debug.click(buttons.CORNER_BUTTON, wait=True)
|
||||
self.debug.click(buttons.CORNER_BUTTON)
|
||||
self.debug.click(buttons.CORNER_BUTTON)
|
||||
self.debug.press_yes()
|
||||
|
||||
def input_flow_tr(self) -> BRGeneratorType:
|
||||
@ -691,10 +692,10 @@ def lock_time_input_flow_tt(
|
||||
double_confirm: bool = False,
|
||||
) -> BRGeneratorType:
|
||||
yield # confirm output
|
||||
debug.wait_layout()
|
||||
debug.read_layout()
|
||||
debug.press_yes()
|
||||
yield # confirm output
|
||||
debug.wait_layout()
|
||||
debug.read_layout()
|
||||
debug.press_yes()
|
||||
|
||||
yield # confirm locktime
|
||||
@ -712,10 +713,10 @@ def lock_time_input_flow_tr(
|
||||
debug: DebugLink, layout_assert_func: Callable[[DebugLink], None]
|
||||
) -> BRGeneratorType:
|
||||
yield # confirm address
|
||||
debug.wait_layout()
|
||||
debug.read_layout()
|
||||
debug.press_yes()
|
||||
yield # confirm amount
|
||||
debug.wait_layout()
|
||||
debug.read_layout()
|
||||
debug.press_yes()
|
||||
|
||||
yield # confirm locktime
|
||||
@ -732,7 +733,7 @@ class InputFlowLockTimeBlockHeight(InputFlowBase):
|
||||
self.block_height = block_height
|
||||
|
||||
def assert_func(self, debug: DebugLink) -> None:
|
||||
layout_text = debug.wait_layout().text_content()
|
||||
layout_text = debug.read_layout().text_content()
|
||||
assert "blockheight" in layout_text
|
||||
assert self.block_height in layout_text
|
||||
|
||||
@ -751,7 +752,7 @@ class InputFlowLockTimeDatetime(InputFlowBase):
|
||||
self.lock_time_str = lock_time_str
|
||||
|
||||
def assert_func(self, debug: DebugLink):
|
||||
layout_text = debug.wait_layout().text_content()
|
||||
layout_text = debug.read_layout().text_content()
|
||||
assert "Locktime" in layout_text
|
||||
assert self.lock_time_str in layout_text
|
||||
|
||||
@ -782,7 +783,7 @@ class InputFlowEIP712ShowMore(InputFlowBase):
|
||||
self.debug.press_yes()
|
||||
|
||||
yield # confirm domain
|
||||
self.debug.wait_layout()
|
||||
self.debug.read_layout()
|
||||
self._confirm_show_more()
|
||||
|
||||
# confirm domain properties
|
||||
@ -791,11 +792,11 @@ class InputFlowEIP712ShowMore(InputFlowBase):
|
||||
self.debug.press_yes()
|
||||
|
||||
yield # confirm message
|
||||
self.debug.wait_layout()
|
||||
self.debug.read_layout()
|
||||
self._confirm_show_more()
|
||||
|
||||
yield # confirm message.from
|
||||
self.debug.wait_layout()
|
||||
self.debug.read_layout()
|
||||
self._confirm_show_more()
|
||||
|
||||
# confirm message.from properties
|
||||
@ -804,7 +805,7 @@ class InputFlowEIP712ShowMore(InputFlowBase):
|
||||
self.debug.press_yes()
|
||||
|
||||
yield # confirm message.to
|
||||
self.debug.wait_layout()
|
||||
self.debug.read_layout()
|
||||
self._confirm_show_more()
|
||||
|
||||
# confirm message.to properties
|
||||
@ -1023,15 +1024,15 @@ class InputFlowSlip39BasicBackup(InputFlowBase):
|
||||
def input_flow_tt(self) -> BRGeneratorType:
|
||||
yield # 1. Checklist
|
||||
self.debug.press_yes()
|
||||
yield # 2. Number of shares (5)
|
||||
if self.click_info:
|
||||
yield from click_info_button_tt(self.debug)
|
||||
yield # 2. Number of shares (5)
|
||||
self.debug.press_yes()
|
||||
yield # 3. Checklist
|
||||
self.debug.press_yes()
|
||||
yield # 4. Threshold (3)
|
||||
if self.click_info:
|
||||
yield from click_info_button_tt(self.debug)
|
||||
yield # 4. Threshold (3)
|
||||
self.debug.press_yes()
|
||||
yield # 5. Checklist
|
||||
self.debug.press_yes()
|
||||
@ -1151,26 +1152,26 @@ class InputFlowSlip39AdvancedBackup(InputFlowBase):
|
||||
def input_flow_tt(self) -> BRGeneratorType:
|
||||
yield # 1. Checklist
|
||||
self.debug.press_yes()
|
||||
yield # 2. Set and confirm group count
|
||||
if self.click_info:
|
||||
yield from click_info_button_tt(self.debug)
|
||||
yield # 2. Set and confirm group count
|
||||
self.debug.press_yes()
|
||||
yield # 3. Checklist
|
||||
self.debug.press_yes()
|
||||
yield # 4. Set and confirm group threshold
|
||||
if self.click_info:
|
||||
yield from click_info_button_tt(self.debug)
|
||||
yield # 4. Set and confirm group threshold
|
||||
self.debug.press_yes()
|
||||
yield # 5. Checklist
|
||||
self.debug.press_yes()
|
||||
for _ in range(5): # for each of 5 groups
|
||||
if self.click_info:
|
||||
yield from click_info_button_tt(self.debug)
|
||||
yield # Set & Confirm number of shares
|
||||
self.debug.press_yes()
|
||||
if self.click_info:
|
||||
yield from click_info_button_tt(self.debug)
|
||||
self.debug.press_yes()
|
||||
yield # Set & confirm share threshold value
|
||||
if self.click_info:
|
||||
yield from click_info_button_tt(self.debug)
|
||||
self.debug.press_yes()
|
||||
yield # Confirm show seeds
|
||||
self.debug.press_yes()
|
||||
|
@ -15,14 +15,14 @@ class PinFlow:
|
||||
self, pin: str, second_different_pin: str | None = None
|
||||
) -> BRGeneratorType:
|
||||
yield # Enter PIN
|
||||
assert "PinKeyboard" in self.debug.wait_layout().all_components()
|
||||
assert "PinKeyboard" in self.debug.read_layout().all_components()
|
||||
self.debug.input(pin)
|
||||
if self.debug.model == "Safe 3":
|
||||
yield # Reenter PIN
|
||||
assert "re-enter PIN" in self.debug.wait_layout().text_content()
|
||||
assert "re-enter PIN" in self.debug.read_layout().text_content()
|
||||
self.debug.press_yes()
|
||||
yield # Enter PIN again
|
||||
assert "PinKeyboard" in self.debug.wait_layout().all_components()
|
||||
assert "PinKeyboard" in self.debug.read_layout().all_components()
|
||||
if second_different_pin is not None:
|
||||
self.debug.input(second_different_pin)
|
||||
else:
|
||||
@ -36,7 +36,7 @@ class BackupFlow:
|
||||
|
||||
def confirm_new_wallet(self) -> BRGeneratorType:
|
||||
yield
|
||||
assert "By continuing you agree" in self.debug.wait_layout().text_content()
|
||||
assert "By continuing you agree" in self.debug.read_layout().text_content()
|
||||
if self.debug.model == "Safe 3":
|
||||
self.debug.press_right()
|
||||
self.debug.press_yes()
|
||||
@ -49,14 +49,14 @@ class RecoveryFlow:
|
||||
|
||||
def confirm_recovery(self) -> BRGeneratorType:
|
||||
yield
|
||||
assert "By continuing you agree" in self.debug.wait_layout().text_content()
|
||||
assert "By continuing you agree" in self.debug.read_layout().text_content()
|
||||
if self.debug.model == "Safe 3":
|
||||
self.debug.press_right()
|
||||
self.debug.press_yes()
|
||||
|
||||
def confirm_dry_run(self) -> BRGeneratorType:
|
||||
yield
|
||||
assert "Check your backup" in self.debug.wait_layout().text_content()
|
||||
assert "Check your backup" in self.debug.read_layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
def setup_slip39_recovery(self, num_words: int) -> BRGeneratorType:
|
||||
@ -73,43 +73,43 @@ class RecoveryFlow:
|
||||
|
||||
def tr_recovery_homescreen(self) -> BRGeneratorType:
|
||||
yield
|
||||
assert "number of words" in self.debug.wait_layout().text_content()
|
||||
assert "number of words" in self.debug.read_layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
def enter_your_backup(self) -> BRGeneratorType:
|
||||
yield
|
||||
assert "Enter your backup" in self.debug.wait_layout().text_content()
|
||||
assert "Enter your backup" in self.debug.read_layout().text_content()
|
||||
if (
|
||||
self.debug.model == "Safe 3"
|
||||
and "BACKUP CHECK" not in self.debug.wait_layout().title()
|
||||
and "BACKUP CHECK" not in self.debug.read_layout().title()
|
||||
):
|
||||
# Normal recovery has extra info (not dry run)
|
||||
self.debug.press_right(wait=True)
|
||||
self.debug.press_right(wait=True)
|
||||
self.debug.press_right()
|
||||
self.debug.press_right()
|
||||
self.debug.press_yes()
|
||||
|
||||
def enter_any_share(self) -> BRGeneratorType:
|
||||
yield
|
||||
assert "Enter any share" in self.debug.wait_layout().text_content()
|
||||
assert "Enter any share" in self.debug.read_layout().text_content()
|
||||
if (
|
||||
self.debug.model == "Safe 3"
|
||||
and "BACKUP CHECK" not in self.debug.wait_layout().title()
|
||||
and "BACKUP CHECK" not in self.debug.read_layout().title()
|
||||
):
|
||||
# Normal recovery has extra info (not dry run)
|
||||
self.debug.press_right(wait=True)
|
||||
self.debug.press_right(wait=True)
|
||||
self.debug.press_right()
|
||||
self.debug.press_right()
|
||||
self.debug.press_yes()
|
||||
|
||||
def abort_recovery(self, confirm: bool) -> BRGeneratorType:
|
||||
yield
|
||||
if self.debug.model == "Safe 3":
|
||||
assert "number of words" in self.debug.wait_layout().text_content()
|
||||
assert "number of words" in self.debug.read_layout().text_content()
|
||||
else:
|
||||
assert "Enter any share" in self.debug.wait_layout().text_content()
|
||||
assert "Enter any share" in self.debug.read_layout().text_content()
|
||||
self.debug.press_no()
|
||||
|
||||
yield
|
||||
assert "cancel the recovery" in self.debug.wait_layout().text_content()
|
||||
assert "cancel the recovery" in self.debug.read_layout().text_content()
|
||||
if self.debug.model == "Safe 3":
|
||||
self.debug.press_right()
|
||||
if confirm:
|
||||
@ -121,33 +121,33 @@ class RecoveryFlow:
|
||||
br = yield
|
||||
assert br.code == B.MnemonicWordCount
|
||||
if self.debug.model == "Safe 3":
|
||||
assert "NUMBER OF WORDS" in self.debug.wait_layout().title()
|
||||
assert "NUMBER OF WORDS" in self.debug.read_layout().title()
|
||||
else:
|
||||
assert "number of words" in self.debug.wait_layout().text_content()
|
||||
assert "number of words" in self.debug.read_layout().text_content()
|
||||
self.debug.input(str(num_words))
|
||||
|
||||
def warning_invalid_recovery_seed(self) -> BRGeneratorType:
|
||||
br = yield
|
||||
assert br.code == B.Warning
|
||||
assert "Invalid recovery seed" in self.debug.wait_layout().text_content()
|
||||
assert "Invalid recovery seed" in self.debug.read_layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
def warning_invalid_recovery_share(self) -> BRGeneratorType:
|
||||
br = yield
|
||||
assert br.code == B.Warning
|
||||
assert "Invalid recovery share" in self.debug.wait_layout().text_content()
|
||||
assert "Invalid recovery share" in self.debug.read_layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
def warning_group_threshold_reached(self) -> BRGeneratorType:
|
||||
br = yield
|
||||
assert br.code == B.Warning
|
||||
assert "Group threshold reached" in self.debug.wait_layout().text_content()
|
||||
assert "Group threshold reached" in self.debug.read_layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
def warning_share_already_entered(self) -> BRGeneratorType:
|
||||
br = yield
|
||||
assert br.code == B.Warning
|
||||
assert "Share already entered" in self.debug.wait_layout().text_content()
|
||||
assert "Share already entered" in self.debug.read_layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
def warning_share_from_another_shamir(self) -> BRGeneratorType:
|
||||
@ -155,46 +155,46 @@ class RecoveryFlow:
|
||||
assert br.code == B.Warning
|
||||
assert (
|
||||
"You have entered a share from another Shamir Backup"
|
||||
in self.debug.wait_layout().text_content()
|
||||
in self.debug.read_layout().text_content()
|
||||
)
|
||||
self.debug.press_yes()
|
||||
|
||||
def success_share_group_entered(self) -> BRGeneratorType:
|
||||
yield
|
||||
assert "You have entered" in self.debug.wait_layout().text_content()
|
||||
assert "Group" in self.debug.wait_layout().text_content()
|
||||
assert "You have entered" in self.debug.read_layout().text_content()
|
||||
assert "Group" in self.debug.read_layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
def success_wallet_recovered(self) -> BRGeneratorType:
|
||||
br = yield
|
||||
assert br.code == B.Success
|
||||
assert (
|
||||
"Wallet recovered successfully" in self.debug.wait_layout().text_content()
|
||||
"Wallet recovered successfully" in self.debug.read_layout().text_content()
|
||||
)
|
||||
self.debug.press_yes()
|
||||
|
||||
def success_bip39_dry_run_valid(self) -> BRGeneratorType:
|
||||
br = yield
|
||||
assert br.code == B.Success
|
||||
assert "recovery seed is valid" in self.debug.wait_layout().text_content()
|
||||
assert "recovery seed is valid" in self.debug.read_layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
def success_slip39_dryrun_valid(self) -> BRGeneratorType:
|
||||
br = yield
|
||||
assert br.code == B.Success
|
||||
assert "recovery shares are valid" in self.debug.wait_layout().text_content()
|
||||
assert "recovery shares are valid" in self.debug.read_layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
def warning_slip39_dryrun_mismatch(self) -> BRGeneratorType:
|
||||
br = yield
|
||||
assert br.code == B.Warning
|
||||
assert "do not match" in self.debug.wait_layout().text_content()
|
||||
assert "do not match" in self.debug.read_layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
def warning_bip39_dryrun_mismatch(self) -> BRGeneratorType:
|
||||
br = yield
|
||||
assert br.code == B.Warning
|
||||
assert "does not match" in self.debug.wait_layout().text_content()
|
||||
assert "does not match" in self.debug.read_layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
def success_more_shares_needed(
|
||||
@ -202,23 +202,23 @@ class RecoveryFlow:
|
||||
) -> BRGeneratorType:
|
||||
yield
|
||||
assert (
|
||||
"1 more share needed" in self.debug.wait_layout().text_content().lower()
|
||||
or "more shares needed" in self.debug.wait_layout().text_content().lower()
|
||||
"1 more share needed" in self.debug.read_layout().text_content().lower()
|
||||
or "more shares needed" in self.debug.read_layout().text_content().lower()
|
||||
)
|
||||
if count_needed is not None:
|
||||
assert str(count_needed) in self.debug.wait_layout().text_content()
|
||||
assert str(count_needed) in self.debug.read_layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
def input_mnemonic(self, mnemonic: list[str]) -> BRGeneratorType:
|
||||
br = yield
|
||||
assert br.code == B.MnemonicInput
|
||||
assert "MnemonicKeyboard" in self.debug.wait_layout().all_components()
|
||||
assert "MnemonicKeyboard" in self.debug.read_layout().all_components()
|
||||
for index, word in enumerate(mnemonic):
|
||||
if self.debug.model == "Safe 3":
|
||||
assert f"WORD {index + 1}" in self.debug.wait_layout().title()
|
||||
assert f"WORD {index + 1}" in self.debug.read_layout().title()
|
||||
else:
|
||||
assert (
|
||||
f"Type word {index + 1}" in self.debug.wait_layout().text_content()
|
||||
f"Type word {index + 1}" in self.debug.read_layout().text_content()
|
||||
)
|
||||
self.debug.input(word)
|
||||
|
||||
@ -243,8 +243,8 @@ class RecoveryFlow:
|
||||
self,
|
||||
) -> BRGeneratorType:
|
||||
# Moving through the INFO button
|
||||
self.debug.press_info()
|
||||
yield
|
||||
self.debug.press_info()
|
||||
self.debug.swipe_up()
|
||||
self.debug.press_yes()
|
||||
|
||||
@ -258,8 +258,8 @@ class EthereumFlow:
|
||||
|
||||
def confirm_data(self, info: bool = False, cancel: bool = False) -> BRGeneratorType:
|
||||
yield
|
||||
assert self.debug.wait_layout().title() == "CONFIRM DATA"
|
||||
assert "Size:" in self.debug.wait_layout().text_content()
|
||||
assert self.debug.read_layout().title() == "CONFIRM DATA"
|
||||
assert "Size:" in self.debug.read_layout().text_content()
|
||||
if info:
|
||||
self.debug.press_info()
|
||||
elif cancel:
|
||||
@ -269,22 +269,22 @@ class EthereumFlow:
|
||||
|
||||
def paginate_data(self) -> BRGeneratorType:
|
||||
br = yield
|
||||
assert self.debug.wait_layout().title() == "CONFIRM DATA"
|
||||
assert self.debug.read_layout().title() == "CONFIRM DATA"
|
||||
assert br.pages is not None
|
||||
for i in range(br.pages):
|
||||
self.debug.wait_layout()
|
||||
self.debug.read_layout()
|
||||
if i < br.pages - 1:
|
||||
self.debug.swipe_up()
|
||||
self.debug.press_yes()
|
||||
|
||||
def paginate_data_go_back(self) -> BRGeneratorType:
|
||||
br = yield
|
||||
assert self.debug.wait_layout().title() == "CONFIRM DATA"
|
||||
assert self.debug.read_layout().title() == "CONFIRM DATA"
|
||||
assert br.pages is not None
|
||||
assert br.pages > 2
|
||||
if self.debug.model == "T":
|
||||
self.debug.swipe_up(wait=True)
|
||||
self.debug.swipe_up(wait=True)
|
||||
self.debug.swipe_up()
|
||||
self.debug.swipe_up()
|
||||
self.debug.click(self.GO_BACK)
|
||||
else:
|
||||
self.debug.press_right()
|
||||
@ -295,7 +295,7 @@ class EthereumFlow:
|
||||
|
||||
def confirm_tx(self, cancel: bool = False, info: bool = False) -> BRGeneratorType:
|
||||
yield
|
||||
assert self.debug.wait_layout().title() == "RECIPIENT"
|
||||
assert self.debug.read_layout().title() == "RECIPIENT"
|
||||
|
||||
if self.debug.model == "T":
|
||||
if cancel:
|
||||
@ -303,25 +303,25 @@ class EthereumFlow:
|
||||
else:
|
||||
self.debug.press_yes()
|
||||
yield
|
||||
assert self.debug.wait_layout().title() == "SUMMARY"
|
||||
assert "Maximum fee:" in self.debug.wait_layout().text_content()
|
||||
assert self.debug.read_layout().title() == "SUMMARY"
|
||||
assert "Maximum fee:" in self.debug.read_layout().text_content()
|
||||
if info:
|
||||
self.debug.press_info(wait=True)
|
||||
assert "Gas limit:" in self.debug.wait_layout().text_content()
|
||||
assert "Gas price:" in self.debug.wait_layout().text_content()
|
||||
self.debug.press_no(wait=True)
|
||||
self.debug.press_info()
|
||||
assert "Gas limit:" in self.debug.read_layout().text_content()
|
||||
assert "Gas price:" in self.debug.read_layout().text_content()
|
||||
self.debug.press_no()
|
||||
self.debug.press_yes()
|
||||
else:
|
||||
if cancel:
|
||||
self.debug.press_left()
|
||||
else:
|
||||
self.debug.press_right()
|
||||
assert "Maximum fee:" in self.debug.wait_layout().text_content()
|
||||
assert "Maximum fee:" in self.debug.read_layout().text_content()
|
||||
if info:
|
||||
self.debug.press_right(wait=True)
|
||||
assert "Gas limit:" in self.debug.wait_layout().text_content()
|
||||
self.debug.press_right(wait=True)
|
||||
assert "Gas price:" in self.debug.wait_layout().text_content()
|
||||
self.debug.press_left(wait=True)
|
||||
self.debug.press_left(wait=True)
|
||||
self.debug.press_right()
|
||||
assert "Gas limit:" in self.debug.read_layout().text_content()
|
||||
self.debug.press_right()
|
||||
assert "Gas price:" in self.debug.read_layout().text_content()
|
||||
self.debug.press_left()
|
||||
self.debug.press_left()
|
||||
self.debug.press_middle()
|
||||
|
@ -42,9 +42,9 @@ def test_abort(core_emulator: Emulator):
|
||||
|
||||
device_handler.run(device.recover, pin_protection=False)
|
||||
|
||||
assert debug.wait_layout().title() == "RECOVER WALLET"
|
||||
assert debug.read_layout().title() == "RECOVER WALLET"
|
||||
|
||||
layout = debug.click(buttons.OK, wait=True)
|
||||
layout = debug.click(buttons.OK)
|
||||
assert "number of words" in layout.text_content()
|
||||
|
||||
debug = _restart(device_handler, core_emulator)
|
||||
@ -55,14 +55,14 @@ def test_abort(core_emulator: Emulator):
|
||||
# no waiting for layout because layout doesn't change
|
||||
assert "number of words" in debug.read_layout().text_content()
|
||||
# clicking at 24 in word choice (the same coords as CANCEL)
|
||||
layout = debug.click(buttons.CANCEL, wait=True)
|
||||
layout = debug.click(buttons.CANCEL)
|
||||
|
||||
# Cancelling the backup
|
||||
assert "Enter your backup" in debug.read_layout().text_content()
|
||||
layout = debug.click(buttons.CANCEL, wait=True)
|
||||
layout = debug.click(buttons.CANCEL)
|
||||
|
||||
assert layout.title() in ("ABORT RECOVERY", "CANCEL RECOVERY")
|
||||
layout = debug.click(buttons.OK, wait=True)
|
||||
layout = debug.click(buttons.OK)
|
||||
|
||||
assert layout.main_component() == "Homescreen"
|
||||
features = device_handler.features()
|
||||
@ -89,7 +89,7 @@ def test_recovery_single_reset(core_emulator: Emulator):
|
||||
assert features.recovery_mode is True
|
||||
|
||||
# we need to enter the number of words again, that's a feature
|
||||
recovery.select_number_of_words(debug, wait=False)
|
||||
recovery.select_number_of_words(debug)
|
||||
recovery.enter_shares(debug, MNEMONIC_SLIP39_BASIC_20_3of6)
|
||||
recovery.finalize(debug)
|
||||
|
||||
@ -126,7 +126,7 @@ def test_recovery_on_old_wallet(core_emulator: Emulator):
|
||||
assert features.recovery_mode is True
|
||||
|
||||
# enter number of words
|
||||
recovery.select_number_of_words(debug, wait=False)
|
||||
recovery.select_number_of_words(debug)
|
||||
|
||||
first_share = MNEMONIC_SLIP39_BASIC_20_3of6[0]
|
||||
words = first_share.split(" ")
|
||||
@ -134,11 +134,11 @@ def test_recovery_on_old_wallet(core_emulator: Emulator):
|
||||
# start entering first share
|
||||
assert "Enter any share" in debug.read_layout().text_content()
|
||||
debug.press_yes()
|
||||
assert debug.wait_layout().main_component() == "MnemonicKeyboard"
|
||||
assert debug.read_layout().main_component() == "MnemonicKeyboard"
|
||||
|
||||
# enter first word
|
||||
debug.input(words[0])
|
||||
layout = debug.wait_layout()
|
||||
layout = debug.read_layout()
|
||||
|
||||
# while keyboard is open, hit the device with Initialize/GetFeatures
|
||||
device_handler.client.init_device()
|
||||
@ -148,7 +148,7 @@ def test_recovery_on_old_wallet(core_emulator: Emulator):
|
||||
for word in words[1:]:
|
||||
assert layout.main_component() == "MnemonicKeyboard"
|
||||
debug.input(word)
|
||||
layout = debug.wait_layout()
|
||||
layout = debug.read_layout()
|
||||
|
||||
# check that we entered the first share successfully
|
||||
assert "1 of 3 shares entered" in layout.text_content()
|
||||
@ -202,7 +202,7 @@ def test_recovery_multiple_resets(core_emulator: Emulator):
|
||||
assert features.recovery_mode is True
|
||||
|
||||
# enter the number of words again, that's a feature!
|
||||
recovery.select_number_of_words(debug, wait=False)
|
||||
recovery.select_number_of_words(debug)
|
||||
|
||||
# enter shares and restart after each one
|
||||
enter_shares_with_restarts(debug)
|
||||
|
Loading…
Reference in New Issue
Block a user