diff --git a/testing/conftest.py b/testing/conftest.py index a2f2ed55..9b823b27 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -189,9 +189,10 @@ def enter_pin(enter_number, need_keypress, cap_screen, is_q1): a,b = pin.split('-') enter_number(a) + need_keypress(KEY_ENTER) scr = cap_screen().split('\n') if is_q1: - words = [i.strip() for i in scr[6].split()] # XXX untested + words = [i.strip() for i in scr[7].split()] else: # capture words? hard to know in general what they should be tho words = scr[2:4] @@ -199,6 +200,7 @@ def enter_pin(enter_number, need_keypress, cap_screen, is_q1): need_keypress('y') enter_number(b) + need_keypress(KEY_ENTER) return words @@ -979,8 +981,8 @@ def settings_remove(sim_exec): return doit @pytest.fixture(scope='module') -def repl(request, is_mark4): - return request.getfixturevalue('mk4_repl' if is_mark4 else 'old_mk_repl') +def repl(request): + return request.getfixturevalue('mk4_repl') @pytest.fixture(scope='module') diff --git a/testing/test_backup.py b/testing/test_backup.py index 8bf53aa6..0d2b87b4 100644 --- a/testing/test_backup.py +++ b/testing/test_backup.py @@ -1,5 +1,7 @@ -import pytest, time, json, os, shutil +import pytest, time, json, os, shutil, re +from collections import OrderedDict from constants import simulator_fixed_words, simulator_fixed_tprv +from charcodes import KEY_QR from pycoin.key.BIP32Node import BIP32Node from mnemonic import Mnemonic @@ -24,11 +26,21 @@ def decode_backup(txt): return vals, trimmed +@pytest.fixture +def parse_q1_words(): + def doit(body): + wrd_d = {} + for mtch in re.findall(r"\d{1,2}: [a-z]+", body): + num, word = mtch.split(":") + wrd_d[num] = word.strip() + + return list(OrderedDict(sorted(wrd_d.items(), key=lambda t: int(t[0]))).values()) + return doit @pytest.fixture def backup_system(settings_set, settings_remove, goto_home, pick_menu_item, cap_story, need_keypress, cap_screen_qr, pass_word_quiz, - get_setting): + get_setting, is_q1, parse_q1_words): def doit(reuse_pw=False, save_pw=False, st=None, ct=False): # st -> seed type # ct -> cleartext backup @@ -82,13 +94,17 @@ def backup_system(settings_set, settings_remove, goto_home, pick_menu_item, assert 'Record this' in body assert 'password:' in body - words = [w[3:].strip() for w in body.split('\n') if w and w[2] == ':'] + if is_q1: + words = parse_q1_words(body) + else: + words = [w[3:].strip() for w in body.split('\n') if w and w[2] == ':'] + assert len(words) == 12 print("Passphrase: %s" % ' '.join(words)) if 'QR Code' in body: - need_keypress('1') + need_keypress(KEY_QR if is_q1 else '1') got_qr = cap_screen_qr().decode('ascii').lower().split() assert [w[0:4] for w in words] == got_qr need_keypress('y') @@ -222,7 +238,8 @@ def test_backup_ephemeral_wallet(stype, pick_menu_item, need_keypress, goto_home verify_backup_file, microsd_path, check_and_decrypt_backup, sim_execfile, unit_test, word_menu_entry, cap_menu, restore_backup_cs, generate_ephemeral_words, - import_ephemeral_xprv, reset_seed_words): + import_ephemeral_xprv, reset_seed_words, parse_q1_words, + is_q1): reset_seed_words() goto_home() if "words" in stype: @@ -251,7 +268,10 @@ def test_backup_ephemeral_wallet(stype, pick_menu_item, need_keypress, goto_home assert 'Record this' in story assert 'password:' in story - words = [w[3:].strip() for w in story.split('\n') if w and w[2] == ':'] + if is_q1: + words = parse_q1_words(story) + else: + words = [w[3:].strip() for w in story.split('\n') if w and w[2] == ':'] assert len(words) == 12 # pass the quiz! count, title, body = pass_word_quiz(words) @@ -303,7 +323,8 @@ def test_backup_bip39_wallet(passphrase, set_bip39_pw, pick_menu_item, need_keyp goto_home, cap_story, pass_word_quiz, get_setting, verify_backup_file, microsd_path, check_and_decrypt_backup, sim_execfile, unit_test, word_menu_entry, cap_menu, - restore_backup_cs, seedvault, settings_set, reset_seed_words): + restore_backup_cs, seedvault, settings_set, reset_seed_words, + is_q1, parse_q1_words): reset_seed_words() goto_home() settings_set("seedvault", int(seedvault)) @@ -329,8 +350,10 @@ def test_backup_bip39_wallet(passphrase, set_bip39_pw, pick_menu_item, need_keyp assert title == 'NO-TITLE' assert 'Record this' in story assert 'password:' in story - - words = [w[3:].strip() for w in story.split('\n') if w and w[2] == ':'] + if is_q1: + words = parse_q1_words(story) + else: + words = [w[3:].strip() for w in story.split('\n') if w and w[2] == ':'] assert len(words) == 12 # pass the quiz! count, title, body = pass_word_quiz(words) @@ -431,7 +454,8 @@ def test_seed_vault_backup(settings_set, reset_seed_words, generate_ephemeral_wo import_ephemeral_xprv, restore_main_seed, settings_get, repl, pick_menu_item, need_keypress, cap_story, get_setting, pass_word_quiz, verify_backup_file, check_and_decrypt_backup, - restore_backup_cs, cap_menu, verify_ephemeral_secret_ui): + restore_backup_cs, cap_menu, verify_ephemeral_secret_ui, + is_q1, parse_q1_words): reset_seed_words() settings_set("seedvault", 1) settings_set("seeds", []) @@ -471,8 +495,10 @@ def test_seed_vault_backup(settings_set, reset_seed_words, generate_ephemeral_wo assert title == 'NO-TITLE' assert 'Record this' in story assert 'password:' in story - - words = [w[3:].strip() for w in story.split('\n') if w and w[2] == ':'] + if is_q1: + words = parse_q1_words(story) + else: + words = [w[3:].strip() for w in story.split('\n') if w and w[2] == ':'] assert len(words) == 12 # pass the quiz! count, title, body = pass_word_quiz(words) diff --git a/testing/test_ux.py b/testing/test_ux.py index 5af8651e..a4266dc0 100644 --- a/testing/test_ux.py +++ b/testing/test_ux.py @@ -52,24 +52,22 @@ def test_home_menu(cap_menu, cap_story, cap_screen, need_keypress, reset_seed_wo need_keypress('x') @pytest.fixture -def word_menu_entry(cap_menu, pick_menu_item, is_q1, do_keypresses, cap_screen): +def word_menu_entry(cap_menu, pick_menu_item, is_q1, cap_screen, need_keypress): def doit(words): if is_q1: # easier for us on Q, but have to anticipate the autocomplete - for n, w in enumerate(words): - do_keypresses(w[0:3]) - time.sleep(0.50) - if 'Next key' in cap_screen(): - do_keypresses(w[4]) - pat = rf'{n+1}:\s?{w}' - for x in range(10): - if re.search(pat, cap_screen()): + for w in words: + for i in range(len(w)): + time.sleep(.3) + menu = cap_menu() + time.sleep(.3) + if w in menu: + pick_menu_item(w) break - time.sleep(0.20) - else: - raise RuntimeError('timeout') - assert 'Valid words' in cap_screen() - do_keypresses('\r') + v = f"{w[:i+1]}-" + if v in menu: + pick_menu_item(v) + return # do the massive drilling-down to pick a specific pass phrase