diff --git a/src/seedsigner/controller.py b/src/seedsigner/controller.py index 4976d6f74..8f68c2647 100644 --- a/src/seedsigner/controller.py +++ b/src/seedsigner/controller.py @@ -309,7 +309,12 @@ def handle_exception(self, e) -> Destination: # So we extract the Exception type and trim off any "foo.bar." namespacing: last_line = traceback.format_exc().splitlines()[-1] exception_type = last_line.split(":")[0].split(".")[-1] - exception_msg = last_line.split(":")[1] + + # Extract the error message, if there is one + if ":" in last_line: + exception_msg = last_line.split(":")[1] + else: + exception_msg = "" # Scan for the last debugging line that includes a line number reference line_info = None diff --git a/tests/test_controller.py b/tests/test_controller.py index bd8b2c18e..2fce03876 100644 --- a/tests/test_controller.py +++ b/tests/test_controller.py @@ -43,6 +43,48 @@ def test_singleton_get_instance_preserves_state(reset_controller): assert controller.unverified_address == "123abc" +def test_handle_exception(reset_controller): + """ Handle exceptions that get caught by the controller """ + + def process_exception_asserting_valid_error(exception_type, exception_msg=None): + """ + Exceptions caught by the controller are forwarded to the + UnhandledExceptionView with view_args["error"] being a list + of three strings, ie: [exception_type, line_info, exception_msg] + """ + try: + if exception_msg: + raise exception_type(exception_msg) + else: + raise exception_type() + except Exception as e: + error = controller.handle_exception(e).view_args["error"] + + # assert that error structure is valid + assert len(error) == 3 + assert error[0] in str(exception_type) + assert type(error[1]) == str + if exception_msg: + assert exception_msg in error[2] + else: + assert error[2] == "" + + # Initialize the controller + controller = Controller.get_instance() + + exception_tests = [ + # exceptions with an exception_msg + (Exception, "foo"), + (KeyError, "key not found"), + # exceptions without an exception_msg + (Exception, ""), + (Exception, None), + ] + + for exception_type, exception_msg in exception_tests: + process_exception_asserting_valid_error(exception_type, exception_msg) + + def test_missing_settings_get_defaults(reset_controller): """ Should gracefully handle all missing fields from `settings.json` """