def helper_test_delete_last_account(self, app): """ Trying to delete the last account, should not crash the app, refs #120. """ controller = app.controller pywalib = controller.pywalib manage_existing = controller.manage_existing # makes sure there's only one account left self.assertEqual(len(pywalib.get_account_list()), 1) # deletes it delete_button_id = manage_existing.ids.delete_button_id delete_button_id.dispatch('on_release') # a confirmation popup should show dialogs = Dialog.dialogs self.assertEqual(len(dialogs), 1) dialog = dialogs[0] self.assertEqual(dialog.title, 'Are you sure?') # confirm it manage_existing.on_delete_account_yes(dialog) # account was deleted dialog message dialogs = Dialog.dialogs self.assertEqual(len(dialogs), 1) dialog = dialogs[0] self.assertEqual(dialog.title, 'Account deleted, redirecting...') Dialog.dismiss_all_dialogs() self.advance_frames(1) # verifies the account was deleted self.assertEqual(len(pywalib.get_account_list()), 0) # this should be done by the events, but doesn't seem to happen # so we have to trigger it manually controller.history.current_account = None self.advance_frames(1)
def helper_test_delete_account(self, app): """ Deletes account from the UI. """ controller = app.controller pywalib = controller.pywalib # makes sure we have an account to play with self.assertEqual(len(pywalib.get_account_list()), 1) # makes sure the account appears in the switch account view switch_account = self.helper_load_switch_account(app) account_list_id = switch_account.ids.account_list_id children = account_list_id.children self.assertEqual(len(children), 1) item = children[0] self.assertEqual(type(item), kivymd.list.OneLineListItem) self.assertEqual(item.account, pywalib.get_account_list()[0]) # go to the manage account screen # TODO: use dispatch('on_release') on navigation drawer controller.load_manage_keystores() # TODO: broken in #124 # self.advance_frames(1) self.advance_frames(30) self.assertEqual('Manage existing', app.controller.toolbar.title) # verifies an account is showing manage_existing = controller.manage_existing account_address_id = manage_existing.ids.account_address_id account = pywalib.get_account_list()[0] account_address = '0x' + account.address.hex() self.assertEqual(account_address_id.text, account_address) # clicks delete delete_button_id = manage_existing.ids.delete_button_id delete_button_id.dispatch('on_release') # a confirmation popup should show dialogs = Dialog.dialogs self.assertEqual(len(dialogs), 1) dialog = dialogs[0] self.assertEqual(dialog.title, 'Are you sure?') # confirm it # TODO: click on the dialog action button itself manage_existing.on_delete_account_yes(dialog) # the dialog should be replaced by another one dialogs = Dialog.dialogs self.assertEqual(len(dialogs), 1) dialog = dialogs[0] self.assertEqual(dialog.title, 'Account deleted, redirecting...') Dialog.dismiss_all_dialogs() # and the account deleted self.assertEqual(len(pywalib.get_account_list()), 0) # makes sure the account was also cleared from the selection view switch_account = self.helper_load_switch_account(app) account_list_id = switch_account.ids.account_list_id # TODO: broken in #124 self.advance_frames(30) self.assertEqual(len(account_list_id.children), 0)
def helper_test_delete_account_none_selected(self, app): """ Tries to delete account when none are selected, refs #90. """ controller = app.controller pywalib = controller.pywalib manage_existing = controller.manage_existing # makes sure an account is selected pywalib.new_account(password="******", security_ratio=1) controller.current_account = pywalib.get_account_list()[0] # ManageExisting and Controller current_account should be in sync self.assertEqual(manage_existing.current_account, controller.current_account) # chaning in the Controller, should trigger the change on the other self.assertTrue(manage_existing.current_account is not None) controller.current_account = None self.assertIsNone(manage_existing.current_account) # let's try to delete this "None account" delete_button_id = manage_existing.ids.delete_button_id delete_button_id.dispatch('on_release') # an error dialog should pop dialogs = Dialog.dialogs self.assertEqual(len(dialogs), 1) dialog = dialogs[0] self.assertEqual(dialog.title, 'No account selected.') Dialog.dismiss_all_dialogs()
def helper_test_address_alias(self, app): """ Creates, updates and deletes account address aliases. """ controller = app.controller pywalib = controller.pywalib account1 = pywalib.get_account_list()[0] # creates a second account account2 = pywalib.new_account(password="******", security_ratio=1) address1 = '0x' + account1.address.encode("hex") address2 = '0x' + account2.address.encode("hex") Controller = main.Controller @staticmethod def get_store_path(): """ Makes sure we don't mess up with actual store config file. """ os.environ['KEYSTORE_PATH'] = self.temp_path store_path = os.path.join(self.temp_path, 'store.json') return store_path with mock.patch.object(Controller, 'get_store_path', get_store_path): # no alias by default with self.assertRaises(KeyError): Controller.get_account_alias(account1) with self.assertRaises(KeyError): Controller.get_address_alias(address1) # sets some aliases alias1 = 'alias1' alias2 = 'alias2' Controller.set_account_alias(account1, alias1) Controller.set_account_alias(account2, alias2) # checks we can retrieve them self.assertEqual(Controller.get_account_alias(account1), alias1) self.assertEqual(Controller.get_account_alias(account2), alias2) self.assertEqual(Controller.get_address_alias(address1), alias1) self.assertEqual(Controller.get_address_alias(address2), alias2) # updates an alias alias1 = 'alias0' Controller.set_account_alias(account1, alias1) self.assertEqual(Controller.get_account_alias(account1), alias1) # deletes one and see if it worked Controller.delete_account_alias(account1) with self.assertRaises(KeyError): Controller.get_account_alias(account1) # the second one should still be there self.assertEqual(Controller.get_address_alias(address2), alias2) # tears down pywalib.delete_account(account2)
def helper_test_delete_account_twice(self, app): """ Trying to delete the same account twice, shoult not crash the app, refs #51. """ controller = app.controller pywalib = controller.pywalib manage_existing = controller.manage_existing # makes sure an account is selected pywalib.new_account(password="******", security_ratio=None) controller.current_account = pywalib.get_account_list()[0] self.assertTrue(manage_existing.current_account is not None) account_count_before = len(pywalib.get_account_list()) # let's try to delete this account once delete_button_id = manage_existing.ids.delete_button_id delete_button_id.dispatch('on_release') self.helper_confirm_account_deletion(app) # the account should be deleted self.assertEqual(len(pywalib.get_account_list()), account_count_before - 1) # makes sure the account was also cleared from the selection view switch_account = self.helper_load_switch_account(app) account_list_id = switch_account.ids.account_list_id self.assertEqual(len(account_list_id.children), len(pywalib.get_account_list())) # TODO: the selected account should now be None # self.assertIsNone(manage_existing.current_account) # self.assertIsNone(controller.current_account) # let's try to delete this account a second time delete_button_id = manage_existing.ids.delete_button_id delete_button_id.dispatch('on_release') # TODO: the second time an error dialog should pop # dialogs = Dialog.dialogs # self.assertEqual(len(dialogs), 1) # dialog = dialogs[0] # self.assertEqual(dialog.title, 'No account selected.') Dialog.dismiss_all_dialogs()
def helper_test_back_home_empty_account(self, app): """ Loading the overview (back button) with no account should not crash the application, refs #115. """ controller = app.controller pywalib = controller.pywalib # loading the app with empty account directory self.assertEqual(len(pywalib.get_account_list()), 0) # tries to go back to the home screen with escape key # def on_keyboard(self, window, key, *args): controller.on_keyboard(window=None, key=27) # loading the overview with empty account should not crash self.assertEqual('', app.controller.toolbar.title) self.assertEqual(controller.screen_manager.current, 'overview')
def helper_test_empty_account(self, app): """ Verifies the UI behaves as expected on empty account list. """ controller = app.controller pywalib = controller.pywalib # loading the app with empty account directory self.assertEqual(len(pywalib.get_account_list()), 0) # should trigger the "Create new account" view to be open self.advance_frames(1) self.assertEqual('Create new account', app.controller.toolbar.title) self.assertEqual(controller.screen_manager.current, 'manage_keystores') dialogs = Dialog.dialogs self.advance_frames(1) self.assertEqual(len(dialogs), 1) dialog = dialogs[0] self.assertEqual(dialog.title, 'No keystore found.') dialog.dismiss() self.assertEqual(len(dialogs), 0)
def helper_test_address_alias(self, app): """ Creates, updates and deletes account address aliases. """ controller = app.controller pywalib = controller.pywalib account1 = pywalib.get_account_list()[0] # creates a second account account2 = pywalib.new_account(password="******", security_ratio=1) address1 = '0x' + account1.address.hex() address2 = '0x' + account2.address.hex() Controller = main.Controller with patch_get_store_path(self.temp_path): # no alias by default with self.assertRaises(KeyError): Controller.get_account_alias(account1) with self.assertRaises(KeyError): Controller.get_address_alias(address1) # sets some aliases alias1 = 'alias1' alias2 = 'alias2' Controller.set_account_alias(account1, alias1) Controller.set_account_alias(account2, alias2) # checks we can retrieve them self.assertEqual(Controller.get_account_alias(account1), alias1) self.assertEqual(Controller.get_account_alias(account2), alias2) self.assertEqual(Controller.get_address_alias(address1), alias1) self.assertEqual(Controller.get_address_alias(address2), alias2) # updates an alias alias1 = 'alias0' Controller.set_account_alias(account1, alias1) self.assertEqual(Controller.get_account_alias(account1), alias1) # deletes one and see if it worked Controller.delete_account_alias(account1) with self.assertRaises(KeyError): Controller.get_account_alias(account1) # the second one should still be there self.assertEqual(Controller.get_address_alias(address2), alias2) # tears down pywalib.delete_account(account2)
def helper_test_create_first_account(self, app): """ Creates the first account. """ controller = app.controller pywalib = controller.pywalib # makes sure no account are loaded self.assertEqual(len(pywalib.get_account_list()), 0) controller.load_create_new_account() self.assertEqual('Create new account', app.controller.toolbar.title) self.assertEqual(controller.current_account, None) # retrieves the create_new_account widget controller = app.controller create_new_account = controller.create_new_account # retrieves widgets (password fields, sliders and buttons) new_password1_id = create_new_account.ids.new_password1_id new_password2_id = create_new_account.ids.new_password2_id speed_slider_id = create_new_account.ids.speed_slider_id create_account_button_id = \ create_new_account.ids.create_account_button_id # fills them up with same password new_password1_id.text = new_password2_id.text = "password" # makes the account creation fast speed_slider_id.value = speed_slider_id.max # before clicking the create account button, # only the main thread is running self.assertEqual(len(threading.enumerate()), 1) main_thread = threading.enumerate()[0] self.assertEqual(type(main_thread), threading._MainThread) # let's not hit the network (speed up testing) with mock.patch('pywalib.PyWalib.get_balance'), \ mock.patch('pywalib.PyWalib.get_transaction_history'): # click the create account button create_account_button_id.dispatch('on_release') # after submitting the account creation thread should run self.assertEqual(len(threading.enumerate()), 2) create_account_thread = threading.enumerate()[1] self.assertEqual(type(create_account_thread), threading.Thread) self.assertEqual(create_account_thread._target.__name__, "create_account") # waits for the end of the thread create_account_thread.join() # thread has ended and the main thread is running alone again self.assertEqual(len(threading.enumerate()), 1) main_thread = threading.enumerate()[0] self.assertEqual(type(main_thread), threading._MainThread) # and verifies the account was created self.assertEqual(len(pywalib.get_account_list()), 1) # TODO verify the form fields were voided # self.assertEqual(new_password1_id.text, '') # self.assertEqual(new_password2_id.text, '') # we should get redirected to the overview page # TODO: broken in #124 # self.advance_frames(1) self.advance_frames(30) self.assertEqual(controller.screen_manager.current, 'overview') # the new account should be loaded in the controller self.assertEqual(controller.current_account, pywalib.get_account_list()[0]) # TODO: also verify the Toolbar title was updated correctly # self.assertEqual('TODO', app.controller.toolbar.title) # joins ongoing threads [t.join() for t in threading.enumerate()[1:]] # check the redirect dialog dialogs = Dialog.dialogs self.assertEqual(len(dialogs), 1) dialog = dialogs[0] self.assertEqual(dialog.title, 'Account created, redirecting...') dialog.dismiss() self.assertEqual(len(dialogs), 0)
def helper_test_create_account_form(self, app): """ Create account form validation checks. Testing both not matching and empty passwords. """ controller = app.controller pywalib = controller.pywalib # number of existing accounts before the test account_count_before = len(pywalib.get_account_list()) # TODO: use dispatch('on_release') on navigation drawer controller.load_create_new_account() self.assertEqual('Create new account', app.controller.toolbar.title) self.assertEqual(controller.screen_manager.current, 'manage_keystores') # retrieves the create_new_account widget controller = app.controller create_new_account = controller.create_new_account # retrieves widgets (password fields, sliders and buttons) new_password1_id = create_new_account.ids.new_password1_id new_password2_id = create_new_account.ids.new_password2_id create_account_button_id = \ create_new_account.ids.create_account_button_id passwords_to_try = [ # passwords not matching { 'new_password1': 'not matching1', 'new_password2': 'not matching2' }, # passwords empty { 'new_password1': '', 'new_password2': '' }, ] for password_dict in passwords_to_try: new_password1_id.text = password_dict['new_password1'] new_password2_id.text = password_dict['new_password2'] # makes the account creation fast # before clicking the create account button, # only the main thread is running self.assertEqual(len(threading.enumerate()), 1) main_thread = threading.enumerate()[0] self.assertEqual(type(main_thread), threading._MainThread) # click the create account button create_account_button_id.dispatch('on_release') # after submitting the account verification thread should run threads = threading.enumerate() # since we may run into race condition with threading.enumerate() # we make the test conditional if len(threads) == 2: create_account_thread = threading.enumerate()[1] self.assertEqual(type(create_account_thread), threading.Thread) self.assertEqual(create_account_thread._target.__name__, "create_account") # waits for the end of the thread create_account_thread.join() # the form should popup an error dialog dialogs = Dialog.dialogs self.assertEqual(len(dialogs), 1) dialog = dialogs[0] self.assertEqual(dialog.title, 'Invalid form') dialog.dismiss() self.assertEqual(len(dialogs), 0) # no account were created self.assertEqual(account_count_before, len(pywalib.get_account_list()))