mirror of
https://github.com/SeedSigner/seedsigner.git
synced 2026-09-14 04:45:08 +00:00
Merge pull request #900 from PROWLERx15/fix-seed-views
[Bugfix] Back Navigation in Seed Entry Views
This commit is contained in:
@@ -226,11 +226,13 @@ class SeedMnemonicEntryView(View):
|
||||
)
|
||||
|
||||
if ret == RET_CODE__BACK_BUTTON:
|
||||
if self.cur_word_index > 0:
|
||||
return Destination(BackStackView)
|
||||
else:
|
||||
# This handles two possible scenarios:
|
||||
# 1. Backing out of the first word cancels the mnemonic entry process;
|
||||
# return to whichever `View` routed us here initially.
|
||||
# 2. Backing out of the current word returns to the previous word.
|
||||
if self.cur_word_index == 0:
|
||||
self.controller.storage.discard_pending_mnemonic()
|
||||
return Destination(MainMenuView)
|
||||
return Destination(BackStackView)
|
||||
|
||||
# ret will be our new mnemonic word
|
||||
self.controller.storage.update_pending_mnemonic(ret, self.cur_word_index)
|
||||
@@ -339,9 +341,6 @@ class SeedFinalizeView(View):
|
||||
elif button_data[selected_menu_num] == self.PASSPHRASE:
|
||||
return Destination(SeedAddPassphraseView)
|
||||
|
||||
elif selected_menu_num == RET_CODE__BACK_BUTTON:
|
||||
return Destination(BackStackView)
|
||||
|
||||
|
||||
|
||||
class SeedAddPassphraseView(View):
|
||||
|
||||
@@ -495,6 +495,79 @@ class TestSeedFlows(FlowTest):
|
||||
|
||||
|
||||
|
||||
class TestSeedEntryBackFlows(FlowTest):
|
||||
"""
|
||||
Tests for every BACK exit scenario from SeedMnemonicEntryView and related views.
|
||||
|
||||
A naive BackStackView swap can leave resume_main_flow dangling, causing
|
||||
auto-redirects on stale flow state. These tests verify that BACK navigation
|
||||
returns to the correct parent view AND that no flow state leaks.
|
||||
"""
|
||||
|
||||
def test_back_from_seed_entry_first_word(self):
|
||||
"""
|
||||
Pressing BACK on the first word of mnemonic entry should return to
|
||||
the View that initiated the mnemonic entry process.
|
||||
"""
|
||||
for seed_type in [seed_views.LoadSeedView.TYPE_12WORD, seed_views.LoadSeedView.TYPE_24WORD]:
|
||||
self.run_sequence([
|
||||
FlowStep(MainMenuView, button_data_selection=MainMenuView.SEEDS),
|
||||
FlowStep(seed_views.SeedsMenuView, is_redirect=True), # No seeds loaded; auto-redirects to LoadSeedView
|
||||
FlowStep(seed_views.LoadSeedView, button_data_selection=seed_type),
|
||||
FlowStep(seed_views.SeedMnemonicEntryView, screen_return_value=RET_CODE__BACK_BUTTON),
|
||||
FlowStep(seed_views.LoadSeedView), # Should land here, NOT MainMenuView
|
||||
])
|
||||
BaseTest.reset_controller()
|
||||
|
||||
|
||||
def test_back_from_seed_entry_mid_word(self):
|
||||
"""
|
||||
Pressing BACK from a middle word (eg. word #2) should return to the
|
||||
previous SeedMnemonicEntryView (eg. word #1) via the back stack.
|
||||
"""
|
||||
self.run_sequence([
|
||||
FlowStep(MainMenuView, button_data_selection=MainMenuView.SEEDS),
|
||||
FlowStep(seed_views.SeedsMenuView, is_redirect=True),
|
||||
FlowStep(seed_views.LoadSeedView, button_data_selection=seed_views.LoadSeedView.TYPE_12WORD),
|
||||
FlowStep(seed_views.SeedMnemonicEntryView, screen_return_value="abandon"), # word #1
|
||||
FlowStep(seed_views.SeedMnemonicEntryView, screen_return_value=RET_CODE__BACK_BUTTON), # BACK from word #2
|
||||
FlowStep(seed_views.SeedMnemonicEntryView), # Returns to word #1
|
||||
])
|
||||
|
||||
# Verify we're back on word #1: word at index 0 should still be set
|
||||
# from the previous entry, while word at index 1 should be unset.
|
||||
assert self.controller.storage.get_pending_mnemonic_word(0) == "abandon"
|
||||
assert self.controller.storage.get_pending_mnemonic_word(1) is None
|
||||
|
||||
|
||||
def test_back_from_seed_entry_via_seed_select(self):
|
||||
"""
|
||||
Backing out of mnemonic entry during an active flow must preserve
|
||||
`resume_main_flow` so the user remains within that flow.
|
||||
"""
|
||||
from seedsigner.controller import Controller
|
||||
from seedsigner.models.settings import SettingsConstants
|
||||
|
||||
self.settings.set_value(SettingsConstants.SETTING__MESSAGE_SIGNING, SettingsConstants.OPTION__ENABLED)
|
||||
|
||||
def load_signmessage_into_decoder(view):
|
||||
view.decoder.add_data("signmessage m/84h/0h/0h/0/0 ascii:test message")
|
||||
|
||||
self.run_sequence([
|
||||
FlowStep(MainMenuView, button_data_selection=MainMenuView.SCAN),
|
||||
FlowStep(scan_views.ScanView, before_run=load_signmessage_into_decoder),
|
||||
FlowStep(seed_views.SeedSignMessageStartView, is_redirect=True),
|
||||
FlowStep(seed_views.SeedSelectSeedView, button_data_selection=seed_views.SeedSelectSeedView.TYPE_12WORD),
|
||||
FlowStep(seed_views.SeedMnemonicEntryView, screen_return_value=RET_CODE__BACK_BUTTON), # BACK on first word
|
||||
FlowStep(seed_views.SeedSelectSeedView), # Should return here, in the sign message flow
|
||||
])
|
||||
|
||||
# Verify resume_main_flow is still set — user is still in the sign message flow
|
||||
assert self.controller.resume_main_flow == Controller.FLOW__SIGN_MESSAGE
|
||||
|
||||
|
||||
|
||||
|
||||
class TestMessageSigningFlows(FlowTest):
|
||||
MAINNET_DERIVATION_PATH = "m/84h/0h/0h/0/0"
|
||||
TESTNET_DERIVATION_PATH = "m/84h/1h/0h/0/0"
|
||||
|
||||
Reference in New Issue
Block a user