diff --git a/test/appium/support/utilities.py b/test/appium/support/utilities.py new file mode 100644 index 0000000000..98a799a0c0 --- /dev/null +++ b/test/appium/support/utilities.py @@ -0,0 +1,25 @@ +def fill_string_with_char(string: str, fillchar: str, amount: int, start: bool = False, end: bool = False) -> str: + """ + :param string: input string to be formatted + :param fillchar: character to fill the original string with + :param amount: how many fillchar characters to put + :param start: allows to put fillchar at the beginning of the original string + :param end: allows to put fillchar at the ending of the original string + :return: new string formatted + + usage: + + fill_string_with_char(string="club script position", fillchar='*', amount=3) + output will be: 'club***script***position' + + fill_string_with_char(string="club script position", fillchar='*', amount=3, start=True, end=True) + output will be: '***club***script***position***' + + """ + fill_with = fillchar * amount + string_revised = fill_with.join(string.split()) + if start: + string_revised = string_revised.rjust(len(string_revised)+len(fill_with), fillchar) + if end: + string_revised = string_revised.ljust(len(string_revised)+len(fill_with), fillchar) + return string_revised diff --git a/test/appium/tests/atomic/account_management/test_recover.py b/test/appium/tests/atomic/account_management/test_recover.py index 9aab165679..6976b6fbee 100644 --- a/test/appium/tests/atomic/account_management/test_recover.py +++ b/test/appium/tests/atomic/account_management/test_recover.py @@ -1,8 +1,9 @@ import pytest +from support.utilities import fill_string_with_char from tests import marks, unique_password from tests.base_test_case import SingleDeviceTestCase -from tests.users import basic_user +from tests.users import basic_user, transaction_senders from views.sign_in_view import SignInView @@ -62,3 +63,84 @@ class TestRecoverAccountSingleDevice(SingleDeviceTestCase): sign_in = SignInView(self.driver) sign_in.recover_access(passphrase=basic_user['passphrase'], password=unique_password) sign_in.check_no_values_in_logcat(passphrase=basic_user['passphrase'], password=unique_password) + + +class TestRecoverAccessFromSignInScreen(SingleDeviceTestCase): + @marks.testrail_id(5363) + def test_pass_phrase_validation(self): + signin_view = SignInView(self.driver) + recover_access_view = signin_view.i_have_account_button.click() + phrase_outside_the_mnemonic = 'one two three four five six seven eight nine ten eleven twelve' + validations = [ + { + 'phrase': ' ', + 'element to check': recover_access_view.warnings.required_field, + 'validation message': 'Required field', + }, + { + 'phrase': 'a', + 'element to check': recover_access_view.warnings.invalid_recovery_phrase, + 'validation message': 'Recovery phrase is invalid' + }, + { + 'phrase': 'one two three four five six seven eight nine ten eleven twelve thirteen', + 'element to check': recover_access_view.warnings.invalid_recovery_phrase, + 'validation message': 'Recovery phrase is invalid' + }, + { + 'phrase': '; two three four five six seven eight nine ten eleven twelve', + 'element to check': recover_access_view.warnings.invalid_recovery_phrase, + 'validation message': 'Recovery phrase is invalid' + }, + { + 'phrase': phrase_outside_the_mnemonic, + 'element to check': recover_access_view.warnings.misspelled_words, + 'validation message': 'Some words might be misspelled' + }, + ] + + # we're performing the same steps changing only phrase per attempt + for validation in validations: + phrase, elm, msg = validation.get('phrase'), validation.get('element to check'), validation.get( + 'validation message') + if signin_view.i_have_account_button.is_element_displayed(): + signin_view.i_have_account_button.click() + recover_access_view.send_as_keyevent(phrase) + recover_access_view.password_input.click() + + if not elm.is_element_displayed(): + self.errors.append('"{}" message is not shown'.format(msg)) + recover_access_view.click_system_back_button() + + signin_view.i_have_account_button.click() + recover_access_view.send_as_keyevent(phrase_outside_the_mnemonic) + recover_access_view.password_input.click() + recover_access_view.send_as_keyevent('123456') + recover_access_view.sign_in_button.click() + recover_access_view.cancel_button.click() + + if recover_access_view.cancel_button.is_element_displayed(): + self.errors.append('Something went wrong. Probably, the confirmation pop up did not disappear') + + recover_access_view.click_system_back_button() + signin_view.i_have_account_button.click() + recover_access_view.send_as_keyevent(phrase_outside_the_mnemonic) + recover_access_view.password_input.click() + recover_access_view.send_as_keyevent('123456') + recover_access_view.sign_in_button.click() + home_view = recover_access_view.confirm_phrase_button.click() + + if not home_view.profile_button.is_element_displayed(): + self.errors.append('Something went wrong. Probably, could not reach the home screen out.') + + self.verify_no_errors() + + @marks.testrail_id(5499) + def test_passphrase_whitespaces_ignored_while_recovering_access(self): + signin_view = SignInView(self.driver) + sender = transaction_senders['U'] + passphrase = fill_string_with_char(sender['passphrase'], ' ', 3, True, True) + home_view = signin_view.recover_access(passphrase=passphrase) + + assert home_view.profile_button.is_element_displayed(), \ + 'Something went wrong. Probably, could not reach the home screen out.' diff --git a/test/appium/views/recover_access_view.py b/test/appium/views/recover_access_view.py index 99baeb1f37..cd16e49040 100644 --- a/test/appium/views/recover_access_view.py +++ b/test/appium/views/recover_access_view.py @@ -1,4 +1,4 @@ -from views.base_element import BaseEditBox, BaseButton +from views.base_element import BaseEditBox, BaseButton, BaseElement from views.sign_in_view import SignInView @@ -16,6 +16,55 @@ class ConfirmRecoverAccess(BaseButton): self.locator = self.Locator.xpath_selector("//android.widget.TextView[@text='RECOVER ACCESS']") +class RequiredField(BaseElement): + def __init__(self, driver): + super().__init__(driver) + self.locator = self.Locator.text_selector("Required field") + + +class InvalidRecoveryPhrase(BaseElement): + def __init__(self, driver): + super().__init__(driver) + self.locator = self.Locator.text_selector("Recovery phrase is invalid") + + +class TooShortPassword(BaseElement): + def __init__(self, driver): + super().__init__(driver) + self.locator = self.Locator.text_selector("Password is too short") + + +class MisspelledWords(BaseElement): + def __init__(self, driver): + super().__init__(driver) + self.locator = self.Locator.text_selector("Some words might be misspelled") + + +class Warnings(BaseElement): + def __init__(self, driver): + super().__init__(driver) + self.required_field = RequiredField(driver) + self.invalid_recovery_phrase = InvalidRecoveryPhrase(driver) + self.too_short_password = TooShortPassword(driver) + self.misspelled_words = MisspelledWords(driver) + + +class ConfirmPhraseButton(BaseButton): + def __init__(self, driver): + super().__init__(driver) + self.locator = self.Locator.id("android:id/button1") + + def navigate(self): + from views.home_view import HomeView + return HomeView(self.driver) + + +class CancelPhraseButton(BaseButton): + def __init__(self, driver): + super().__init__(driver) + self.locator = self.Locator.id("android:id/button2") + + class RecoverAccessView(SignInView): def __init__(self, driver): @@ -24,3 +73,6 @@ class RecoverAccessView(SignInView): self.passphrase_input = PassphraseInput(self.driver) self.confirm_recover_access = ConfirmRecoverAccess(self.driver) + self.warnings = Warnings(self.driver) + self.confirm_phrase_button = ConfirmPhraseButton(self.driver) + self.cancel_button = CancelPhraseButton(self.driver)