mirror of
https://github.com/SeedSigner/seedsigner.git
synced 2026-10-05 15:08:25 +00:00
SettingsQR tests; mocked MicroSD.is_inserted
This commit is contained in:
+21
-3
@@ -1,6 +1,6 @@
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from mock import MagicMock, patch
|
||||
from mock import MagicMock, Mock, patch
|
||||
from typing import Callable
|
||||
|
||||
# Prevent importing modules w/Raspi hardware dependencies.
|
||||
@@ -11,17 +11,27 @@ sys.modules['seedsigner.gui.toast'] = MagicMock()
|
||||
sys.modules['seedsigner.views.screensaver'] = MagicMock()
|
||||
sys.modules['seedsigner.hardware.buttons'] = MagicMock()
|
||||
sys.modules['seedsigner.hardware.camera'] = MagicMock()
|
||||
sys.modules['seedsigner.hardware.microsd'] = MagicMock()
|
||||
|
||||
from seedsigner.controller import Controller, FlowBasedTestException, StopFlowBasedTest
|
||||
from seedsigner.gui.screens.screen import RET_CODE__BACK_BUTTON, RET_CODE__POWER_BUTTON
|
||||
from seedsigner.hardware.microsd import MicroSD
|
||||
from seedsigner.models.settings import Settings
|
||||
from seedsigner.views.view import Destination, MainMenuView, View
|
||||
|
||||
|
||||
|
||||
|
||||
class BaseTest:
|
||||
|
||||
class MockMicroSD(Mock):
|
||||
"""
|
||||
A test suite-friendly replacement for `MicroSD` that gives a test explicit
|
||||
control over the reported state of the SD card.
|
||||
"""
|
||||
# Tests are free to directly manipulate this attribute as needed
|
||||
is_inserted: bool = True
|
||||
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
# Ensure there are no on-disk artifacts after running tests.
|
||||
@@ -30,6 +40,13 @@ class BaseTest:
|
||||
# Mock out the loading screen so it can't spawn. View classes must import locally!
|
||||
patch('seedsigner.gui.screens.screen.LoadingScreenThread').start()
|
||||
|
||||
# Instantiate the mocked MicroSD; hold on to the instance so tests can manipulate
|
||||
# it later.
|
||||
cls.mock_microsd = BaseTest.MockMicroSD()
|
||||
|
||||
# And mock it over `MicroSD`'s instance
|
||||
MicroSD.get_instance = Mock(return_value=cls.mock_microsd)
|
||||
|
||||
|
||||
@classmethod
|
||||
def teardown_class(cls):
|
||||
@@ -62,11 +79,12 @@ class BaseTest:
|
||||
|
||||
|
||||
def setup_method(self):
|
||||
""" Guarantee a clean/default Controller and Settings state for each test case """
|
||||
""" Guarantee a clean/default Controller, Settings, & MicroSD state for each test case """
|
||||
BaseTest.reset_controller()
|
||||
BaseTest.reset_settings()
|
||||
self.controller = Controller.get_instance()
|
||||
self.settings = Settings.get_instance()
|
||||
self.mock_microsd.is_inserted = True
|
||||
|
||||
|
||||
def teardown_method(self):
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
from typing import Callable
|
||||
|
||||
# Must import test base before the Controller
|
||||
from base import FlowTest, FlowStep
|
||||
@@ -6,13 +7,13 @@ from base import FlowTest, FlowStep
|
||||
from seedsigner.models.settings import Settings
|
||||
from seedsigner.models.settings_definition import SettingsDefinition, SettingsConstants
|
||||
from seedsigner.gui.screens.screen import RET_CODE__BACK_BUTTON
|
||||
from seedsigner.hardware.microsd import MicroSD
|
||||
from seedsigner.views.view import MainMenuView
|
||||
from seedsigner.views import settings_views
|
||||
from seedsigner.views import scan_views, settings_views
|
||||
|
||||
|
||||
|
||||
class TestSettingsFlows(FlowTest):
|
||||
|
||||
def test_persistent_settings(self):
|
||||
""" Basic flow from MainMenuView to enable/disable persistent settings """
|
||||
# Which option are we testing?
|
||||
@@ -67,3 +68,56 @@ class TestSettingsFlows(FlowTest):
|
||||
FlowStep(settings_views.DonateView),
|
||||
FlowStep(settings_views.SettingsMenuView),
|
||||
])
|
||||
|
||||
|
||||
def test_settingsqr(self):
|
||||
"""
|
||||
Scanning a SettingsQR should present the success screen and then return to
|
||||
MainMenuView.
|
||||
"""
|
||||
def load_persistent_settingsqr_into_decoder(view: scan_views.ScanView):
|
||||
settingsqr_data_persistent: str = "settings::v1 name=Total_noob_mode persistent=E coords=spa,spd denom=thr network=M qr_density=M xpub_export=E sigs=ss scripts=nat xpub_details=E passphrase=E camera=0 compact_seedqr=E bip85=D priv_warn=E dire_warn=E partners=E"
|
||||
view.decoder.add_data(settingsqr_data_persistent)
|
||||
|
||||
def load_not_persistent_settingsqr_into_decoder(view: scan_views.ScanView):
|
||||
settingsqr_data_not_persistent: str = "settings::v1 name=Ephemeral_noob_mode persistent=D coords=spa,spd denom=thr network=M qr_density=M xpub_export=E sigs=ss scripts=nat xpub_details=E passphrase=E camera=0 compact_seedqr=E bip85=D priv_warn=E dire_warn=E partners=E"
|
||||
view.decoder.add_data(settingsqr_data_not_persistent)
|
||||
|
||||
def _run_test(initial_setting_state: str, load_settingsqr_into_decoder: Callable, expected_setting_state: str):
|
||||
self.settings.set_value(SettingsConstants.SETTING__PERSISTENT_SETTINGS, initial_setting_state)
|
||||
self.run_sequence([
|
||||
FlowStep(MainMenuView, button_data_selection=MainMenuView.SCAN),
|
||||
FlowStep(scan_views.ScanView, before_run=load_settingsqr_into_decoder), # simulate read message QR; ret val is ignored
|
||||
FlowStep(settings_views.SettingsIngestSettingsQRView), # ret val is ignored
|
||||
FlowStep(MainMenuView),
|
||||
])
|
||||
|
||||
assert self.settings.get_value(SettingsConstants.SETTING__PERSISTENT_SETTINGS) == expected_setting_state
|
||||
|
||||
|
||||
# First load a SettingsQR that enables persistent settings
|
||||
self.mock_microsd.is_inserted = True
|
||||
assert MicroSD.get_instance().is_inserted is True
|
||||
|
||||
_run_test(
|
||||
initial_setting_state=SettingsConstants.OPTION__DISABLED,
|
||||
load_settingsqr_into_decoder=load_persistent_settingsqr_into_decoder,
|
||||
expected_setting_state=SettingsConstants.OPTION__ENABLED
|
||||
)
|
||||
|
||||
# Then one that disables it
|
||||
_run_test(
|
||||
initial_setting_state=SettingsConstants.OPTION__ENABLED,
|
||||
load_settingsqr_into_decoder=load_not_persistent_settingsqr_into_decoder,
|
||||
expected_setting_state=SettingsConstants.OPTION__DISABLED
|
||||
)
|
||||
|
||||
# Now try to enable persistent settings when the SD card is not inserted
|
||||
self.mock_microsd.is_inserted = False
|
||||
assert MicroSD.get_instance().is_inserted is False
|
||||
|
||||
_run_test(
|
||||
initial_setting_state=SettingsConstants.OPTION__DISABLED,
|
||||
load_settingsqr_into_decoder=load_persistent_settingsqr_into_decoder,
|
||||
expected_setting_state=SettingsConstants.OPTION__DISABLED
|
||||
)
|
||||
|
||||
@@ -8,6 +8,7 @@ from seedsigner.models.settings_definition import SettingsConstants
|
||||
class TestSettings(BaseTest):
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
super().setup_class()
|
||||
cls.settings = Settings.get_instance()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user